Sunday, February 5, 2012

Clones, Versions, and Shared Fields

In Sitecore's release notes for 6.4.1 build 3 (110720), there's an interesting, if somewhat cryptic, announcement:
Clones are now treated as a whole instead of version-by-version, meaning that all versions on the cloned item must refer to the same source item. It is no longer supported that different versions on the cloned item point to different source items or that some versions on a clone do not refer to any source item. This restriction removes potential confusion about which items clones are referencing, and ensures that the value of shared fields is well-defined. If any existing clones in a solution reference different source items, the behavior of shared fields is undefined for these clones.
So, what does this mean? It's clear why shared fields could be a thorny issue for clones.  Unlike a proxy, which is a  copy of the original item in all regards except ID and path, the clone is an independent item with special  rules for the interpretation of null fields.

The Problem
The connection between a clone and its source is defined through the "__Source" field.  Basically, when the source field points to another item, Sitecore uses this item, rather than Standard Values, to pull default values for fields. The problem is that "__Source" is a versioned field, so there is nothing to prevent different versions of a clone from pointing to different objects, or having one version be uncloned.

This breaks the expected behavior of shared fields, which are supposed to be the same across all versions of an item.  If CloneA has two versions, and version 1 points to Item1, while version 2 points to Item2, then clearly the shared fields of item 1 and 2 can diverge.  So is Sitecore's statement an announcement of new functionality, a warning that this sort of thing is not "officially supported", or a mixture of the two?

Some Experiments
To get a better handle on this, I did a number of tests with sandbox environments of 6.4.1-build 1 (110324) and 6.4.1-build 5 (111003)

Uncloning:  There is no change in functionality here.  If you have a multiversioned item, and you click unclone, only the currently selected item is uncloned.  The __Source value stays populated for the other versions.  If a shared field, such as "context menu," is updated in the original item, this will carry through to the cloned version only.

Languages: What happens when you add a language?  I created a clone of Our-Process, and then added a language (Fr-fr) to the original of Site-Audit.  This generated a notification on the clone, which I accepted to create a clone of the French item.  Next, I clicked unclone on this item, which again only uncloned this version, leaving the English clone intact.

Separate Source Items:  The only way to bring this about is to manually change the __Source field.  I added a version, and changed the __Source.  Neither version of Sitecore complained, and the "Created From" field in Quick Info showed the different source items.

What has changed?
So as far as the mechanics of creating versions, adding languages, and uncloning, nothing has changed.  What has changed, however, is the behavior of shared fields in some of these contexts.  Before build 3, the value of a shared field depends on the currently active version.  After build 3, Sitecore appears to use the new item property "Item.SharedFieldsSource" to access shared fields.   However, this behavior is not consistent between mulit-language and multi-version scenarios.

Some More Experiments
The icon field is shared, and is rendered by the Content Editor at the top of the Content tab, so it is a logical field to test.

Let's look at a multi-language scenario in build 5:
1. Create an item, change the icon, and add a language.  When prompted, add a version for this language.
2. Create a clone of this item.
3.  Unclone one of the languages.
4.  Reset the icon.
5.  Even though the current language is uncloned, the field that was reset will revert to the source value, not the standard value, and the icon will be consistent across languages of the half-clone.  In build 1, the icon would change depending on which language was selected.

However, with multiple versions in a single language, the behavior is different:
1.  Create an item, change the icon.
2.  Clone the item.
3.  Add a version to the clone.
4.  Unclone the second version.
5.  Reset the icon on the second version.
6. The icon changes depending on which item is selected, breaking the expected behavior of a shared field. This behavior is the same in build 5 and build 1.

The effort to enforce the expected behavior of shared fields makes sense, but Sitecore is not yet there.  The behavior should be consistent regardless of whether the scenario involves languages or version numbers.  Moreover, it does not seem reasonable that Sitecore does not support mixing cloned and uncloned versions of an item if this is the way that the "Unclone" button works.   Mixed clones are also required by the "auto-unclone" behavior that occurs when an item is deleted: you would not want to force a clone to become a non-clone simply because one of the source item languages or versions is removed.  So we, and Sitecore, are stuck with half-clones.  Rather than saying they are not supported, I recommend Sitecore work out deterministic behavior for these scenarios so that the value of a shared field is defined in all cases.  And of course, "unversioned" fields (i.e., shared by all versions in a language) need to be similarly defined.


  1. I would separate source ID from source version. ID should be shared - that would make cloning consistent - all versions should point to the same item and all versions are either cloned or not cloned. Each version should point it's source version, but from the same source item.

  2. Basically, when the source field points to another item, Sitecore uses this item, rather than Standard Values, to pull default values for fields.