LibrarySites.Banner

Add Custom Standard Values Tokens in the Sitecore ASP.NET CMS

This blog post explains how you can add tokens for Sitecore to expand when users create new items with the Sitecore ASP.NET web Content Management System (CMS).

When a user creates an item based on a data template, if the standard value for any field in that data template contains any of the following tokens, Sitecore expands those tokens as explained in this list to populate the field value in the new item:

  • $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

When a user creates an item using a branch template, Sitecore performs this standard values token substitution on the field values of that new item. If fields in the descendants of a branch template definition item contain values that override the standard values for those fields, Sitecore performs token substitution on those overriding values. Wherever the $name token appears in the name(s) of the item(s) created from a branch template, Sitecore also replaces the $name token with the name entered by the user before invoking the branch template.

When Sitecore performs such token expansion, the resulting fields no longer contain their standard value, but a concrete value after applying such expansion. Items created from branch templates that contain values in fields also override standard values for those fields, whether or not those values contain any of these tokens.

You can implement a solution based on the following untested prototype that adds a custom token for expansion:

namespace Sitecore.Sharedsource.Data
{
  using System;
  using System.Collections.Generic;
  
  using SC = Sitecore;
  
  public class MasterVariablesReplacer : SC.Data.MasterVariablesReplacer
  {
    public override string Replace(string text, SC.Data.Items.Item targetItem)
    {
      SC.Diagnostics.Assert.ArgumentNotNull(text, "text");
      SC.Diagnostics.Assert.ArgumentNotNull(targetItem, "targetItem");
      string result = this.ReplaceValues(
        text,
        () => targetItem.Name,
        () => targetItem.ID.ToString(),
        () => SC.Data.Items.ItemUtil.GetParentName(targetItem),
        () => targetItem.ParentID.ToString());
      return result;
    }
  
    private string ReplaceValues(
      string text,
      Func<string> defaultName,
      Func<string> defaultId,
      Func<string> defaultParentName,
      Func<string> defaultParentId)
    {
      if ((text.Length != 0) && (text.IndexOf('$') >= 0))
      {
        SC.Text.ReplacerContext context = this.GetContext();
  
        if (context != null)
        {
          foreach (KeyValuePair<string, string> pair in context.Values)
          {
            text = text.Replace(pair.Key, pair.Value);
          }
        }
  
        text = this.ReplaceWithDefault(text, "$name", defaultName, context);
        text = this.ReplaceWithDefault(text, "$id", defaultId, context);
        text = this.ReplaceWithDefault(text, "$parentid", defaultParentId, context);
        text = this.ReplaceWithDefault(text, "$parentname", defaultParentName, context);
        text = this.ReplaceWithDefault(text, "$date", () => SC.DateUtil.IsoNowDate, context);
        text = this.ReplaceWithDefault(text, "$time", () => SC.DateUtil.IsoNowTime, context);
        text = this.ReplaceWithDefault(text, "$now", () => SC.DateUtil.IsoNow, context);
        text = this.ReplaceWithDefault(text, "$user", () => SC.Context.User.LocalName, context);
      }
  
      return text;
    }
  
    private string ReplaceWithDefault(
      string text, 
      string variable, 
      Func<string> defaultValue, 
      SC.Text.ReplacerContext context)
    {
      if ((context != null) && context.Values.ContainsKey(variable))
      {
        return text;
      }
  
      if (text.IndexOf(variable, StringComparison.InvariantCulture) < 0)
      {
        return text;
      }
  
      return text.Replace(variable, defaultValue());
    }
  }
}

This class duplicates much of the code in the default Sitecore.Data.MasterVariableReplacer class (mainly because existing methods are private or non-virtual), but adds the $user token expansion. Use a tool such as .NET reflector to disassemble the source code for your version and then make the corresponding change to that. With this customization in place, Sitecore replaces the token $name with the name of the context user (the user that created the item) wherever that token appears in standard values for the data template or field values for the branch template used to create the item.

You can use a Web.config include file such as the following (Sitecore.Sharedsource.MasterVariableReplacer.config in my case) to enable this customization:

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

Unfortunately, replacing tokens in the names of items in branch template definitions appears to require more work (this logic may be obfuscated in Sitecore.Nexus.dll); this solution applies only to field values.

Resources