1

Basically I am trying to extend (add fields & make a copy) of the 'Command' and 'Task' templates which are under sitecore/Templates/System/Tasks

Duplicating them and adding fields to them is not an issue, however objects/items that are built from them will not work. Schedules do not run & commands do not fire.

Is this a limitation, or is there a way to get this to work?

Thanks.

0
4

First things first - You shouldn't extend templates this way. Best practice is to set inherited (in your case OOTB) template as base template to your custom template and add your custom fields.

You can set in in Builder -> Base Templates on your custom template. You can inspire by /sitecore/templates/System/Content Testing/Tasks/Rebuild Index Command template:

enter image description here

You have two options to achieve your goal:

1. Extending task commands - Create custom task command template + class

You can inspire by command that you can find here /sitecore/system/Tasks/Commands/Content Testing/Rebuild Suggested Tests Index

task command

As you can see template of this command is different to the others and has "Index Name" field which other command templates don't have. You can have similarly your custom fields as you need.

Take a look on value of field "Type". Opening Sitecore.ContenTesting.dll in dotPeek or IlSpy and finding class Sitecore.ContentTesting.Tasks.RebuildIndex will give you this code:

using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Maintenance;
using Sitecore.ContentTesting.Configuration;
using Sitecore.ContentTesting.Model.Data.Items;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Tasks;
using System.Diagnostics.CodeAnalysis;

namespace Sitecore.ContentTesting.Tasks
{
  public class RebuildIndex
  {
    [SuppressMessage("Microsoft.Performance", "CA1822:Mark members as static", Justification = "This will introduce breaking changes.")]
    public void Process(Item[] items, CommandItem command, ScheduleItem schedule)
    {
      if (!Settings.IsAutomaticContentTestingEnabled)
        return;
      Assert.ArgumentNotNull((object) items, nameof (items));
      Assert.ArgumentNotNull((object) command, nameof (command));
      Assert.ArgumentNotNull((object) schedule, nameof (schedule));
      ISearchIndex index = ContentSearchManager.GetIndex(new RebuildIndexCommandItem(command.InnerItem).IndexName);
      if (index == null)
        return;
      IndexCustodian.FullRebuild(index, true);
    }
  }
} 

You need to go further into RebuildIndexCommandItem class and do something similar.

Reading custom field values is simple with this notation:

this.InnerItem[RebuildIndexCommandItem.FieldIDs.IndexName]

2. Extending task schedules - Create custom DatabaseAgent class and replace OOTB one. This agent will "know" about your fields that you have added and it will use them during processing.

In this case, you are extending schedule task template itself and also logic in Sitecore which is not very good if it's multisite / multitenant solution. Also maintainability and upgradedability of solution won't be that good. I would prefer option 1 to begin with.

It can look like this:

public class DatabaseAgent : Sitecore.Tasks.DatabaseAgent
{

 public DatabaseAgent(string databaseName, string scheduleRoot) : base(databaseName, scheduleRoot)
 {
 }

 public new void Run()
 {
    this.LogInfo("Scheduling.DatabaseAgent started. Database: " + this.Database.Name);
    Job job = Context.Job;
    ScheduleItem[] schedules = this.GetSchedules();
    this.LogInfo("Examining schedules (count: " + (object)schedules.Length + ")");
    if (this.IsValidJob(job))
        job.Status.Total = (long)schedules.Length;
    foreach (ScheduleItem scheduleItem in schedules)
    {
        try
        {
            if (scheduleItem.IsDue && IsInTimeFrame(scheduleItem))
            {
                this.LogInfo("Starting: " + scheduleItem.Name + (scheduleItem.Asynchronous ? " (asynchronously)" : string.Empty));
                scheduleItem.Execute();
                this.LogInfo("Ended: " + scheduleItem.Name);
            }
            else
                this.LogInfo("Not due: " + scheduleItem.Name);
            if (scheduleItem.AutoRemove)
            {
                if (scheduleItem.Expired)
                {
                    this.LogInfo("Schedule is expired. Auto removing schedule item: " + scheduleItem.Name);
                    scheduleItem.Remove();
                }
            }
        }
        catch
        {
        }
        if (this.IsValidJob(job))
            ++job.Status.Processed;
    }
}

private bool IsInTimeFrame(ScheduleItem scheduleItem)
{
    var startTimeString = scheduleItem.InnerItem.Fields["ScheduledItemExtensionDataTimeframeStart"].Value;
    var endTimeString = scheduleItem.InnerItem.Fields["ScheduledItemExtensionDataTimeframeEnd"].Value;

    return IsDue(startTimeString, endTimeString);
}

private bool IsDue(string startTime, string endTime)
{
    DateTime start;
    DateTime end;
    DateTime.TryParse(startTime, out start);
    DateTime.TryParse(endTime, out end);
    return (CheckTime(DateTime.Now, start, end));
}

private bool CheckTime(DateTime time, DateTime after, DateTime before)
{
    return ((time >= after) && (time <= before));
}

private ScheduleItem[] GetSchedules()
{
    Item obj = this.Database.Items[this.ScheduleRoot];
    if (obj == null)
        return new ScheduleItem[0];
    ArrayList arrayList = new ArrayList();
    foreach (Item innerItem in obj.Axes.GetDescendants())
    {
        if (innerItem.TemplateID == TemplateIDs.Schedule)
            arrayList.Add((object)new ScheduleItem(innerItem));
    }
    return arrayList.ToArray(typeof(ScheduleItem)) as ScheduleItem[];
}

private bool IsValidJob(Job job)
{
    if (job != null)
        return job.Category == "schedule";
    return false;
}

private void LogInfo(string message)
{
    if (!this.LogActivity)
        return;
    Log.Info(message, (object)this);
}

}

where here you are reading values of your added fields:

var startTimeString = scheduleItem.InnerItem.Fields["ScheduledItemExtensionDataTimeframeStart"].Value;
var endTimeString = scheduleItem.InnerItem.Fields["ScheduledItemExtensionDataTimeframeEnd"].Value;

You can find more information and also implementation in this great blog post made by Jens Gustafsson -> http://coreofsite.com/2017/09/15/extending-scheduled-task-set-execution-time/ . Also code above was taken from this blog post

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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