Deep Publishing Of Related Items With Sitecore Experience Editor

Problem :

Let’s assume that we have callout on our page, this callout has Image, summary and list of Links:

saveur

In Sitecore content tree, we will have folder contains this callout,  and Links as children:

callout

and we have component to display this callout and we are pointing to that callout by datasource property :

datasource

Now when we change anything on the callout item from experience editor like, title “ex:save online time”, and publish, the change will appear to the front end website, but when we change anything related to the links (callout children) under that callout “ex:Activate Tag” from experience editor and publish, the change will not appear to the front end website. If we checked that item from Sitecore content tree, we will see that item changed on Master but it is not published to web.

The reason why the DataSource subitems are not published is that items are second level references. In order to prevent huge amount of items being published, Sitecore doesn’t process references of references, so the DataSource item references are not being processed, and that is how Sitecore publishing currently works.

Solution:

  1.  Create our custom processor based on the
    Sitecore.Publishing.Pipelines.GetItemReferences.AddItemLinkReferences one (using .Net Reflector to copy the code of processor ).
  2.  Modify the GetReferences() method so that it would recursively process reference references if item is being referenced by the Renderings field (i.e. reference is a data source item).
  3.  Replace predefined processor with our custom one.

Code:

I copied the code from sitecore.kernal, my changes in red color.

public class AddItemLinkReferences : GetItemReferencesProcessor
{
private static readonly ID RenderingsFieldId = new ID("{F1A1FE9E-A60C-4DDB-A3A0-BB5B29FE732E}");
public AddItemLinkReferences()
 {
 }
 /// <summary>
 /// Gets the list of item references.
 /// </summary>
 /// <param name="context">The publish item context.</param>
 /// <returns>
 /// The list of item references.
 /// </returns>
 protected override List<Item> GetItemReferences(PublishItemContext context)
 {
 Assert.ArgumentNotNull(context, "context");
 List<Item> items = new List<Item>();
 if (context.PublishOptions.Mode != Sitecore.Publishing.PublishMode.SingleItem)
 {
 return items;
 }
 switch (context.Action)
 {
 case PublishAction.PublishSharedFields:
 {
 Item sourceItem = context.PublishHelper.GetSourceItem(context.ItemId);
 if (sourceItem == null)
 {
 return items;
 }
 items.AddRange(this.GetReferences(sourceItem, true));
 break;
 }
 case PublishAction.PublishVersion:
 {
 Item versionToPublish = context.VersionToPublish;
 if (versionToPublish == null)
 {
 return items;
 }
 items.AddRange(this.GetReferences(versionToPublish, false));
 break;
 }
 default:
 {
 return items;
 }
 }
 return items;
 }
 /// <summary>
 /// Gets the related references.
 /// </summary>
 /// <param name="item">The item.</param>
 /// <param name="sharedOnly">Determines whether to process shared fields only or not.</param>
 /// <returns>
 /// The related references.
 /// </returns>
 private IEnumerable<Item> GetReferences(Item item, bool sharedOnly)
 {
 Assert.ArgumentNotNull(item, "item");
 List<Item> items = new List<Item>();
 ItemLink[] validLinks = item.Links.GetValidLinks();
 validLinks = (
 from link in validLinks
 where item.Database.Name.Equals(link.TargetDatabaseName, StringComparison.OrdinalIgnoreCase)
 select link).ToArray<ItemLink>();
 if (sharedOnly)
 {
 validLinks = ((IEnumerable<ItemLink>)validLinks).Where<ItemLink>((ItemLink link) =>
 {
 Item sourceItem = link.GetSourceItem();
 if (sourceItem == null)
 {
 return false;
 }
 if (ID.IsNullOrEmpty(link.SourceFieldID))
 {
 return true;
 }
 return sourceItem.Fields[link.SourceFieldID].Shared;
 }).ToArray<ItemLink>();
 }
 List<Item> list = (
 from link in (IEnumerable<ItemLink>)validLinks
 select link.GetTargetItem() into relatedItem
 where relatedItem != null
 select relatedItem).ToList<Item>();
 foreach (Item item1 in list)
 {
 items.AddRange(PublishQueue.GetParents(item1));
 items.Add(item1);

// get all items childrens, if referenced by the __Renderings field.
 if (Globals.LinkDatabase.GetReferrers(item1).Any(p => p.SourceFieldID == RenderingsFieldId))
 {
 items.AddRange(item1.Axes.GetDescendants());
 }

}
 return items.Distinct<Item>(new ItemIdComparer());
 }
 }

Configuration :

In Sitecore.config, we will replace :

 <getItemReferences>
 <processor type="Sitecore.Publishing.Pipelines.GetItemReferences.AddItemCloneReferences, Sitecore.Kernel"/>
 <processor type="Sitecore.Publishing.Pipelines.GetItemReferences.AddFileDropAreaMediaReferences, Sitecore.Kernel"/>
<processor type="Sitecore.Publishing.Pipelines.GetItemReferences.AddItemLinkReferences, Sitecore.Kernel"/>
<processor type="Sitecore.Publishing.Pipelines.GetItemReferences.AddItemAliasReferences, Sitecore.Kernel"/>
 </getItemReferences>

with :

 <getItemReferences>
 <processor type="Sitecore.Publishing.Pipelines.GetItemReferences.AddItemCloneReferences, Sitecore.Kernel"/>
 <processor type="Sitecore.Publishing.Pipelines.GetItemReferences.AddFileDropAreaMediaReferences, Sitecore.Kernel"/>
 <processor type="YourWebsite.Web.Events.AddItemLinkReferences, YourWebsite.Web"/>
 <processor type="Sitecore.Publishing.Pipelines.GetItemReferences.AddItemAliasReferences, Sitecore.Kernel"/>
 </getItemReferences>

 

Advertisements

4 thoughts on “Deep Publishing Of Related Items With Sitecore Experience Editor

  1. Great post!
    After some tests I noticed that the related items were not always being published. They only get published when you’re working on the Shared Layout.
    To fix this I included the Final Rendering ID {04BF00DB-F5FB-41F7-8AB7-22408372A981} as well.

    Nele

    Liked by 1 person

    1. For me i used rendering id it was working fine, but regarding to Nele’s comment, I think he was using final rendering id instead, i believe both should work fine, and those templates can be found under : /sitecore/templates/System/Templates/Sections/Layout/Layout
      And no it’s not available as shared module.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s