4

How to implement this with in Workflow - "In the workflow when the approver has approved the item then it should be scheduled for future publishing date say tommorrow 8pm. Is there any API method that we can use with in workflow Code to achieve this ?

1 Answer 1

6

I have some code which does something similar. Our requirement was the scheduled item to stay in workflow until the Publish time so that users could still change it and cancel it without going to the publish Q. We achive this by finishing an activity which reads the next activities Due Date from a filed in the component. Here is our example.

namespace UrbanCherry.Net.SDLTridion.Workflow
{
    public class ScheduleForPublish : ExternalActivity
    {
        /// <summary>
        ///
        /// </summary>
        protected override void Execute()
        {
            Utilities util = new Utilities(CoreServiceClient, ActivityInstance);
            string publishDateFieldSource = util.GetActivityParamValue("PublishDateFieldSource");//could be data or metadata
            string publishDateXPath = util.GetActivityParamValue("PublishDateXPath");

            ComponentData workflowItem = (ComponentData)CoreServiceClient.Read(ActivityInstance.WorkItems[0].Subject.IdRef + "-v0", new ReadOptions());

            XDocument sourceXml = new XDocument();
            if (publishDateFieldSource == "data")
            {
                sourceXml = XDocument.Parse(workflowItem.Content);
            }else
            {
                sourceXml = XDocument.Parse(workflowItem.Metadata);
            }


            ActivityFinishData finishData = new ActivityFinishData
            {
                //NextActivityDueDate = publishTime,
                Message = "Placing in Publishing Override Queue for default period, because no date or time was set, or it was in the past",
                NextActivityTitle = "Holding for default publish delay"
            };

            XElement dateElement = sourceXml.XPathSelectElement(publishDateXPath);

            if (dateElement != null)
            {
                DateTime enteredDateTime = DateTime.Parse(dateElement.Value);
                if (enteredDateTime > DateTime.Now)
                {
                    //publishTime = enteredDateTime;
                    finishData.Message = "Placing in Publishing Override Queue until:"  + enteredDateTime;
                    finishData.NextActivityDueDate = enteredDateTime;
                    finishData.NextActivityTitle = "Holding for future publishing";
                }
            }


            CoreServiceClient.FinishActivity(ActivityInstance.Id, finishData, new ReadOptions());

        }
    }
}

This will trigger the "Holding for Publish" activity to expire (and then run the expiration script which follows)

using Tridion.ContentManager.CoreService.Client;
using Tridion.ContentManager.CoreService.Workflow;


namespace UrbanCherry.Net.SDLTridion.Workflow
{
    public class PublishingExpirationHandler : ExternalActivity
    {
        /// <summary>
        /// This Expiration script should be to automatically finish a manual activity that expires
        /// the script will read what activity to assign to, and finish the current activity
        /// </summary>
        protected override void Expire()
        {
            //Create a Utility Class
            Utilities util = new Utilities(CoreServiceClient, ActivityInstance);
            string expirationActivity = util.GetActivityParamValue("ExpirationActivityName", Utilities.ScriptType.Expiration);

            string uriNextActivity = util.GetActivityURI(expirationActivity, ProcessInstance.ProcessDefinition.IdRef);
            DecisionActivityFinishData decisionActivityFinishData = new DecisionActivityFinishData
            {
                NextActivity = new LinkToActivityDefinitionData { IdRef = uriNextActivity },
                Message = "Released for publishing by workflow at " + DateTime.Now
            };

            CoreServiceClient.FinishActivity(ActivityInstance.Id, decisionActivityFinishData, null);

        }
    }


}

This then allows the final workflow activity to actually publish the item using code a bit like this

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tridion.ContentManager.CoreService.Client;
using Tridion.ContentManager.CoreService.Workflow;


namespace UrbanCherry.Net.SDLTridion.Workflow
{
    public class Publish : ExternalActivity
    {
        /// <summary>
        ///
        /// </summary>
        protected override void Execute()
        {
            Utilities util = new Utilities(CoreServiceClient, ActivityInstance);
            string targetTypeName = util.GetActivityParamValue("TargetTypeName");

            ActivityFinishData finishData = new ActivityFinishData
            {

                Message = "Items placed in the queue for publishing"

            };
            CoreServiceClient.FinishActivity(ActivityInstance.Id, finishData, new ReadOptions());
            util.PublishToTargetType(new string[] { ActivityInstance.WorkItems[0].Subject.IdRef }, targetTypeName);
        }
    }
}


public void PublishToTargetType(string[] publishItems, string TargetTypeName, PublishDirection direction = PublishDirection.Publish)
    {
        string uriTargetType = null;

        TargetTypesFilterData filter = new TargetTypesFilterData();

        IdentifiableObjectData[] targetTypes = _client.GetSystemWideList(filter);
        foreach (IdentifiableObjectData targetType in targetTypes)
        {
            if (targetType.Title == TargetTypeName)
            {
                uriTargetType = targetType.Id;
            }
        }

        if (!string.IsNullOrEmpty(uriTargetType))
        {
            string[] targets = new String[] { uriTargetType };

            RenderInstructionData renderInstruction = new RenderInstructionData();
            ResolveInstructionData resolveInstruction = new ResolveInstructionData();

            if (direction == PublishDirection.UnPublish)
            {
                UnPublishInstructionData unpublishInstruction = new UnPublishInstructionData
                {
                    ResolveInstruction = resolveInstruction,
                    RollbackOnFailure = false,
                    StartAt = DateTime.Now
                };
                _client.UnPublish(publishItems, unpublishInstruction, targets, PublishPriority.High, new ReadOptions());
            }
            else
            {

                PublishInstructionData publishInstruction = new PublishInstructionData
                {
                    DeployAt = DateTime.Now,
                    MaximumNumberOfRenderFailures = 0,
                    RenderInstruction = renderInstruction,
                    ResolveInstruction = resolveInstruction,
                    StartAt = DateTime.Now.AddSeconds(10)

                };
                _client.Publish(publishItems, publishInstruction, targets, PublishPriority.Normal, new ReadOptions());
            }
        }


    }

This is probably more complicated than you need. You might just use the Publish class and used a future date in the StartAt value

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.