This has been on my plate for a while and to be honest I’m not sure what took me so long as it literally took around 4 hours from start to completion which I consider a testament to how easy it is to create additional integrations with PowerShell akin to the Gutter integration or the login/logout integration Michael West has recently introduced in the platform.

creating_a_better_process_800_clr_7366

What this integration allows you to do is to eliminate the need for code deployment when you’re in need for a quick action here and there for when a user executes a workflow command.

You might find this article helpful by a Cognifide colleague of mine. I especially like this image which illustrates nicely where actions fit in a Sitecore workflow.

 

They are effectively little bits of code that get executed automatically when a user triggers a command.

Implementation

This couldn’t really be any simpler. All we need to do is to implement a workflow action and provide a workflow action data template that will allow us to pick a script to be executed when an item is triggered.

To do that I have Implemented the following template:

image

The Type field needs to be there for Sitecore to be able to determine which class to execute. This is however provided in the __Standard Values and you will not need to change it when using it in your code.

The Script field allows you to pick the script to execute in your action.

The EnableRule field allows you to specify additional rules for when you want the action NOT to be triggered. e.g. You might only execute it for users in some roles or only for items under some specific branch – this gives you the flexibility to customize that.

Based on the template I’ve implemented the action as following:

using System.Globalization;
using Cognifide.PowerShell.PowerShellIntegrations.Settings;
using Cognifide.PowerShell.Utility;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Text;
using Sitecore.Web.UI.Sheer;
using Sitecore.Workflows.Simple;

namespace Cognifide.PowerShell.SitecoreIntegrations.Workflows
{
    public class ScriptAction
    {
        public void Process(WorkflowPipelineArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            ProcessorItem processorItem = args.ProcessorItem;
            if (processorItem == null)
            {
                return;
            }

            // this is the action item that defines which script will be executed etc.
            Item actionItem = processorItem.InnerItem;

            // and this is the item for which the action has been triggered
            Item dataItem = args.DataItem;

            // is the script is not defined - just do nothing
            if (string.IsNullOrEmpty(actionItem["Script"]))
            {
                return;
            }

            // retrieve the scrpt item
            Item scriptItem = actionItem.Database.GetItem(new ID(actionItem[ScriptItemFieldNames.Script]));

            // make sure that rules on both the script and action are valid for this execution
            if (RulesUtils.EvaluateRules(actionItem[ScriptItemFieldNames.EnableRule], dataItem) &&
                RulesUtils.EvaluateRules(scriptItem[ScriptItemFieldNames.EnableRule], dataItem))
            {
                // pass the relevant data to the PowerShell Runner App
                var str = new UrlString(UIUtil.GetUri("control:PowerShellRunner"));
                str.Append("id", dataItem.ID.ToString());
                str.Append("db", dataItem.Database.Name);
                str.Append("lang", dataItem.Language.Name);
                str.Append("ver", dataItem.Version.Number.ToString(CultureInfo.InvariantCulture));
                str.Append("scriptId", scriptItem.ID.ToString());
                str.Append("scriptDb", scriptItem.Database.Name);
                Context.ClientPage.ClientResponse.Broadcast(
                    SheerResponse.ShowModalDialog(str.ToString(), "400", "220", "PowerShell Script Results", false),
                    "Shell");
            }
        }
    }
}

And I could immediately start using my scripted actions!

Use case

What triggered this was my need to add comments to the history table without changing the workflow state of an item. I’ve tried this by adding a command that would take me from a workflow step to the same step but ask for a comment. Unfortunately when Sitecore does not change the workflow state it does not store the comment you provide during the workflow command execution either.

Our new scripted actions can help…

A script that would do this couldn’t really be more trivial:

$item = Get-Item .
$comment = Show-Input -Prompt "Provide comment to add to history..."
if($comment -ne $null){
    New-ItemWorkflowEvent -Item $item -Text $comment
}
Close-Window

What it does is:

  • retrieve the context item and stores it in the $item variable.
  • Ask user for comment (we do it in the script as we only want to do this if the rules validate)
  • If user provided the comment – adds a new history entry for the item we are working on
  • Dismiss the PowerShell Runner window immediately after script ends – not to make user have to click "Close".

And I’ve saved the script straight under the Script Library root and named it Add Comment.

For the purpose of this I’ve created a regular “Add comment” command in the Sample Workflow and suppressed the prompt for comment as I’m doing this in the script, then added an item using our newly created PowerShell Script Workflow Action template underneath it (1), picked the script I’ve just created (2) and applied a rule that I want this action only to be triggered for items under my Home item (3).

image

Now let’s see how this behaves in action:

Given I have my item in the Avaiting Approval state, when I click the Add Comment command (1) then I will see the PowerShell runtime popup (2) and ask me for the comment to be provided (3). When I provide the comment and click OK (4) the comment will be added.

SNAGHTML6164da8

… and I can verify that that it worked immediately

SNAGHTML615e9fd

Because of the rule I have defined it will not work anywhere outside Home.

That is it, really!

This integration will be available in Sitecore PowerShell Extensions out-of-the-box in the next version (probably called 2.8.0).

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5.00 out of 5)
Loading...



This entry (Permalink) was posted on Sunday, November 9th, 2014 at 2:49 pm and is filed under Open Source, PowerShell, Sitecore, Software Development, Solution, Web applications. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response , or trackback from your own site.