Sitecore auto publishing agent

There are many reasons to do auto publishing i Sitecore. For example users that forgets to publish their changes, an auto publish will correct that. In a large scale setup, the problem could be the opposite. Too many CM users publishing their changes all the time, so that the CD servers cache gets cleared too often giving the site a bad performance. Then, remove the publish access from the authors and schedule an publish task like every few hours or so.

In an environment with limited languages, the Sitecore.Tasks.PublishAgent is really handy, but its main problem is that the list of languages that should be published is stored in the config files. I wanted to change that. Unfortunately the PublishAgent is almost a sealed class, so I ended up copying the main code of it and created a new class.

Also, I wanted to be able to publish either all languages, or a selection of languages. By default, the class loops through all languages in the source (master) database and publishes them. If you extend the language item template with a CheckBox named AutoPublish, the agent will only publish the languages with this CheckBox checked. This is handy if you’re dealing with a lot of “not-yet-published” languages or if you’re dealing with a group of content editors that just don’t get it 😉

So here’s the code for this agent:

public class LanguagePublishEngine
{
    public string SourceDatabase { get; protected set; }
    public string TargetDatabase { get; protected set; }
    public PublishMode Mode { get; protected set; }

    public LanguagePublishEngine(string sourceDatabase, string targetDatabase, string mode)
    {
        Assert.ArgumentNotNullOrEmpty(sourceDatabase, "sourceDatabase");
        Assert.ArgumentNotNullOrEmpty(targetDatabase, "targetDatabase");
        Assert.ArgumentNotNullOrEmpty(mode, "mode");
        this.SourceDatabase = sourceDatabase;
        this.TargetDatabase = targetDatabase;
        this.Mode = ParseMode(mode);
    }

    public virtual void Run()
    {
        var db = Factory.GetDatabase(SourceDatabase);
        foreach (Language language in LanguageManager.GetLanguages(db))
        {
            ID languageItemId = LanguageManager.GetLanguageItemId(language, db);
            var languageItem = db.GetItem(languageItemId);
            CheckboxField autoPublish = languageItem.Fields["AutoPublish"];
            if (autoPublish == null || autoPublish.Checked)
            {
                this.StartPublish(language);
            }
        }
    }

    public static PublishMode ParseMode(string mode)
    {
        switch (mode.ToLowerInvariant())
        {
            case "full":
                return PublishMode.Full;
            case "incremental":
                return PublishMode.Full;
            case "smart":
                return PublishMode.Smart;
            default:
                return PublishMode.Unknown;
        }
    }

    protected virtual void StartPublish(Language language)
    {
        Assert.ArgumentNotNull(language, "language");
        Log.Info(string.Format("PublishAgent started (source: {0}, target: {1}, language: {2},  mode: {3})", SourceDatabase, TargetDatabase, language.Name, Mode), this);
            
        Database sourceDatabase = Factory.GetDatabase(SourceDatabase);
        Database targetDatabase = Factory.GetDatabase(TargetDatabase);
        Assert.IsNotNull(sourceDatabase, "Unknown database: {0}", SourceDatabase);
        Assert.IsNotNull(targetDatabase, "Unknown database: {0}", TargetDatabase);

        var options = new PublishOptions(sourceDatabase, targetDatabase, Mode, language, DateTime.Now) {Deep = true};
        var publisher = new Publisher(options);
        bool willBeQueued = publisher.WillBeQueued;
        publisher.PublishAsync();

        Log.Info(string.Format("Asynchronous publishing {0}. Job name: {1}", willBeQueued ? "queued" : "started", publisher.GetJobName()), this);
        TaskCounters.Publishings.Increment();
    }
}

and then just enable it in the configuration

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <scheduling>
      <agent hint="Web1" patch:instead="*[@type='Sitecore.Tasks.PublishAgent']" type="Your.Namespace.LanguagePublishEngine" method="Run" interval="01:00:00">
        <param desc="source database">master</param>
        <param desc="target database">web</param>
        <param desc="mode (full or smart or incremental)">smart</param>
      </agent>
    </scheduling>
  </sitecore>
</configuration>

done.

4 thoughts on “Sitecore auto publishing agent

    • You can put it anywhere in your solution, or in a separate assembly if you like to. Just put the same namespace and assembly in the configuration xml, like <agent type=”namespace.where.you.place.your.file”… Wrap the code with your own namespace.

    • It has changed slightly in later versions. It now is in:

      Sitecore.Diagnostics.PerformanceCounters.JobsCount.TasksPublishings.Increment()

Comments are closed.