This weeks "TBB of the Week" is Get Linked Components TBB. I don't know who exactly wrote it, so I'm not taking credit for it. It is part of the Templating Base project, IIRC.
This is a very powerful TBB that I use in almost all my projects. The issue it solves is the following: whenever there a Component Link appears in Component's RTF or link field (or Page metadata), it is impossible using Dreamweaver syntax alone, to access the linked Component fields directly. Instead, this TBB should be used to place the linked Component in the Package and then access its fields.
Name
|
Get Linked Components TBB
|
Type
|
· Template in .NET Assembly
|
Description
|
Used to:
· Extract Component links from Page metadata or
from Component fields;
· Create Package items from the identified
Components;
Notes:
When placed on a Page Template, this generic TBB identifies
Component Links from the Page’s Metadata section.
When placed on a Component Template, it identifies
Component Links in the current Component’s fields (including RTF and
Component Link fields) and metadata fields.
The TBB pushes each identified Component into the Package.
|
Parameters
|
n/a
|
Applicable to
|
Component Templates and Page
Templates
|
This is a very powerful TBB that I use in almost all my projects. The issue it solves is the following: whenever there a Component Link appears in Component's RTF or link field (or Page metadata), it is impossible using Dreamweaver syntax alone, to access the linked Component fields directly. Instead, this TBB should be used to place the linked Component in the Package and then access its fields.
The Code
[TcmTemplateTitle("Get Linked Components TBB")]
public class GetLinkedComponents
: ITemplate {
private Engine
_engine = null;
private Package
_package = null;
private TemplatingLogger
_log = null;
//-1 = not set, 0 = component, 1 = page
private int
_renderContext = -1;
/// <summary>
/// Executes
the transformation
/// </summary>
/// <param name="engine">Templating engine (context for the template code)</param>
/// <param name="package">Transformation context (contains both the inputs and the
outputs of the transformation)</param>
void ITemplate.Transform(Engine engine, Package
package) {
_engine = engine;
_package = package;
_log = TemplatingLogger.GetLogger(this.GetType());
if
(IsPage) {
//Add
linked components from metadata
_log.Info("Scanning
Page Metadata for link fields...");
AddLinkedComponents(GetContextItemFields("meta"),
"MetaData.", 0);
} else
{
//Add
both linked components from standard schema and metadata fields
//_log.Info("Scanning
Component for link fields...");
AddLinkedComponents(GetContextItemFields("link"),
string.Empty, 0);
//_log.Info("Scanning
Component Metadata for link fields...");
AddLinkedComponents(GetContextItemFields("meta"),
"MetaData.", 0);
//Fix for
RenderComponentField
Item
MainComponent = _package.GetByName("Component");
_package.Remove(MainComponent);
_package.PushItem("Component", MainComponent);
}
}
/// <summary>
/// Add linked
components to the package from the given fields
/// </summary>
/// <param name="fields">The ItemFields to search for component links</param>
/// <param name="packageKeyPostfix">Postfix to add to package item name</param>
private void
AddLinkedComponents(ItemFields fields, string packageKeyPrefix, int
depth) {
if
(fields != null) {
Hashtable
itemFieldCounter = new Hashtable();
foreach
(ItemField itemField in fields) {
String
itemFieldName = itemField.Name.ToString();
if
(!itemFieldCounter.ContainsKey(itemFieldName)) {
itemFieldCounter[itemFieldName] = 0;
} else
{
itemFieldCounter[itemFieldName] = (int)itemFieldCounter[itemFieldName]
+ 1;
}
if
(itemField is ComponentLinkField)
{
ComponentLinkField
field = itemField as ComponentLinkField;
if
(depth > 0) {
_log.Info("Found 1 deep: " + field.Name);
}
if
(field != null &&
((field.Definition.MaxOccurs == 1 && field.Value != null) || field.Values != null))
{
// --------------------------
Item item = null;
if (field.Definition.MaxOccurs == 1 && field.Value != null) {
//If the field is single value, add it to the package as a
component
//_log.Info("Found single value link field: " +
field.Name);
item =
_package.CreateTridionItem(ContentType.Component,
field.Value.Id);
} else {
//Otherwise create a uri list of all values
IList<TcmUri>
uriList = new List<TcmUri>();
foreach (Component
linkedComp in field.Values) {
uriList.Add(linkedComp.Id);
}
if
(uriList.Count > 0) {
//_log.Info("Found multivalue link field: " +
field.Name);
item =
_package.CreateComponentUriListItem(ContentType.ComponentArray,
uriList);
}
}
if (item != null) {
_package.PushItem(packageKeyPrefix + field.Name, item);
}
// --------------------------
}
}
/*
*/
else
if (itemField is
EmbeddedSchemaField) {
EmbeddedSchemaField
field = itemField as EmbeddedSchemaField;
ItemFields
fieldValues = field.Values as ItemFields;
/*
* /
if
(field.Definition.MaxOccurs == 1 && field.Value != null)
{
//If the field is
single value, add it to the package as a component
//_log.Info("Found
single value Embedded field: " + field.Name + " -- " +
field.Value.ToString());
//item = _package.CreateTridionItem(ContentType.Component,
field.Value);
}
else
/* */
if
(field.Values.Count > 0) {
//Otherwise create a uri list of all values
foreach
(ItemFields linkedComp in field.Values) {
foreach (ItemField
iField in linkedComp) {
String lItemFieldName = itemFieldName + "." + iField.Name.ToString();
if
(!itemFieldCounter.ContainsKey(lItemFieldName)) {
itemFieldCounter[lItemFieldName] = 0;
} else {
itemFieldCounter[lItemFieldName] = (int)itemFieldCounter[lItemFieldName]
+ 1;
}
String newPackageKeyPrefix = packageKeyPrefix +
lItemFieldName + itemFieldCounter[lItemFieldName];
// pass the fieldValues if its not null, and go only 1 deep
//_log.Info("Possible: " + newPackageKeyPrefix);
//_log.Info("???: " + field.Values.ToString());
//_log.Info("Found object: " +
itemField.GetType().ToString());
if (iField is ComponentLinkField) {
ComponentLinkField convIField = iField as ComponentLinkField;
if
(convIField != null &&
((convIField.Definition.MaxOccurs == 1 && convIField.Value != null) || convIField.Values != null)) {
Item convItem = null;
if (convIField.Definition.MaxOccurs == 1 &&
convIField.Value != null) {
//If the field is single value, add it to the package as a
component
//_log.Info("Found single value link field: " +
field.Name);
convItem = _package.CreateTridionItem(ContentType.Component,
convIField.Value.Id);
} else {
//Otherwise create a uri list of all values
IList<TcmUri>
convUriList = new List<TcmUri>();
foreach (Component
convLinkedComp in convIField.Values) {
if
(convLinkedComp != null) {
convUriList.Add(convLinkedComp.Id);
_log.Info("Found multivalue link field:
" + convLinkedComp);
}
}
if (convUriList.Count > 0) {
convItem = _package.CreateComponentUriListItem(ContentType.ComponentArray,
convUriList);
}
}
if (convItem != null)
{
_package.PushItem(newPackageKeyPrefix,
convItem);
}
}
} else if (iField is EmbeddedSchemaField)
{
AddLinkedComponents(((EmbeddedSchemaField)iField).Value,
newPackageKeyPrefix, depth + 1);
}
}
}
}
/*
*/
} //
end else if (itemField is EmbeddedSchemaField)
else
{
//_log.Info("Found
itemField: " + itemField.Name.ToString());
}
}
}
}
/// <summary>
/// Get the
ItemFields for the context item
/// </summary>
/// <returns></returns>
private ItemFields
GetContextItemFields(string type) {
ItemFields
fields = null;
if
(IsPage) {
Item
item = _package.GetByName("Page");
if
(item != null) {
string
pid = item.GetValue("ID");
Page
page = _engine.GetObject(pid) as Page;
if
(page.Metadata != null)
fields = new ItemFields(page.Metadata,
page.MetadataSchema);
}
} else
{
Item
item = _package.GetByName("Component");
if
(item != null) {
string
cid = item.GetValue("ID");
Component
comp = _engine.GetObject(cid) as Component;
if
(type == "meta" &&
comp.Metadata != null) {
fields = new ItemFields(comp.Metadata,
comp.MetadataSchema);
} else
if (type == "link")
{
fields = new ItemFields(comp.Content,
comp.Schema);
}
}
}
return
fields;
}
/// <summary>
/// True if
the rendering context is a page, rather than component
/// </summary>
private bool
IsPage {
get {
if
(_renderContext == -1) {
if
(_engine.PublishingContext.ResolvedItem.Item is
Page)
_renderContext = 1;
else
_renderContext = 0;
}
if
(_renderContext == 1)
return
true;
else
return
false;
}
}
}
Comments