3

This is an old issue, and it was resolved in our old 8.2 instance by a prior dev but after upgrading to 9.0 the issue has reappeared. When a user copies or duplicates an item, all of the local components that are children of that item are copied, but the datasources of the renderings on the copied parent item all point to the original local components rather than the new ones.

For example:

  • Duplicate /sitecore/content/Example with name Example2
  • Example2 is successfully created, as well as /sitecore/content/Example2/local components and /sitecore/content/Example2/local components/RichText
  • However, the Rich Text rendering on Example2 has a datasource of /sitecore/content/Example/local components/RichText instead of /sitecore/content/Example2/local components/RichText

I've been trying to find solutions but all of the posts I've found are really old and reference blogs that no longer seem to exist. Is there a patch for this, or any current blogs that explain how to fix this?

2
  • 1
    Does the Smart Commands module provide any insight into how this problem can be solved? github.com/AlenPelin/Sitecore-Smart-Commands Jul 4, 2019 at 2:27
  • I don't think this is an issue, Sitecore works in this way. if you want to do something like this, you may need to write your custom code for event or command. As @MichaelWest suggested you can use Sitecore smart commands module Jul 4, 2019 at 13:26

2 Answers 2

3

It's not an out of the box feature, however there is a way to do this. Check out this blog post for the details. http://byteium.com/2019/02/update-rendering-datasources-on-item-copy You want to test to see if the item at the relative path exists, and if it does, you might assume that it's safe to set it as the copied items rendering datasource.

1
  • any powershell version of it ? Mar 1, 2023 at 9:59
1

I needed to make a few updates to the linked post due to some limitations:

  • Added ability to copy shared layout along with the final layout
  • Added ability to copy to different folders
  • Added setting to specify path of local data source folder
protected void UpdateRenderingDatasources(Item copy, Item source, string localFolder)
        {
            ID[] layoutFieldIDs = new ID[]
            {
                Sitecore.FieldIDs.LayoutField,
                Sitecore.FieldIDs.FinalLayoutField
            };

            foreach (var layoutFieldID in layoutFieldIDs)
            {
                LayoutField layoutField = new LayoutField(copy.Fields[layoutFieldID]);
                LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value);

                foreach (DeviceDefinition device in layoutDefinition.Devices)
                {
                    if (device.Renderings != null)
                    {
                        for (var i = 0; i < device.Renderings.Count; i++)
                        {
                            RenderingDefinition rendering = (RenderingDefinition)device.Renderings[i];
                            if (!string.IsNullOrWhiteSpace(rendering.Datasource))
                            {
                                var guid = rendering.Datasource;
                                var datasourceItem = GetItem(new ID(guid));
                                if (datasourceItem != null)
                                {
                                    if (isLocal(source, datasourceItem, localFolder))
                                    {
                                        var localPath = datasourceItem.Paths.Path.Replace(source.Paths.Path, "");
                                        var path = copy.Paths.Path + localPath;
                                        var newPathItem = GetItem(path);

                                        if (newPathItem != null)
                                        {
                                            rendering.Datasource = newPathItem.ID.ToString();
                                            copy.Editing.BeginEdit();
                                            layoutField.Value = layoutDefinition.ToXml();
                                            copy.Editing.EndEdit();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private bool isLocal(Item source, Item datasourceItem, string localFolder)
        {
            var sourceUri = (source.Paths.Path + "/" + localFolder).ToLower();
            var dataSourceUri = datasourceItem.Paths.Path.ToLower();
            return dataSourceUri.Contains(sourceUri);
        }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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