Friday, November 4, 2022

Sitecore Branch template to create page with datasource structure

 The following code augments the functionality of Branch Templates by making any rendering data sources set in the layout on the branch that points to the newly created branch items.

This allows for templating including data source items using branches.


public class AddFromBranchPreset : AddFromTemplateProcessor

{

public override void Process(AddFromTemplateArgs args)

{

Assert.ArgumentNotNull(args, nameof(args));


if (AddFromTemplatePresetDisabler.IsActive)

{

return;

}


if (args.Destination.Database.Name != "master") return;


var templateItem = args.Destination.Database.GetItem(args.TemplateId);


Assert.IsNotNull(templateItem, "Template did not exist!");


// if this isn't a branch template, we can use the stock behavior

if (templateItem.TemplateID != TemplateIDs.BranchTemplate) return;


Assert.HasAccess((args.Destination.Access.CanCreate() ? 1 : 0) != 0, "AddFromTemplate - Add access required (destination: {0}, template: {1})", args.Destination.ID, args.TemplateId);


// Create the branch template instance

var newItem = args.Destination.Database.Engines.DataEngine.AddFromTemplate(args.ItemName, args.TemplateId, args.Destination, args.NewId);


// find all rendering data sources on the branch root item that points to an item under the branch template,

// and repoint them to the equivalent subitem under the branch instance

RewriteBranchRenderingDataSources(newItem, templateItem, newItem.Paths.FullPath);


args.Result = newItem;

}


protected virtual void RewriteBranchRenderingDataSources(Item item, BranchItem branchTemplateItem, string branchRoot)

{

var branchBasePath = branchTemplateItem.InnerItem.Paths.FullPath;


LayoutHelper.ApplyActionToAllRenderings(item, rendering =>

{

if (string.IsNullOrWhiteSpace(rendering.Datasource))

return RenderingActionResult.None;


// note: queries and multiple item datasources are not supported

var renderingTargetItem = item.Database.GetItem(rendering.Datasource);


if (renderingTargetItem == null)

Log.Warn("Error while expanding branch template rendering datasources: data source {0} was not resolvable.".FormatWith(rendering.Datasource), this);


// if there was no valid target item OR the target item is not a child of the branch template we skip out

if (renderingTargetItem == null || !renderingTargetItem.Paths.FullPath.StartsWith(branchBasePath, StringComparison.OrdinalIgnoreCase))

return RenderingActionResult.None;


var relativeRenderingPath = renderingTargetItem.Paths.FullPath.Substring(branchBasePath.Length).TrimStart('/');

relativeRenderingPath = relativeRenderingPath.Substring(relativeRenderingPath.IndexOf('/')); // we need to skip the "/$name" at the root of the branch children


var newTargetPath = item.Paths.FullPath + relativeRenderingPath;


var newTargetItem = item.Database.GetItem(newTargetPath);


// if the target item was valid under branch item, but the same relative path does not exist under the branch instance

// we set the datasource to something invalid to avoid any potential unintentional edits of a shared data source item

if (newTargetItem == null)

{

rendering.Datasource = "INVALID_BRANCH_SUBITEM_ID";

return RenderingActionResult.None;

}


rendering.Datasource = newTargetItem.ID.ToString();

return RenderingActionResult.None;

});


if (!item.HasChildren) return;

item.Children.ToList().ForEach(x => RewriteBranchRenderingDataSources(x, branchTemplateItem, branchRoot));

}

}

No comments:

Post a Comment

How to Create a Public Link Using the Sitecore Content Hub REST API

Creating a public link using the Sitecore Content Hub REST API is a straightforward process that enables you to share content externally whi...