Working With Custom Hooks: OnMove_Page
Location of a Content Item within the Site Tree can have a huge impact, directly effecting things like URL structure for example. In this article we explore some ways to safeguard the integrity of your content structure with the OnMove custom hook.
There are several ways to move Content Items in the Site Tree. Perhaps the most common method is to click, drag, and drop a Content Item to a new location in the tree. When a Content Item is moved, its descendants are automatically moved along with it.
The structure or hierarchy of Content Items in the Site Tree is how URLs are constructed for content in the site. The Site Tree also defines the main navigation menus and information architecture of content in the site. So, as you can imagine, moving Content Items around can have an extreme impact. Administrators can control who is allowed to move items in the Site Tree with group permissions.
There are many reasons to take advantage of scripts in these hooks, such as updating content that is specific to a new section into which the item was placed, updating or moving related content, and preventing the movement of certain items into places they do not belong.
Users can trigger this action manually by:
- Left clicking and dragging a Site Tree Content Item to another location.
- Right clicking a Site Tree Content Item and selecting Cut from the context menu, then right clicking a new Site Tree Content Item and selecting Paste.
Considerations
Moves happen often so be as efficient as possible if you write scripts for this hook.
Consider moving larger update scripts to a manual process that can be invoked after the move or an automated task that updates content on a schedule based on CMS user downtime rather than attaching it to the move itself.
Examples
Update Section Control After Page Move
Often in website content architecture there is content that needs to be shared across a section of the site, such as navigations, banners, color schemes, and headings. These pieces of content are best placed on a component so they can be written once and reused and displayed as needed.
Schema fields on pages and components can have default content. This default content is simple, such as a string for a plain text field or a bit of static HTML for an XHTML field.
Component fields can have a default xID of a component to be automatically used as content upon creation. Anything more complex than a single ID for a single component can’t be set in the schema. Sometimes though, this is necessary in your site builds. For instance, you might have a component that an entire section of a site needs to share across all pages, or one that needs to be put into the page based on who created it. Rather than leaving this for your contributors to do manually, you could use this hook to automatically detect the scenario and place the correct component into the field upon move or creation.
The first portion of code goes into your custom hook, while the two functions should be placed after the hook end region comment in the custom hooks file.
The following example script has a few reusable functions:
- GetComponentID: Finds the field provided in the eltName argument on the item provided in the parent argument and returns the ID.
- GetSectionControlFromHeirarchy: Scans through the ancestors of the item provided in the page argument and locates the first item to have a field called Section Control by calling the GetComponent() function.
var currentSectionControl = GetComponentID(sourcePage, "SectionControl");
var parentPage = GetComponentID(targetPage, "SectionControl");
var ancestor = GetSectionControlFromHeirarchy(targetPage);
if (!string.IsNullOrWhiteSpace(currentSectionControl) && !string.IsNullOrWhiteSpace(parentPage))
{
if (currentSectionControl != parentPage)
{
if (targetPage.SchemaName != "Folder" && !targetPage.IsComponent)
{
SetElementValue(sourcePage, "SectionControl", parentPage);
sourcePage.Save();
}
if (targetPage.SchemaName == "Folder")
{
SetElementValue(sourcePage, "SectionControl", ancestor);
sourcePage.Save();
}
}
}
else
{
SetElementValue(sourcePage, "SectionControl", ancestor);
}
//Separate Section: Outside the Hook
/// <summary>
/// This method looks up the ancestor tree to see if it can find the specified element and returns its ID if found, else returns and empty string.
/// </summary>
/// <param name="page">The newly created page</param>
/// <param name="eltName">The element to be found</param>
public string GetComponentID(IPage parent, string eltName)
{
IPage current = parent;
while (current != null)
{
var elt = current.Element(eltName);
if (elt != null && !string.IsNullOrWhiteSpace(elt.Value))
{
return elt.Value;
}
current = current.Parent();
}
return "";
}
public string GetSectionControlFromHeirarchy(IPage page)
{
IPage current = page;
while (current != null)
{
var elt = current.Schema.RootName;
if(elt != "Folder")
{
var currentSectionControl = GetComponentID(current, "SectionControl");
if (!string.IsNullOrWhiteSpace(currentSectionControl))
{
return currentSectionControl;
}
else
{
current = current.Parent();
}
}
current = current.Parent();
}
return "";
}
Possible Enhancements
Pages shouldn’t be moved outside of the home page, as that will disrupt the information architecture and URL structures of the site. However, content items may be moved to a folder for archival or deletion.
The script currently will do nothing if the page’s new location after move doesn’t have an ancestor with a new section control. It could be updated to switch to a default control if there is no new ancestor to find, which could help you manage the content better for removal purposes.
There are no comments yet.