Pages

Sunday, August 17, 2008

This applies to version 5.3.x but also can be used with the latest Sitecore 6. Imagine a scenario when you have a multisite or a department-based content tree with micro-sites or department sections sharing the same data template definitions. For example, we have the “Articles” section defined in the both “US” and “France” micro-sites. The articles as items have the same set of fields, in other words, these items are created from the same data template. Also, there is an absolute requirement is to have different workflows assigned to different instances of the articles. For example, for the articles created inside of the “France” micro-site, the workflow will consist of three states and have a unique set of workflow actions and possibly different security. For the “US” articles, the whole workflow configuration will be different.

The easiest and most straightforward way to approach this will be to create a common base template for all the articles, ex. “Base Article” with the template definitions and then create two separate templates “FR Article” and “US Article” that inherit from “Base Article” and have different initial workflows assigned to the “__Standard Values” for the templates. This way the workflows will be inherited.
This approach would work fine for the described scenario with two micro-sites if the articles are the only data types that should belong to different workflows.
Now imagine if the number of the micro-sites grows to 10 and most of the content items within main sections such as Products, News, About pages, Events, Jobs, etc. should be associated with unique workflows. This basically means that you will end up with having the amount of (10 X number of content types) of data templates inheriting from the same “base” with only one differentiating initial workflow assigned on the “__Standard Values” level.
This of course becomes very difficult to maintain and begs for an alternative approach.
Obviously, in this case the data template is not a good candidate to be the carrier of the workflow definition, it is more logical to define workflow on the content section or micro-site level, for example separately for all articles, events, about pages, all content pages of the US site, etc. A good way to approach this will be to create a separate template used as base template for the items that will be carrying the workflow information. Then for example, the template of the first level items (content sections) will inherit from this template and the section items will have the workflow field (see below).
The base template:
In my example with two micro-sites I have different workflows assigned on the “Articles” section. Both items are created from the “Section” template subsequently inherited from “Base Workflow Section”. For the “France” micro-site:
For the “US” micro-site:
Note that for the “US” micro-site the articles may even be structured differently, not in the flat list. The custom workflow logic (details below) will take care of this.
The second step will be to create a common workflow with a custom action that will lookup the actual workflow on the content level basis and will do the switch. This workflow will be assigned on the “__Standard Values” for all templates that require such workflow behavior (***). Here is the “Common” workflow definition that has one final state “Done” (see notes) and a workflow action:
As you can see, there is one “Done” state and a custom action that is fired whenever a new version of the content item is created. This “DoSwitch” code is using a number of parameters to lookup the workflow definition on the content level basis and is performing the programmatic switch of the workflow. The code logic is pretty straightforward – go up the content tree and find an item which template is inherited from the one defined in the “WorkflowCarrierTemplate” parameter, then try to find a field with the ID equals to “WorkflowDefinitionFieldID”, retrieve the value of that field (the actual workflow ID that should be used) and assign the workflow and initial state field of the item dynamically. The search logic will stop whenever an item with the template equal to “HardStopItemTemplate” selection is found. It will fail if “workflow carrier” item is found or if it is found but the “WorkflowDefinition” field is not there or equals to an empty string (*).
The beauty of the approach is that is it dynamic. Since the “article”, “event”, etc. templates will still have the “Common” workflow assigned through the “__Standard Values”, the “DoSwitch” logic will be applied whenever a new version of the item is created (after approval). This means that it will be necessary to change the workflow at some point, this can be accomplished with one field change on the content level and the next version of the content item that is created will pick up the change and switch the workflow to the new one.
Also since the search logic has the fallback mechanism, once the necessity of having department based workflow is not the case anymore for certain content types, you can simply inherit the “Home” item’s template from the same “Base Workflow Section” template so it is found in the search logic. This way the “Home” item will be used as fallback workflow carrier item.
The source code of the workflow action along with the Sitecore package containing necessary items and templates can be downloaded from here.