Sitecore CMS - Handling Item copying where DataSources are referenced inside the copied structure, to inserted in the Item:Copied event queue.
/// <summary> | |
/// Class used to update Spot Context Data, when copying trees in Sitecore. | |
/// </summary> | |
public class LayoutDataSourceReferenceUpdater | |
{ | |
#region Properties | |
/// <summary> | |
/// Gets or sets the new root Item (source item). | |
/// </summary> | |
/// <value>The new root Item.</value> | |
public Item NewRoot | |
{ | |
get; | |
set; | |
} | |
/// <summary> | |
/// Gets or sets the original root Item (destination item). | |
/// </summary> | |
/// <value>The original root Item.</value> | |
public Item OriginalRoot | |
{ | |
get; | |
set; | |
} | |
#endregion Properties | |
#region Methods | |
/// <summary> | |
/// Updates the references using <see cref="OriginalRoot"/> and <see cref="NewRoot"/>. | |
/// </summary> | |
/// <param name="parameters">The parameters.</param> | |
public void UpdateReferences(object[] parameters) | |
{ | |
Assert.IsNotNull(OriginalRoot, "OriginalRoot cannot be null"); | |
Assert.IsNotNull(NewRoot, "NewRoot cannot be null"); | |
UpdateTree(OriginalRoot); | |
} | |
/// <summary> | |
/// Finds the corresponding item using <see cref="OriginalRoot"/> and <see cref="NewRoot"/>. | |
/// </summary> | |
/// <param name="itemBeingCopied">The item being copied.</param> | |
/// <returns></returns> | |
private Item FindCorrespondingItem(Item itemBeingCopied) | |
{ | |
if (!itemBeingCopied.Axes.IsDescendantOf(OriginalRoot)) | |
{ | |
return null; | |
} | |
string relativePath = itemBeingCopied.Paths.FullPath.Substring(OriginalRoot.Paths.FullPath.Length); | |
string newItemPath = String.Concat(NewRoot.Paths.FullPath, relativePath); | |
return NewRoot.Database.GetItem(newItemPath, itemBeingCopied.Language, itemBeingCopied.Version); | |
} | |
/// <summary> | |
/// Updates the items Context fields to point to correct references. | |
/// </summary> | |
/// <param name="itemBeingCopied">The item being copied.</param> | |
private void UpdateItemFields(Item itemBeingCopied) | |
{ | |
LayoutField layoutField = new LayoutField(itemBeingCopied.Fields[Sitecore.FieldIDs.LayoutField]); | |
if (layoutField.InnerField.HasValue && itemBeingCopied.Languages.Count() > 0) | |
{ | |
Item newItem = FindCorrespondingItem(itemBeingCopied); | |
if (newItem == null) | |
{ | |
Log.Warn(String.Format("Unable to find corresponding item for copied item {0} - root {1}.", itemBeingCopied.Paths.FullPath, OriginalRoot.Paths.FullPath), this); | |
return; | |
} | |
foreach (Language language in itemBeingCopied.Languages) | |
{ | |
Item versionedItem = itemBeingCopied.Database.GetItem(itemBeingCopied.ID, language, | |
itemBeingCopied.Version); | |
if (versionedItem != null && versionedItem.Versions.Count > 0) | |
{ | |
foreach (var itemVersion in versionedItem.Versions.GetVersions()) | |
{ | |
if (itemVersion != null) | |
{ | |
// Loop all datasources, if sources is child tree FindCorrespondingItem and replace | |
layoutField = new LayoutField(itemVersion.Fields[Sitecore.FieldIDs.LayoutField]); | |
if (!layoutField.InnerField.HasValue) | |
{ | |
continue; | |
} | |
var rawLayout = itemVersion.Fields[Sitecore.FieldIDs.LayoutField].Value; | |
if (string.IsNullOrWhiteSpace(layoutField.Value)) | |
{ | |
continue; | |
} | |
LayoutDefinition layout = LayoutDefinition.Parse(layoutField.Value); | |
for (int i = 0; i < layout.Devices.Count; i++) | |
{ | |
DeviceDefinition device = layout.Devices[i] as DeviceDefinition; | |
for (int j = 0; j < device.Renderings.Count; j++) | |
{ | |
RenderingDefinition rendering = device.Renderings[j] as RenderingDefinition; | |
if (!string.IsNullOrEmpty(rendering.Datasource)) | |
{ | |
Item datasourceItem = itemVersion.Database.GetItem(rendering.Datasource); | |
if (datasourceItem == null) | |
{ | |
Log.Warn(string.Format("Could not find datasource item {0} while copying item {1}", rendering.Datasource, itemVersion.ID), this); | |
continue; | |
} | |
// Exit if datasource is not a descendend of the item being copied | |
if (!datasourceItem.Axes.IsDescendantOf(itemBeingCopied)) | |
{ | |
continue; | |
} | |
// Find new datasource if it is not under path of parent | |
Item correspondingItem = FindCorrespondingItem(datasourceItem); | |
if (correspondingItem == null) | |
{ | |
Log.Warn(string.Format("Could not find datasource target item {0} while copying item {1}", rendering.Datasource, itemVersion.ID), this); | |
continue; | |
} | |
rawLayout = rawLayout.Replace(datasourceItem.ID.ToString(), | |
correspondingItem.ID.ToString()); | |
} | |
} | |
} | |
// Replace Layout field on new item | |
newItem = itemVersion.Database.GetItem(newItem.ID, itemVersion.Language, | |
itemVersion.Version); | |
if (rawLayout != newItem.Fields[Sitecore.FieldIDs.LayoutField].Value) | |
{ | |
// Save updated layout information | |
newItem.Editing.BeginEdit(); | |
newItem.Fields[Sitecore.FieldIDs.LayoutField].Value = rawLayout; | |
newItem.Editing.EndEdit(); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Updates a tree in Sitecore (fixes all references in the tree). | |
/// </summary> | |
/// <param name="root">The root Item.</param> | |
private void UpdateTree(Item root) | |
{ | |
UpdateItemFields(root); | |
foreach (Item child in root.GetChildren(ChildListOptions.None)) | |
{ | |
UpdateTree(child); | |
} | |
} | |
/// <summary> | |
/// Called when the item copied event runs. Will update the Context references contained in the copied tree structure. | |
/// </summary> | |
/// <param name="sender">The sender.</param> | |
/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param> | |
protected void OnItemCopied(object sender, EventArgs args) | |
{ | |
Item itemThatWasCopied = Event.ExtractParameter(args, 0) as Item; | |
Item itemRootCreatedByCopy = Event.ExtractParameter(args, 1) as Item; | |
Error.AssertNotNull(itemThatWasCopied, "No sourceItem in parameters"); | |
Error.AssertNotNull(itemRootCreatedByCopy, "No targetItem in parameters"); | |
LayoutDataSourceReferenceUpdater updater = new LayoutDataSourceReferenceUpdater | |
{ | |
NewRoot = itemRootCreatedByCopy, | |
OriginalRoot = itemThatWasCopied | |
}; | |
ProgressBox.Execute( | |
Sitecore.Globalization.Translate.Text("Updating context references"), | |
Sitecore.Globalization.Translate.Text("Updating context references"), | |
"Applications/16x16/form_blue.png", | |
new ProgressBoxMethod(updater.UpdateReferences), | |
new object[] | |
{ | |
Event.ExtractParameter(args, 0), | |
Event.ExtractParameter(args, 1) | |
}); | |
} | |
#endregion Methods | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment