Auto-Generating Custom Items on Save

When the Custom Item Generator (CIG) was originally built by Velir’s MVP Gabe Boys several years ago, it revolutionized how we build Sitecore sites and how we reference items. Gabe provided us with an intuitive way to access a Sitecore item’s field values through the custom item wrapper.

Though the custom item was not new to Sitecore, Gabe made it possible for us to use it within our code so we didn’t have to access an item’s field index whenever we needed a field value. He also provided us with a quick and easy way to create one, or many custom items right through the content editor.

Simple Problem

One of the downsides of working with the CIG over the course of a project is that many times as developers, we forget to recreate a custom item after we modify the template. This can cause the custom item to not properly represent its template. For example, if we change a field name from “Nav Title” to “Navigation Title”, wherever we referenced that field, it would no longer work.

Simple Solution

As the title of this blog post implies, we tapped into the “event:saved” pipeline to recreate or create a custom item automatically. This solves the problem of forgetfulness and by using nant you can make it only run on your local development environment so it is not included in the production build. As a side note, you always want to use a custom include file for these types of customizations. It makes upgrading much easier!

<events>
	<event name="item:saved">
		<handler type="Collette.Library.CustomSitecore.Events.Saved.RebuildCustomItem, Collette.Library" method="OnItemSaved" />
	</event>
</events>

The class file that is run by the save event is relatively simple. It does a series of checks to make sure we are saving a template and not something else such as content or media. It then instantiates some of the CIG’s class files to generate the code for the custom item.

That’s it! Once you implement this code you can now go into the content editor, modify a template, and see the custom item be generated for you. There is no need to manually keep the template and the custom item synced up.

Here is a link Gabe’s blog posts where he describes the CIG in more detail.  Click here

Thanks and if you have any questions please reach out! 🙂
Tim

P.S. – If you do run into any issues, you want to make sure your application pool user has access to your custom item directory.

public class RebuildCustomItem
{
	private TemplateItem Template { get; set; }

	/// <summary>
	/// Determine if we are rebuilding a custom item
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="args"></param>
	public void OnItemSaved(object sender, EventArgs args)
	{
		if (args == null)
		{
			return;
		}

		SitecoreEventArgs sitecoreArgs = args as SitecoreEventArgs;
		Assert.IsNotNull(sitecoreArgs, "eventArgs");

		SitecoreEventArgs eventArgs = args as SitecoreEventArgs;
		Assert.IsNotNull(eventArgs, "eventArgs");
		Item item = eventArgs.Parameters[0] as Item;
		Assert.IsNotNull(item, "item");
		if (item == null)
		{
			return;
		}

		if (!IsTemplateItem(item))
		{
			Log.Debug("Rebuild Custom Item - Item is not a template");
			return;
		}

		if (Template == null)
		{
			return;
		}

		try
		{
			CustomItemSettings settings = new CustomItemSettings(HttpContext.Current);
			string baseNamespace = settings.BaseNamespace;
			string baseFileOutputPath = settings.BaseFileOutputPath;

			if (string.IsNullOrEmpty(baseNamespace) || string.IsNullOrEmpty(baseFileOutputPath))
			{
				SheerResponse.Alert("CIG - You need to set your namespace or file output path in your nant settings.");
				return;
			}

			ICustomItemNamespaceProvider namespaceProvider = AssemblyUtil.GetNamespaceProvider(settings.NamespaceProvider);
			ICustomItemFolderPathProvider filePathProvider = AssemblyUtil.GetFilePathProvider(settings.FilepathProvider);

			CustomItemInformation customItemInformation = new CustomItemInformation(Template, baseNamespace, baseFileOutputPath, filePathProvider, namespaceProvider);
			CodeGenerator generator = new CodeGenerator(customItemInformation, true, false, false, false);
			generator.GenerateCode();

			Log.Debug("CIG - Created custom item for template");
			Log.Debug("Name: " + item.Name);
			Log.Debug("Id: " + item.ID);
		}
		catch (Exception e)
		{
			Log.Error("Rebuild Custom Item - Error creating custom item.", this);
			Log.Error(e.Message, this);
		}
	}

	/// <summary>
	/// Checks to see if the item is a template and in the proper directory
	/// </summary>
	/// <param name="item"></param>
	/// <returns></returns>
	public bool IsTemplateItem(Item item)
	{
		bool inTemplateDirectory = item.Paths.FullPath.ToLower().StartsWith("/sitecore/templates/collette/", StringComparison.OrdinalIgnoreCase);
		if (!inTemplateDirectory)
		{
			return false;
		}

		//if we are on a template field, walk up
		if (item.TemplateID.ToString() == Sitecore.TemplateIDs.TemplateField.ToString())
		{
			Template = item.GetAncestor(Sitecore.TemplateIDs.Template.ToString());
			return true;
		}

		//verify we are on a template item
		if (item.TemplateID.ToString() == Sitecore.TemplateIDs.Template.ToString())
		{
			Template = item;
			return true;
		}

		return false;
	}
}

One thought on “Auto-Generating Custom Items on Save

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s