Make your own custom Standard Values tokens in Sitecore

StandardValuesHeader

I just love Sitecores’s Standard Values. They allows you to set default values on an item when it’s created. There are some really nice posts explaining the basics of Standard Values. Please read John West’s post – ALL ABOUT STANDARD VALUES IN THE SITECORE ASP.NET CMS and Jens Mikkelsen’s post – Standard Values in Sitecore

A very cool thing in Standard Values is the tokens. You just enter a token in the field on the standard values and then it will be replaced with an other value when the item is created. The tokens you can use are:

  • $name: The name for the new item entered by the user
  • $id: The ID of the new item
  • $parentid: The ID of the parent of the new item
  • $parentname: The name of the parent of the new item
  • $date: The system date in yyyyMMdd format
  • $time: The system time in HHmmss format
  • $now: The system date and time in yyyyMMddTHHmmss format

But would it not be nice if you could do your own custom tokens? I found some very nice posts about that subject:
John WestADD CUSTOM STANDARD VALUES TOKENS IN THE SITECORE ASP.NET CMS
Mike ReynoldsContent Manage Custom Standard Values Tokens in the Sitecore Client

While working with the PushBroker Manager I needed to get a value from an ancestor item and put it in a descendant item when it was created. In this case I wanted to know what market campaign(DMS) was selected in the campaign item
PushBrokerManagerCampaignArrow
and put it in the “Query Parameters” field in the message item.
PushBrokerManagerMessageArrow

Shorting it down – I need to get values from an ancestor item and put them in a descendant item when it is created. I want to do it by using custom tokens.

The custom tokens will be defined in Sitecore so I did a StandardValue Variable item:
StandardValueFolder

And here is the template:
StandardValueTemplate

  • StandardValueVariableToken: The token
  • StandardValueVariableAncestorOrParentFieldName: The field from the parent/ancestor item
  • StandardValueVariableAncestorOrParentFieldId: The field from the parent/ancestor item
  • StandardValueVariableAncestorOrParentItemTemplateName: The template from the parent/ancestor item
  • StandardValueVariableAncestorOrParentItemTemplateId: The template from the parent/ancestor item
  • StandardValueVariableSourceItemFieldName: The field from the source item in the parent/ancestor item selected from a Droplink, Multilist or a Treelist
  • StandardValueVariableSourceItemFieldId: The field from the source item in the parent/ancestor item selected from a Droplink, Multilist or a Treelist
  • StandardValueVariableSourceItemTemplateName: The template from the source item in the parent/ancestor item selected from a Droplink, Multilist or a Treelist
  • StandardValueVariableSourceItemTemplateId: The template from the source item in the parent/ancestor item selected from a Droplink, Multilist or a Treelist

Next thing to do will be to put the custom tokens in a repository class.

public class StandardValueVariableRepository
{
    public static StandardValueVariable Get(Item item)
    {
        if (item == null || !item.IsDerived(Constants.Templates.StandardValueVariable))
            return null;

        return StandardValueVariableFactory.Create(item);
    }


    public static StandardValueVariable Get(ID itemId, Language language)
    {
        return Get(SitecoreItemRepository.Get(itemId, language));

    }

    public static IEnumerable<StandardValueVariable> Collection(Language language)
    {
        Item standardValueVariablesFolderItem =
            SitecoreItemRepository.Get(Constants.Items.StandardValueVariablesFolder, language);

        return standardValueVariablesFolderItem.GetChildren().Select(Get);
    }

}

Here is is the factory class.

internal class StandardValueVariableFactory
{
    internal static StandardValueVariable Create(Item item)
    {
        return new StandardValueVariable()
        {
            Id = item.ID.ToString(),
            Token = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableToken),
            AncestorOrParentTemplateName = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableAncestorOrParentItemTemplateName),
            AncestorOrParentTemplateId = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableAncestorOrParentItemTemplateId),
            AncestorOrParentFieldName = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableAncestorOrParentFieldName),
            AncestorOrParentFieldId = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableAncestorOrParentFieldId),
            SourceTemplateName = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableSourceItemTemplateName),
            SourceTemplateId = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableSourceItemTemplateId),
            SourceFieldId = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableSourceItemFieldId),
            SourceFieldName = item.GetString(Constants.Fields.StandardValueVariable.StandardValueVariableSourceItemFieldName)
        };
    }
}

And the model:

public class StandardValueVariable
{
    public string Id { get; set; }
        
    public string Token { get; set; }

