14 June 2014

Splash Page

I had an interesting query today. The query was for the possibility to have a Splash Page while the website was not announced. The functionality will be to either only redirect the Homepage to the Splash page so the http://mydomain.com will go to the SPlash Page. This would allow a content author to get the rest of the site reviewed for content and get it ready for go live. The second part of the functionality would be to hide the entire content behind the Splash Page until go live.

So here is the approach: we will use the HttpRequestBegin Pipeline to intercept the request and check on if the Splash Page is Enable and is it for the entire Site...

1 Starting with our Pipeline action

First you want to avoid applying the action to certain page and site. If the current Site is not your website then exit the action. In a similar matter, you do not want to execute the action if your request is the Splash page or you will end up with an infinite loop.
            if (Context.Item.TemplateID.ToGuid() == new Guid(TemplateIds.Pages.SplashPage))
                return;

            if (Context.Site.Name.ToLower() != Settings.GetSetting(SitecoreSettings.SiteName).ToLower())
                return;

Next, you want to resolve your homepage, site root... By the way for this exercise, the Splash Page Settings are defined in the Root Item...
            string rootPath = Context.Site.RootPath;
            var rootItem = Context.Database.GetItem(rootPath);
            if (rootItem == null)
                return;

            string homePath = string.Format("{0}/{1}", Context.Site.RootPath, Context.Site.StartItem);
            var homepage = Context.Database.GetItem(homePath);
            if (homepage == null)
                return;

Then, once you have the root item let's get the properties for the Splash Page: Enable, Splash Page Target, Enable for Entire Site
            string enableSplashPage = rootItem[FieldIds.Base.SplashPage.EnableSplashPage];
            string enableSplashPageEntireSite = rootItem[FieldIds.Base.SplashPage.EnableForEntireSite];
            string splashPage = rootItem[FieldIds.Base.SplashPage.PageLink];

Then the rest is quite simple:
namespace MyProject.Business.Sitecore.Pipelines
{
    /// 
    /// This processor will check if the current item has a Redirect field and setup correctly
    /// Redirect the user to the redirect link setup...
    /// 
    public class SplashPageRedirect : HttpRequestProcessor
    {
        public override void Process(HttpRequestArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            if (Context.Item == null || Context.Database == null || args.Url.ItemPath.Length == 0 || Context.Site == null)
                return;

            if (Context.Item.TemplateID.ToGuid() == new Guid(TemplateIds.Pages.SplashPage))
                return;

            if (Context.Site.Name.ToLower() != Settings.GetSetting(SitecoreSettings.SiteName).ToLower())
                return;

            string rootPath = Context.Site.RootPath;
            var rootItem = Context.Database.GetItem(rootPath);
            if (rootItem == null)
                return;

            string homePath = string.Format("{0}/{1}", Context.Site.RootPath, Context.Site.StartItem);
            var homepage = Context.Database.GetItem(homePath);
            if (homepage == null)
                return;

            Profiler.StartOperation("Resolve splash page Redirect item.");

            string enableSplashPage = rootItem[FieldIds.Base.SplashPage.EnableSplashPage];
            string enableSplashPageEntireSite = rootItem[FieldIds.Base.SplashPage.EnableForEntireSite];
            string splashPage = rootItem[FieldIds.Base.SplashPage.PageLink];

            if (enableSplashPage != "1")
            {
                Profiler.EndOperation();
                return;
            }

            if (!SC.Data.ID.IsID(splashPage))
            {
                Profiler.EndOperation();
                return;
            }

            if (homepage.ID.Guid == Context.Item.ID.Guid || enableSplashPageEntireSite == "1")
            {
                var newItem = Context.Database.GetItem(new SC.Data.ID(splashPage));
                if (newItem == null)
                {
                    Profiler.EndOperation();
                    return;
                }

                Context.Item = newItem;
                Profiler.EndOperation();
                return;
            }
        }
    }
}



Now we have our Pipeline action, lets hook it up with the configuration file:
      < httprequestbegin>
        < processor patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" type="MyProject.Business.Sitecore.Pipelines.SplashPageRedirect, MyProject.Business" />
      < /httprequestbegin>


Finally, just to give the idea of the fields on the Root Item:

9 June 2014

Deleting fields content on item copied

Today we were assisting content publishing on a site we built, and I have been asked to possibility to clear some fields when they were copying item. Well here is what we did:

1- Creating the class that will delete the field:

The class will be used as an handler in the On Item Copied event. Here is the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sitecore.Data.Items;
using Sitecore.Events;
using MyProject.Common.Constants;
using Sitecore.Configuration;

namespace MyProject.Business.Sitecore.Events.ItemCopied
{
    public class ClearFields
    {
        /// 
        /// Clear fields to avoid duplicate data when copying or duplicating item on Authoring
        /// 
        /// 
        /// 
        protected void OnItemCopied(object sender, EventArgs args)
        {
            if (args != null)
            {
                Item item = Event.ExtractParameter(args, 1) as Item;
                if (item == null)
                    return;
                foreach (var field in GetFieldsToClear())
                {
                    if (!string.IsNullOrEmpty(item[field]))
                    {
                        item.Editing.BeginEdit();
                        item.Fields[field].Value = "";
                        item.Editing.EndEdit();
                    }
                }
            }
        }

        private static List GetFieldsToClear()
        {
            string strFields = Settings.GetSetting(SitecoreSettings.ClearFieldsName);
            return strFields.Split('|').Select(strField => strField.Trim()).ToList();
        }
    }
}


You will notice we have stored the field names in a sitecore settings so we could add more if need to extend it later on.

2- Hook the event in the configuration file:
      < event name="item:copied">
        < handler type="MyProject.Business.Sitecore.Events.ItemCopied.ClearFields, MyProject.Business" method="OnItemCopied" />
      < /event>


Here we go, now when copying an item you will be able to clear the Rich Text Editor field, the Meta Data...