Today, I procrastinated on doing chores around the house by exploring whether one could chain together Sitecore client commands in order to reduce the number of clicks and/or keypresses required when invoking these commands separately — combining the click of the ‘Save’ button followed by one of the publishing buttons would be an example of this.
Immediately, the composite design pattern came to mind for a candidate solution — you can read more about this pattern in the the Gang of Four’s book on design patterns.
This high-level plan of attack lead to the following custom composite command.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using Sitecore.Configuration; using Sitecore.Diagnostics; using Sitecore.Shell.Framework.Commands; using Sitecore.Text; namespace Sitecore.Sandbox.Commands { public class CompositeCommand : Command { public override void Execute(CommandContext commandContext) { IEnumerable<Command> commands = GetCommands(); foreach (Command command in commands) { command.Execute(commandContext); } } protected IEnumerable<Command> GetCommands() { ListString commandNames = GetCommandNames(); IList<Command> commands = new List<Command>(); foreach(string commandName in commandNames) { AddToListIfNotNull(commands, CommandManager.GetCommand(commandName)); } return commands; } private ListString GetCommandNames() { return new ListString(GetCommandsFieldValue(), '|'); } private string GetCommandsFieldValue() { XmlNode xmlNode = Factory.GetConfigNode(string.Format("commands/command[@name='{0}']", Name)); bool canGetCommands = xmlNode != null && xmlNode.Attributes["commands"] != null; if (canGetCommands) { return xmlNode.Attributes["commands"].Value; } return string.Empty; } private static void AddToListIfNotNull<T>(IList<T> list, T objectToAdd) where T : class { Assert.ArgumentNotNull(list, "list"); if (objectToAdd != null) { list.Add(objectToAdd); } } } }
The above command — using the Sitecore.Configuration.Factory class — gets its XML configuration element; parses the list of commands it wraps from a new attribute I’ve added — I’ve named this attribute “commands”; gets instances of these commands via Sitecore.Shell.Framework.Commands.CommandManager (from Sitecore.Kernel.dll); and invokes all Command instances’ Execute() methods consecutively — ordered from left to right, separated by pipes, in the “commands” attribute on the command XML element in /App_Config/Commands.config.
To test this out, I thought I’d create a composite command combining the item save command with the publish command — the command that launches the Publish Item Wizard.
I first had to wire up my new command by adding a new command XML element to /App_Config/Commands.config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <!-- bunch of commands up here --> <command name="composite:savethenpublish" commands="contenteditor:save|item:publish" type="Sitecore.Sandbox.Commands.CompositeCommand,Sitecore.Sandbox"/> </configuration>
Next, in the core db, I had to create a reference under the home strip:
Followed by a chunk containing a button that holds the name of our new command:
Let’s see this new composite command in action. I did the following:
After the Sitecore save animation completed, the Publish Item Wizard popped up:
Now, it’s time for some fun. Let’s combine commands that make little sense in chaining together.
Let’s chain together:
- the command I built in my post on expanding Standard Values tokens
- the command to move an item before all its siblings in the content tree
- the command to move an item down in the content tree
Here’s what the command’s configuration looks like in /App_Config/Commands.config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <!-- bunch of commands up here --> <command name="composite:chainsomeunrelatedcommands" commands="item:expandtokens|item:movefirst|item:movedown" type="Sitecore.Sandbox.Commands.CompositeCommand,Sitecore.Sandbox"/> </configuration>
I decided to add this to the item context menu — for more information on adding to the context menu for items, please check out my post that shows you how to do this — so I created new menu option in the context menu for items in the core database:
I switched back to the master database; added some Standard Values tokens to some fields in the Page 4 item I created for testing; right-clicked on on it; and clicked my new context menu option:
After a second or two, I saw that the tokens were expanded, and the item was moved:
That’s all for now. It’s now time to go do some house chores. Otherwise, people might start thinking I’m truly addicted to building things in Sitecore. 🙂
[…] IDTable Entries Across Multiple Sitecore Databases Using a Composite IDTableProvider and Chain Together Sitecore Client Commands using a Composite Command — I used the Composite design pattern to chain together functionality in two or more classes […]
[…] decided to revisit a post I wrote over two years ago on chaining together client commands — these are invoked via the […]