Typically I see this breadcrumb being generated in the front-end from the Sitemap, which is not a very expensive operation but still a very silly approach. If an editor creates a page in a given Structure Group and publishes it, we already know the page's location at publish time, so why would we waste some CPU cycles on the front-end determining this?
Since I had to write this Building Block just now I thought I could share it with you.
using System.Text.RegularExpressions;
using System.Xml;
using Tridion.ContentManager;
using Tridion.ContentManager.CommunicationManagement;
using Tridion.ContentManager.ContentManagement;
using Tridion.ContentManager.Templating;
using Tridion.ContentManager.Templating.Assembly;
namespace TridionTemplates
{
public class GetPageBreadcrumb : ITemplate
{
private const string _separator = " » ";
private const string RegexPattern = @"^[\d]* ";
private const string indexPagePattern = "index";
private readonly Regex _regex = new Regex(RegexPattern, RegexOptions.None);
public void Transform(Engine engine, Package package)
{
TemplatingLogger log = TemplatingLogger.GetLogger(GetType());
if (package.GetByName(Package.PageName) == null)
{
log.Info("Do not use this template building block in Component Templates");
return;
}
Page page = (Page)engine.GetObject(package.GetByName(Package.PageName));
string output = StripNumbersFromTitle(page.OrganizationalItem.Title);
foreach (OrganizationalItem parent in page.OrganizationalItem.GetAncestors())
{
output = GetLinkToSgIndexPage((StructureGroup)parent, engine.GetSession()) + _separator + output;
}
package.PushItem("breadcrumb", package.CreateStringItem(ContentType.Html, output));
}
private string StripNumbersFromTitle(string title)
{
return Regex.Replace(title, RegexPattern, string.Empty);
}
private string GetLinkToSgIndexPage(StructureGroup sg, Session session)
{
OrganizationalItemItemsFilter filter = new OrganizationalItemItemsFilter(session);
filter.ItemTypes = new[] { ItemType.Page };
string title = StripNumbersFromTitle(sg.Title);
string pageLinkFormat = "<a tridion:href=\"{0}\">{1}</a>";
string result = null;
foreach (XmlElement page in sg.GetListItems(filter).ChildNodes)
{
if (page.Attributes["Title"].Value.ToLower().Contains(indexPagePattern))
{
result = string.Format(pageLinkFormat, page.Attributes["ID"].Value, title);
break;
}
}
if (string.IsNullOrEmpty(result))
{
result = title;
}
return result;
}
}
}
Yes, it does quite a lot more than just create a breadcrumb, I'll leave it up to you figure that out :)
PS - I am using OrganizationalItem.GetAncestors() in this code, which means it will only work with SDL Tridion 2011 SP1.
1 comment:
Nice way of looking for index pages.
If you want to use it on older versions, you can do something like:
StructureGroup parent = page.OrganizationalItem as StructureGroup;
while (parent != null)
{
output = ... + output;
parent = parent.OrganizationalItem as StructureGroup;
}
Post a Comment