codeflood logo

Custom Tokens and NVelocity for Item Creation

We'd all be familiar with the tokens you can use in template standard values which get replaced on item creation in Sitecore. They are a great way to set some default field values based on some other data such as the name given to the item or the current date.

The following lists the tokens available in Sitecore 6.2.

  • $name: The name of the item being created
  • $id: The ID of the item being created
  • $parentid: The ID of the parent of the item being created
  • $parentname: The name of the parent of the item being created
  • $date: Date part of the current datetime in Sitecore ISO format
  • $time: Time part of the current datetime in Sitecore ISO format
  • $now: The current date in Sitecore ISO format

I remember being told during the Sitecore 5 time frame that token replacement used NVelocity. In fact, I'm sure I remember it being in the training material. Well in Sitecore 6 it doesn't appear as if it is. The tokens look like Velocity variables, but that's just coincidence.

But could I get some value from using NVelocity to process the replacements?

Firstly, let's just look at adding our own token into the replacement. It's actually quite simple. All we have to do is add a processor to the expandInitialFieldValue pipeline. So let's go ahead and create a processor which will insert the domain for the current request (which is quite commonly the same URL used to access the public site).

using Sitecore.Pipelines.ExpandInitialFieldValue;
using System.Web;

namespace CustomReplacers
{
  public class DomainReplacer : ExpandInitialFieldValueProcessor
  {
    public override void Process(ExpandInitialFieldValueArgs args)
    {
      var context = HttpContext.Current;
      if(context != null)
      {
        if (args.SourceField.Value.Contains("$domain"))
        {
          var uri = context.Request.Url;
          args.Result = args.Result.Replace("$domain", uri.Scheme +
            "://" + uri.Host);
        }
      }
    }
  }
}

And add our custom processor to the expandInitialFieldValue pipeline.

<processor type="CustomReplacers.DomainReplacer, CustomReplacers" />

Add this processor at the bottom of the pipeline below the default Sitecore processors to allow Sitecore to do it's thing before our custom processor gets involved. As with other pipeline processors you can abort a run in a processor and the expandInitialFieldValue pipeline is no exception; note the SkipStandardValueItems processor. You don't want your processor doing extra work it didn't have to.

Inside the custom processor you'll notice all the magic happens around the ExpandInitialFieldValueArgs parameter which is passed into the Process method. You have access to the source field through the SourceField property where you can grab the current value to process. We need to put our output into the Result property. But seeing as though our processor is not the first to run, we'll want to process the existing Result property, not the original field value as the previous processors may have already altered the result and if we just processed the source field value again we'd lose the processed value.

After you've adding this processor in and setup a template's standard values with the $domain token when you now create an item based on this template the token will be replaced with the current domain URL.

As you can see, adding your own tokens is pretty simple. But let's explorer the idea of using NVelocity to process the fields. We'll of course need to start with a new custom processor. This processor will use NVelocity and add the item being currently processed into the context for use.

using System.IO;
using NVelocity;
using Sitecore.Pipelines.ExpandInitialFieldValue;

namespace CustomReplacers
{
  public class VelocityProcessor : ExpandInitialFieldValueProcessor
  {
    public override void Process(ExpandInitialFieldValueArgs args)
    {
      if (args.SourceField.Value.Contains("$item"))
      {
        var context = new VelocityContext();
        context.Put("item", args.TargetItem);
        NVelocity.App.Velocity.Init();
        var output = new StringWriter();
        NVelocity.App.Velocity.Evaluate(context, output,
          "VelocityProcessor", args.Result);
        args.Result = output.GetStringBuilder().ToString();
      }
    }
  }
}

We'll of course also need to add the processor to the pipeline.

<processor type="CustomReplacers.VelocityProcessor, CustomReplacers" />

Objects you put into a velocity context are not just strings; they are real objects which you can interact with and call on their properties and methods.

Now we can do some pretty cool stuff using VTL (Velocity Template Language). Just add some of these into your template standard values.

The name of the item:

$item.Name

The path of the item:

$item.Paths.FullPath

The name of the item's grandparent:

$item.Parent.Parent.Name

The ID of an ancestor whose key is "home":

$item.Axes.SelectSingleItem("ancestor::*[@@key='home']").ID

That's right, we can use Sitecore Query in our item creation now. This is because the Item class is a very rich class which gives access to a lot of functionality. In the above Sitecore Query example I use the Axes property of the class so I can execute a Sitecore Query using the SelectSingleItem method. I could also use the SelectItems method to return an array of items. And VTL allows me to iterate over those items.

<ul>
#foreach($i in $item.Axes.SelectItems("
  ancestor::*[@@templatekey='sample item']"))
  <li>$i.Name</li>
#end
</ul>

To learn more about VTL check out the Velocity User Guide. Note that VTL used by NVelocity should follow that used by Velocity (the original Java project which NVelocity is based on).

And I should also point out an article which I stumbled upon whilst writing this article. Looks like our man Alexey Rusakov beat me to this idea way back in 2005. Check out his Velocity master variables replacer.

Comments

Anonymous

The VelocityProcessor is a great idea. But Velocity will be confused... first Sitecore removes it, almost... and then you bring it back! Poor thing.

[...] from __standard values &#8211; variables such as $name are processed when items are created. See [/blog/2009/12/28/custom-tokens-and-nvelocity-for-item-creation/](/blog/2009/12/28/custom-tokens-and-nvelocity-for-item-creation/) for info on how to create custom replacement tokens. There is also more information on [...]

[...] Deneys also wrote a good article about NVelocity here. Deneys posits Sitecore no longer uses NVelocity for token replacement. However, three years after [...]

[...] Sitecore provides tokens that you can use in standard values to default field values when an item is created (Here is a useful post about the Sitecore provided tokens as well as creating custom tokens). [...]

Leave a comment

All fields are required.