You may
have items such as news, publication, blog, events etc. that contain date field.
Its great
to show these items according to datewise so that each item should place in
"YYYY > MMM > dd" path. This type of content
structure is good to locate the item quickly.
Whenever
content editor creates such item with specified date and save the item, our job
is to fire an event to move that item in the respective date folder. If date
folder is not exist then it should be created automatically and move the item
into that.
In below
image there are two year folders - 2017 and 2018. I am adding new item "Test
News Article 111" and selected its date as "12-Feb-2016".
When I click on save button, my event automatically created folders 2016, February
and 12 and moved the item under that.
Moving news item to datewise folder automatically |
Implementation Details
Create 3 template
items in Sitecore for Year, Month and Date at path “/sitecore/templates/Project/Common/Content
Types” as below
Name – Year Folder
Template - /sitecore/templates/System/Templates/Template
Icon - Business/32x32/calendar.png
Name – Month Folder
Template - /sitecore/templates/System/Templates/Template
Icon - Business/32x32/calendar_31.png
Name – Day Folder
Template - /sitecore/templates/System/Templates/Template
Icon - Business/32x32/calendar_7.png
Create constant
to specify different news items details as
namespace Sitecore.Foundation.SitecoreExtensions
{
using Sitecore.Data;
public struct Constants
{
public struct DateWiseStructure
{
public static readonly ID NewsArticleTemplateID = new ID("{B69277AD-E917-4B9F-9136-A12E0A3E462F}");
public static readonly ID NewsArticleParentID = new ID("{FBF578DE-0640-43CF-91C1-492ECD093BC4}");
public static readonly string NewsDateFieldName = "NewsDate";
public static readonly ID YearFolderItemTemplateID = new ID("{B64C595D-FE20-44B1-96CC-38F292730437}");
public static readonly ID MonthFolderItemTemplateID = new ID("{F1183F76-17AC-4DF3-877C-85726A16EECA}");
public static readonly ID DayFolderItemTemplateID = new ID("{A443C72F-8A0B-4816-BCEF-D537905A7331}");
}
}
}
To
implement such functionality, we need to write below code for Save event
using Sitecore.Collections;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Data.Managers;
using Sitecore.Globalization;
using Sitecore.SecurityModel;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sitecore.Foundation.SitecoreExtensions.Extensions
{
/// <summary>
/// Save Event to create folder struture datewise in Sitecore content
tree
/// </summary>
public class ItemSaveEventHandler
{
/// <summary>
/// Check language version is exist for the item
/// </summary>
/// <param name="item"></param>
/// <param name="contextLanguage"></param>
/// <param name="database"></param>
/// <returns></returns>
public bool
HasGivenLanguageVersion(Item item, Language contextLanguage, Database database)
{
try
{
if (item != null
&& item.Languages != null && contextLanguage != null)
{
Item languageSpecificItem =
database.GetItem(item.ID, contextLanguage);
if (languageSpecificItem != null &&
languageSpecificItem.Versions.Count > 0)
{
return true;
}
}
}
catch (Exception ex)
{
Sitecore.Diagnostics.Log.Error("Error while checking language version of item " + item.ID + " Error is " + ex, typeof(BasicUtil));
}
return false;
}
/// <summary>
/// Save Event method to create folder struture datewise in Sitecore
content tree
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
public void OnItemSaved(object sender,
EventArgs args)
{
if (args == null ||
Sitecore.Context.Site.Name.ToLower().Equals("publisher")) return;
Item itemToOrganize =
Sitecore.Events.Event.ExtractParameter(args, 0) as Item;
if(itemToOrganize == null || itemToOrganize.Name.ToLower().Equals("__standard values") ||
!itemToOrganize.TemplateID.Equals(Constants.DateWiseStructure.NewsArticleTemplateID))
{
return;
}
Item parentOfTypeAutosave = null;
Database master =
Sitecore.Configuration.Factory.GetDatabase("master");
parentOfTypeAutosave =
SitecoreUtil.GetItem(Constants.DateWiseStructure.NewsArticleParentID, master);
if (parentOfTypeAutosave == null || BasicUtil.IsOfTypeFolder(itemToOrganize)) return;
string dateFld = string.Empty;
ID dayFolderTemplateID;
if (itemToOrganize.TemplateID.Equals(Constants.DateWiseStructure.NewsArticleTemplateID))
{
dateFld =
Constants.DateWiseStructure.NewsDateFieldName;
dayFolderTemplateID =
Constants.DateWiseStructure.DayFolderItemTemplateID; //Day Folder Template ID
}
else
{
return;
}
Item _currentYearItem = null;
Item _currentMonthItem = null;
Item _currentDayItem = null;
bool _yearFolderExist = false;
bool _monthFolderExist = false;
bool _dayFolderExist = false;
DateTime date =
((DateField)itemToOrganize.Fields[dateFld]).DateTime.Date;
LanguageCollection languages =
LanguageManager.GetLanguages(master);
Item langItem = null;
DateTime langDate =
DateTime.MinValue;
if (date == DateTime.MinValue)
{
foreach (Language language in languages)
{
if (HasGivenLanguageVersion(itemToOrganize,
language, master))
{
langItem =
master.GetItem(itemToOrganize.ID, language);
langDate =
((DateField)langItem.Fields[dateFld]).DateTime.Date;
if (langDate != DateTime.MinValue
&& date < langDate)
{
date = langDate;
}
}
}
}
List<Item> yearItems =
parentOfTypeAutosave.Children.Where(
x =>
x.TemplateID.Equals(Constants.DateWiseStructure.YearFolderItemTemplateID)
&& x.Name.Equals(date.ToString("yyyy"))).ToList();
if (yearItems.Any())
{
_yearFolderExist = true;
_currentYearItem =
yearItems.First();
List<Item> monthItems =
_currentYearItem.Children.Where(x =>
x.TemplateID.Equals(Constants.DateWiseStructure.MonthFolderItemTemplateID)
&&
x.Name.ToLower().Equals(date.ToString("MMMM").ToLower())).ToList();
if (monthItems.Any())
{
_monthFolderExist = true;
_currentMonthItem =
monthItems.First();
List<Item> dayItems =
_currentMonthItem.Children.Where(x =>
x.TemplateID.Equals(dayFolderTemplateID) &&
x.Name.Equals(date.ToString("%d"))).ToList();
if (dayItems.Any())
{
_dayFolderExist = true;
_currentDayItem =
dayItems.First();
}
else
{
_dayFolderExist = false;
}
}
else
{
_monthFolderExist = false;
}
}
else
{
_yearFolderExist = false;
}
if (!_yearFolderExist)
{
using (new
SecurityDisabler())
{
TemplateID yearTemplateId =
new
TemplateID(Constants.DateWiseStructure.YearFolderItemTemplateID);
_currentYearItem =
parentOfTypeAutosave.Add(date.ToString("yyyy"), yearTemplateId);
}
}
if (!_monthFolderExist)
{
using (new
SecurityDisabler())
{
TemplateID monthTemplateId
= new
TemplateID(Constants.DateWiseStructure.MonthFolderItemTemplateID);
_currentMonthItem =
_currentYearItem.Add(date.ToString("MMMM"), monthTemplateId);
}
}
if (!_dayFolderExist)
{
using (new
SecurityDisabler())
{
TemplateID dayTemplateId = new TemplateID(dayFolderTemplateID);
_currentDayItem =
_currentMonthItem.Add(date.ToString("%d"), dayTemplateId);
}
}
if (itemToOrganize.Parent.Name.Equals(_currentDayItem.Name)
&&
itemToOrganize.Parent.Parent.Name.Equals(_currentMonthItem.Name)
&&
itemToOrganize.Parent.Parent.Parent.Name.Equals(_currentYearItem.Name)) return;
using (new
SecurityDisabler())
{
itemToOrganize.MoveTo(_currentDayItem);
}
}
}
}
Create custom
config file to register this event as
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<events>
<event name="item:saved">
<handler type="Sitecore.Foundation.SitecoreExtensions.Extensions.ItemSaveEventHandler,Sitecore.Foundation.SitecoreExtensions" method="OnItemSaved"/>
</event>
</events>
</sitecore>
</configuration>
That’s it.
Now
whenever you are creating any such news item, it will move to correct date
folder.
Note :- If you have not specified
any value in date fields then that item will move to 0001 > 01 > 01
folder.
I hope you
enjoy this Sitecore article. Stay tuned for more Sitecore related articles.
Till that happy
Sitecoring :)
Please leave your
comments or share this article if it’s useful for you.