Contact Us

One differentiating factor between “hobby” CMSs and Enterprise level CMSs is often the level of customization one can apply to the CMS in question. Sitecore is a very flexible Content Management System (CMS) and one of the Altudo's primary platforms for implementing websites for clients. One aspect of Sitecore I really like is the level of flexibility I am granted through the system.

This flexibility comes in handy when trying to meet client requirements. Different organizations have different ways of working, so being able to customize an out-of-the-box process is fantastic. To quote Sitecore CTO John West from his previous post around Sitecore Differentiating Factors Blog Series: Extensibility

Because no CMS can provide every feature that every organization requires, it is important that each customer can enhance the CMS with the custom functionality they need.

Sitecore provides a great deal of flexibility in the configuration and topology of the production environment. It is quite common to have multiple servers delivering content in the production environment and separate the content delivery servers from the content authoring servers. This kind of topology provides additional content workflow features to authors, allowing them to publish content within the content authoring environment so it can be viewed and approved by non-CMS users (such as a manager or other senior member of staff) before publishing the content to the public. In this kind of topology, the authoring server is also acting as a “staging” environment.

To facilitate this kind of setup Sitecore includes a feature called “Publishing Targets”. Publishing Targets are listed in the publishing wizard dialog so an author can select which environment the content will be published to.

The issue with the default publishing model in Sitecore is that there is no enforcement to ensure content flows through the appropriate environments before being published. In the scenario given above where we have separated the content authoring server from the content delivery servers, within the publishing wizard dialog there are no checks to ensure content must be published to the content authoring server (staging environment) and checked before it can be published to the public.

But luckily, thanks to Sitecore’s extensibility and flexibility we have many options for implementing such a requirement.

Let’s start by defining what it is we want to achieve:

As a content publisher, I want to ensure content that is published to production has already been published to staging and been approved to allow review by non-CMS users within the organization.

Below is a list of several options to assist in meeting this requirement. All options below assume you’ve already followed the guidance in Sitecore’s Scaling Guide document available on the Sitecore Developer Network to set up your publishing targets.

Need Help?

Set default publishing targets

Sitecore contains a setting in the configuration for defining which publishing targets should be selected by default. The publishing targets will be selected in the publishing wizard dialog every time it opens. Even if the user unchecked the publishing target to deselect it when next the dialog opens the publishing target will be selected again.

The following configuration patch file can be dropped into the App_Config\Include folder of the authoring Sitecore instance to have the publishing target named staging selected by default every time the dialog opens.

Sitecore publishing target 1

The biggest issue with this option is that users can easily uncheck the default publishing targets. This option acts as a reminder rather than a verification of publication.

Use an event handler to verify items being published

Sitecore defines many events which are fired in response to various system actions taking place. One such event is the publish:itemProcessing event which is fired for each item during a publishing operation. We can write an event handler, which is custom code, to respond to this event and abort the publication of the current item if that same item doesn’t exist in the staging database (used by the staging environment). The following prototype code shows how this event handler might be created.

Sitecore publishing target 2

Sitecore publishing target 3

Sitecore publishing target 4

The above code first performs some checks to ensure the handler should operate on the item being published as this may be a publish from master to staging for which this handler has no interest. If the handler should run and all prerequisite data can be found then a comparison is done between the item from the source database and the item in the staging database, comparing the revision fields of the items. Sitecore automatically assigns a new GUID to the revision field of an item every time it is saved, so you can be sure if separate instances of an item have different revision values the items cannot be the same.

To subscribe the above event handler to the publish:itemProcessing event use the following configuration patch file which should be deployed to the App_Config\Include folder.

Sitecore publishing target 5

One point to note about the above prototype is the order in which the publishing targets are defined. The publishing process will process the publishing targets in the order that they appear in this dialog, which follows the content order of the publishing target definition items under /sitecore/system/Publishing targets. Make sure your staging publishing target is sorted before the internet publishing target otherwise you’ll end up in a situation where within a single publishing operation Sitecore is trying to publish items to internet before staging and the custom event handler above is failing publication of items to internet because they haven’t yet been published to staging, even though they’re about to be.

Customize the publish dialog to select and disable the staging publishing target

This option entails overriding the Sitecore publish wizard dialog UI with our own implementation to select the desired publishing targets in code, then disable the publishing target checkbox so users cannot uncheck the publishing target.

The publishing wizard dialog in Sitecore is implemented using Sitecore's SheerUI, so the dialog itself is defined in an XML file which can be easily overridden.

The following prototype code shows how to extend the default Sitecore publish dialog box implementation class and programmatically select the publishing target then disable the control.

Sitecore publishing target 6

The default dialog implementation contains a method for populating the publishing targets called GetPublishingTargets(). This would have been an ideal method to override but unfortunately the method is private, static and non-virtual.

Rather than trying to identify a method further up in the call chain that makes use of the GetPublishingTargets() method and rewriting all the logic contained within these methods it’s much easier to intercept before the response is returned to the user and make the required updated to the UI components, as is being done above. The sample code overrides the OnPreRender() method which is called just before the response is returned.

By inspecting the generated markup of the default publishing dialog, we can ascertain the format of the control ID for the checkbox we want to alter. This requires the ID of the publishing target definition item. Once we’ve found the checkbox control in the dialog we can select it and disable it.

Now we have to update the Publish dialog XML to reference the above custom form class instead of the default implementation.

Sitecore provides a facility to override any of the SheerUI controls it uses without editing the original file. This makes future updates much easier. If we updated the original file then a future update to that file would remove our customizations. By using the override facility, our customization will remain even if the original file is updated.

To override the publish dialog, we simply copy the existing XML file which describes the dialog UI from sitecore\shell\Applications\Dialogs\Publish\Publish.xml to sitecore\shell\override\Publish.xml. Any XML file which appears in this location will replace any default XML file that defines the same control ID (first child element name of the control element inside the XML file). We need to update the dialog to use our implementation class instead of the default class.

Locate the following line in the XML file:

Sitecore publishing target 7

And change it to reference our custom implementation class:

Sitecore publishing target 8

Now when we open the publishing wizard and proceed to the publishing target selection tab the staging publishing target will be selected and disabled.As with the previous option, take note of the publishing target order. You will need to ensure your publishing target definition items are sorted correctly to ensure the staging target is first on the list.

Conclusion

Several options were explored above to ensure content is published to the content staging server before it’s published to the world. The appropriate option for you would depend on your situation. Do you want a gentle reminder (option 1) or do you need to ensure content simply cannot be published to production without first passing through staging no matter what (option 2)?

Of the options presented I think option 2 is the best as it ensures the requirement at the data level and doesn’t rely on UI tweaks.

Altudo in partnership with Sitecore is fully committed to enable brands across verticals to woo their customers across all channels by creating exceptional customer experiences with 1:1 personalized content.

Check out our capabilities to know more about how we enable brands to build Revenue Engine using Sitecore.

If you have Sitecore implemented as your CMS and are looking to build a mobile application for Omnichannel CX, drop us a line at marketing@altudo.co