Scenario
Assume that you have a set of items (say..Product items) (sitting anywhere within the /sitecore/content..) based on a specific template. The requirement here is that
"A Product cannot be published if one of its fields (ProductID) isn't populated."
Background
To achieve this, we need to hook into the publish:itemProcessing event in the web.config. This event gets triggered every time an item is published. The general steps involved in this situation are:
- Create a class with a method that adheres to the EventHandler delegate signature. Whenever you initiate a publish operation in sitecore (be it smart publish, incremental or full publish), the method will be called (depending on how many items that need to be published)
- Modify the web.config to subscribe to ItemPublishing event
ItemPublisher Class
namespace Test.Events
{
public class ItemPublisher
{
public void CheckProcessing(object sender, EventArgs args)
{
ItemProcessingEventArgs theArgs = args as ItemProcessingEventArgs;
Item currentItem = theArgs.Context.PublishHelper.GetSourceItem(theArgs.Context.ItemId);
if ((currentItem != null) && (currentItem.Paths.IsContentItem))
{
//Template ID of item on which selective publishing is to be applied
if (currentItem.TemplateID == new ID("{9C9A2F3D-652A-4490-AB57-E9F1B4D5BF05}"))
{
Job currentJob = theArgs.Context.Job;
JobStatus currentJobStatus = currentJob.Status;
if (String.IsNullOrEmpty((currentItem.Fields["Product ID"].Value)))
{
currentJobStatus.Messages.Add(String.Format("Item :{0} has not been published since it has no Product ID", currentItem.Name));
theArgs.Cancel = true;
return;
}
}
}
}
}
}
Line 7: Cast the standard EventArgs class to ItemProcessingEvent. This is important since it gives you the possibility of retrieving details of the items being published.
Line 9: Retrieve the item being published.
Line 11: The check for "currentItem.Paths.IsContentItem" is important since we only want to check for content items. Since publishable items sitecore vary from templates,standard values, renderings... we do not want to check for the condition in ALL items.
Line 14: If the template of the current item matches the id of the Product template, then we're back in business.
Line 16 - 21: Find the reference to the current Job (and JobStatus) being executed in the publish pipeline. If the item's field is empty, add a message to the JobStatus.
Line 22: Abort the publish operation of the current item. I don't think we require the return statement after that. Publishing will then resume for the next item in the publishing queue.
Web.Config Change
Locate the publish:itemProcessing event in the web.config. Hook up the new handler to the event.
<event name="publish:itemProcessing"
help="Receives an argument of type ItemProcessingEventArgs (namespace: Sitecore.Publishing.Pipelines.PublishItem)" >
<handler type="Test.Events.ItemPublisher,TestApplication" method="CheckProcessing" />
</event>
Let's put it to the test
That's all to it really. If you now initiate a publish operation and one of the Products has an emtpy Product ID, you will end up with this (if you click on "Click here to see additional information" on the last screen of the publish wizard.)
Items Skipped = 1 (.i.e Camera item has been skipped during the publish process since it has no ProductID). If you switch to the web database, there will not be any "Camera" item.
Result... :)