    public string AncestorOrParentTemplateName { get; set; }

    public string AncestorOrParentTemplateId { get; set; }

    public string AncestorOrParentFieldName { get; set; }

    public string AncestorOrParentFieldId { get; set; }

    public string SourceTemplateName { get; set; }

    public string SourceTemplateId { get; set; }

    public string SourceFieldName { get; set; }

    public string SourceFieldId { get; set; }
}

The actual “replacing” happens in the class Sitecore.Data.MasterVariablesReplacer which means I need to replace it with my own class but I don’t want to interfere with the standard tokens from Sitecore.

public class CustomTokensMasterVariablesReplacer : MasterVariablesReplacer
{

    private List<StandardValueVariable> _standardValueVariables;

    private IEnumerable<StandardValueVariable> StandardValueVariables
    {
        get
        {
            if (_standardValueVariables != null)
                return _standardValueVariables;

            _standardValueVariables = StandardValueVariableRepository.Collection(Sitecore.Context.Language).ToList();

            return _standardValueVariables;
        }
    }

    public override string Replace(string text, Item targetItem)
    {

        return GetReplacedCustomTokenValue(text, targetItem);

    }


    private string GetReplacedCustomTokenValue(string tokenText, Item targetItem)
    {
        string replacedText = base.Replace(tokenText, targetItem);

        if (replacedText != tokenText)
            return replacedText;

        foreach (StandardValueVariable standardValueVariable in StandardValueVariables)
        {
            if (standardValueVariable == null)
                continue;

            if (string.IsNullOrWhiteSpace(standardValueVariable.Token))
                continue;

            if (!tokenText.Contains(standardValueVariable.Token))
                continue;

            if (string.IsNullOrWhiteSpace(standardValueVariable.AncestorOrParentTemplateId) && string.IsNullOrWhiteSpace(standardValueVariable.AncestorOrParentTemplateName))
                continue;

            if (string.IsNullOrWhiteSpace(standardValueVariable.AncestorOrParentFieldName) && string.IsNullOrWhiteSpace(standardValueVariable.AncestorOrParentFieldId))
                continue;

            if (string.IsNullOrWhiteSpace(standardValueVariable.AncestorOrParentTemplateId))
                continue;

            Item ancestorItem = targetItem.GetAncestors()
                .FirstOrDefault(item => item.IsDerived(new ID(standardValueVariable.AncestorOrParentTemplateId)));

            if (ancestorItem == null)
                continue;

            if (string.IsNullOrWhiteSpace(standardValueVariable.SourceTemplateId) &&
                string.IsNullOrWhiteSpace(standardValueVariable.SourceFieldId))
            {
                return ancestorItem.GetString(new ID(standardValueVariable.AncestorOrParentFieldId));
            }

            //This is for treelist, droplink or multilist
            Item sourceItem = ancestorItem.GetItemValues(new ID(standardValueVariable.AncestorOrParentFieldId)).FirstOrDefault();

            if (sourceItem == null)
                continue;

            //Checking if it's a campaign(DMS). I was going crazy trying to get the value from an iframe field. 
            //Instead I just took the the campaign id... 
            if (sourceItem.IsDerived(Constants.Templates.AnalyticsCampaign) && standardValueVariable.SourceFieldId == Constants.Fields.AnalyticsCampaign.CampaignLink.ToString())
                return string.Format("sc_camp={0}", sourceItem.ID.ToShortID());

            if (!string.IsNullOrWhiteSpace(standardValueVariable.SourceFieldId))
                return sourceItem.GetString(new ID(standardValueVariable.SourceFieldId));
        }


        return string.Empty;

    }

}

I inherit the Sitecore.Data.MasterVariablesReplacer and override method Replace(This is where the replacing of tokens is done).
In GetReplacedCustomTokenValue I use the base.Replace from the inherited class to get the “replaced value”. If the “replaced value” is the same as the token text it means that “the replacing” was not successful. In other words – here is a custom token.

Next thing will be to iterate through the custom tokens(StandardValue Variable items), find the correct one and from it’s settings together with targetItem return the “replaced value”. That’s it 🙂

Oh I almost forgot, here is the patch config file.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <settings>
      <setting name="MasterVariablesReplacer">
        <patch:attribute name="value">Sitecore.Sharedsource.CustomTokensMasterVariablesReplacer,Sitecore.Sharedsource</patch:attribute>
      </setting>
    </settings>
  </sitecore>
</configuration>

That’s all for now folks 🙂


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.