12

When you create items based on a branch template, those items will contain a copy of the content, renderings etc. of the branch at the time the items were created - any changes applied to the branch template, once the items have been created, will not automatically appear on the created items.

Assuming that I want to update all the previously created items, with any new changes found in the branch template since the item creation (including sub-items, renderings etc.), what would be the best strategy for doing so? The strategy should take into account that renderings that might have been added previously, but later removed by a content editor, should not be re-added back to the item. Preferably, the update strategy functionality should be something that is executable from within the content editor in Sitecore.

  • 1
    Branch templates should be used to organize structure, not content. If you find yourself needing to update a bunch of content in a single location, you should probably be using references to shared content, rather than a bunch of items with duplicate content. – zzzzBov Sep 20 '16 at 13:35
3

I know that this is an old post, but I was looking through and just wanted to add some information to help anyone who is actually still hoping to implement similar behavior to this.

At a high-level, @MarkCassidy is correct that there is no OOTB mechanism for what you are describing. However, you could achieve a limited version of this functionality by leveraging eventing or the item provider pipelines, combined with a little extra logic.

Lingo

  • Branch = Branch
  • Implementor = subtree created from branch
  • Corresponding Item = item in implementor that corresponds to item in branch
  • Corresponding Field = field of corresponding item in implementor corresponding to field of item in branch

Functionality to Implement

Before we start coding, let's consider the functionality that we can and plan to implement:

  • Item in branch has field or presentation change -> change applied to corresponding item in implementors of the branch
  • If corresponding item doesn't exist in implementor then no action is taken
  • If a field is changed and the original value of the field does not match the value of the corresponding field in the implementor then no action is taken (do not overwrite changes)
  • Item renames should not be applied to implementors

The above logic includes both the Renderings and Final Renderings fields (Shared Layout and Final Layout), so long as no changes have been made to either.

For simplicity, we will skip the following enhancements, but they could be added with limited additional effort:

  • Field comparison supports token resolution (e.g. $name)
  • Deleted item support (would require an additional event-handler; see below for more)
  • Rendering property change detected by reviewing content of deltas
  • Comparison of deltas in corresponding item to allow applying changes even after corresponding item's presentation details have been changed (this one would likely take more than a little effort, but it is still doable, with limitations)

Calling our Logic

Before we get into specifics, let's figure out how we will be calling this logic. For starters, we know that we want the logic to run when a branch template is "changed." We can detect that a branch template has "changed" by listening for when the branch template item or one of its descendants has been saved. However, note that it is possible that the branch template or one of its descendants will be saved without any actual changes. This extra call to our logic should not result in any side-effects.

Listening for Changes

Now that we know that we want to listen for the branch items or one of its descendants to be saved, we can pick the "listening" mechanism. This is a crucial step, as the information that we have about the item being changed will vary based on the mechanism that we choose. For example, the item:saved event will show us the changed item, but we won't be able to compare it with its previous state (i.e. before it was changed).

There is really only one good candidate for listening mechanisms in this case: the item:saving event.

The item:saving Event

The item:saving event has been around for a long time and its use is fairly well-documented online. The item:saving event is viable for our use-case because while one of its parameters is an updated "copy" of the item being saved (i.e. an item that looks like the unmodified item, except that it has all of the changes that were made and are being saved), yet the changes haven't actually been saved. This means that we have access to both of the following:

  • The "updated item", and thus the changes, by looking at the item retrieved from the event's parameters
  • The unmodified item, and thus a point of comparison, by retrieving the item from the database using the same ID as the "updated item" (remember that the updated item hasn't been saved yet)

While this is all well and good, there are two major drawbacks of using the item:saving handler for our use-case:

  • In order to get the unmodified item for comparison, we need to retrieve the item from the database by performing an extra item-get (yuck, but not the end of the world)
  • In order to actually see the changes that were made, all of the fields of the updated item will need to be compared with the unmodified item and any that differ can be considered "modified" (BIG yuck!)

The good news, is that - as previously mentioned - using this event has been pretty well-documented and should be pretty straightforward.

The only change that this handler will not support is if an item is deleted/archived. In this case, we would need to add an additional handler to support accounting for those changes. Once our initial logic is written, that extra handler will be pretty straightforward, so I will skip that functionality for the purpose of this post.

The Code/Logic

Obviously, this is a pretty complex piece of functionality, so I'm not actually going to code it here (being lazy :P), but I will walk you through the high-level of what you will want to do:

  1. Set up your event handler to run the rest of your logic and configure it to fire on item:saving.
  2. When hit, handler first checks to see if the item is or is part of a branch template and returns if it is not
  3. Retrieve the unmodified version of the item from the database and compare the fields to create a Dictionary<KeyValuePair<string, string>, string> with the KeyValuePair<FieldName, OriginalValue> as a key and ModifiedValue as the value. This will be the changesDictionary If the populated changesDictionary is empty, then return.
  4. Find all of the items created from that item's branch (links database, content search, etc)
  5. For each of the returned items, select the corresponding item to the item in the branch that was changed. If the corresponding item is missing, return null
  6. Filter out null items from the list (i.e. filter out implementors that are missing the corresponding item)
  7. For each Key in the changesDictionary iterate through the remaining items and if the value of the Key.Key field (corresponding field) is the same as the Key.Value (unmodified branch field value) then update the field to the changesDictionary[Key] (modified value) inside of an EventDisabler (for performance reasons; not to avoid side-effects)

While this will work, there is a fairly large risk of performance degradation when saving branch items. Fortunately, this isn't something that happens often after initial development.

22

There isn't a way - really. Not an out-of-the-box one, anyway.

To achieve it; Sitecore would need to record a delta of item changes - which it doesn't. Remove a rendering - Sitecore removes it; but leaves no paper trail of the event.

What you're asking for is akin to what Item Clones does - except that it does not keep track of an entire item structure, and is not related to Branch templates in any way.

You're left with a few options.

  • Update renderings via Standard Values. But it will not be limited to items created on the basis of your branch.
  • Script it. Like using Sitecore Powershell Extensions.
  • Code it. Hook into item:copy events and so on - like Alen Pelin's Smart Commands - and do the rendering and content delta yourself. Not easy, mind you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.