6

I am trying to move items, upon expiration date from one folder to another. It is possible? Is there a way for the items to be moved maybe programmatically at the end of the month, or every 10 days. Or even better when Arhive day is set, and the item gets Archived. So for example, I will set up Archive date for the item, and then it will move to the "Archive" when the time comes, that I can access from Desktop>All Applications. But it will automatically appear in the "News Archive". See the screenshot below. I want to be able to automatically move items from "news" to "news archive" when certain day and time occur.

enter image description here

I want to be able to consider expiration date in the the code also:

enter image description here

13

You would want to setup a Sitecore Scheduled task to do this. You have 2 options:

1. C# Scheduled Task

The code to move an item is pretty simple:

var currentDb = Sitecore.Data.Database.GetDatabase("master");
var folderItem = currentDb.GetItem("/sitecore/content/AutoArchive/NewsArchive");
var archiveItem = currentDb.GetItem("/sitecore/content/AutoArchive/News/News01");
archiveItem.MoveTo(folderItem);

You would want to use the search API to get you a list of news items that need archiving rather than getting the News item and looping through the child items, depending on how many child items it has.

To create that as a scheduled task, create a class for the task:

using System;
using Utils;

namespace WebsiteNamespace
{
     public class ArchiveNewsItemsScheduledTask
     {
         private static readonly object Monitor = new object();

         public void Run()
         {
             lock (Monitor)
             {
                 // Code to move the items here
             }
         }
    }
}

Then add your config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
    <sitecore>
        <scheduling>
            <agent type="MyNamespace.ArchiveNewsScheduledTask, MyAssembly" method="Run" interval="00:20:00"></agent>
        </scheduling>
    </sitecore>
</configuration>

Set the interval to daily or however often you want to run the task to pick up items it needs to archive.

UPDATE: Get items based on expiry date

This is based on your code from the deleted question:

var itemContainer = _sourceDatabase.GetItem("/sitecore/content/AutoArchive/News");
var destinationContainer = _sourceDatabase.GetItem("/sitecore/content/AutoArchive/News Archive");

if (itemContainer != null)
{
    var items = itemContainer.Children;
    foreach (Item item in items)
    {
        // Only move the item if the expiry date is in the past
        var expiryDate = (DateField)item.Fields["Expiration Date"];
        if (expiryDate.DateTime < System.DateTime.Now.ToUniversalTime()) {
            item.MoveTo(destinationContainer);
        }
    }
}

There are more efficient ways of doing this, but it should give you a start. I suggest you look up a simple Sitecore query, or for more performance use the Sitecore Search API and pull the items from the index

2. Use Sitecore PowerShell Extensions

Using SPE you can setup a scheduled task without having to write or deploy any .net code. Again moving an item is pretty simple:

$destinationPath = "/sitecore/content/AutoArchive/News Archive";

#templateName = "News"
Get-ChildItem master:/sitecore/content/AutoArchive/News | Where-Object { $_.TemplateName -match $templateName } | ForEach-Object {
    Move-Item -Path $_.ItemPath -Destination $destinationPath;
}

Write a new SPE module that does the archiving, then create a scheduled task to run that SPE script. The instructions are already available for those things so I wont add all that detail here as its not the main answer to the question

Either option would work.

Are You Sure?

Some things to think about tho - automatically moving items will change the Urls that may already have links created to them, so how will you handle redirects or broken links?

  • thank you for your help. If I have a field in an item that is "Expiration Date" how would I check for that field's value and only archive when the that date passes? – Tony Jun 5 '17 at 15:50
  • @Tony - its best to open a new question for that. Each question should deal with a single "thing" not multiple questions in one. Open an new one and I can provide an answer there. – Richard Seal Jun 5 '17 at 15:52
  • I just updated the question – Tony Jun 5 '17 at 16:17
  • Answer updated. – Richard Seal Jun 5 '17 at 16:48
8

You can achieve this by scheduling a task. You can use

  1. Sitecron and implement a job which performs the desired actions
  2. Sitecore Powershell.
  3. Default Sitecore Schedule Job

Option 1

First, you need to install the Sitecron Module if not available on your Sitecore Instance. You can download it from Marketplace here.

Code

public class ArchiveItemJob : IJob
{
    private readonly Database _sourceDatabase = Factory.GetDatabase("master");

    public void Execute(IJobExecutionContext context)
    {
        var itemContainer = _sourceDatabase.GetItem("path or item id of the container to archive");

        var destinationContainer = _sourceDatabase.GetItem("path or item id of the destination container");

        if (itemContainer != null)
        {
            var items = itemContainer.Children;

            foreach (Item item in items)
            {
                item.MoveTo(destinationContainer);
            }
        }
    }
}

In Sitecore, you will need to create a Sitecron Job. So, navigate to /sitecore/system/Modules/Sitecron and insert a Sitecron job item. Then, fill in the fields.

  • Type: Insert the namespace and the assembly name here. Example: experimental.Jobs.ArchiveItemJob,experimental.

  • Cron Expression: Insert the expression here. You can use the following site to generate the expression: CronMaker.

Option 2

Using Sitecore Powershell can allow you to easily schedule a task to trigger a Powershell Script

Powershell Script

$sourceContainer = "Your source path here";
$destinationContainer = "Your destination path here";

Get-ChildItem $sourceContainer | ForEach-Object {
    Move-Item -Path $_.ItemPath -Destination $destinationContainer;
}

You can download the Sitecore Powershell Module from Marketplace here.

Then, again you will need to create the task. The following link explain how to create the Task item for powershell.

Option 3

This option is similar to Option 1 but with a slight modification. The class will not extend the IJob and does not require Sitecron. Only thing is to have a config file with the agent and the interval.

Code

public class ArchiveItemJob
{
    private readonly Database _sourceDatabase = Factory.GetDatabase("master");

    public void Execute()
    {
        var itemContainer = _sourceDatabase.GetItem("path or item id of the container to archive");

        var destinationContainer = _sourceDatabase.GetItem("path or item id of the destination container");

        if (itemContainer != null)
        {
            var items = itemContainer.Children;

            foreach (Item item in items)
            {
                item.MoveTo(destinationContainer);
            }
        }
    }
}

Config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <sitecore>
    <scheduling>
      <agent type="NamespaceHere" method="Execute" interval="01:00:00"/>
    </scheduling>
  </sitecore>
</configuration>

The only drawback here is that if the App Pool is restarted, the timer will reset. In other words, for example, if only 5 minutes remain for the job to trigger and the App pool restarts, you will need to wait again for the interval for another 1 hour.

access from Desktop -> All Applications

You will require to implement a custom module which makes use of any above options in order to display the list of archive items.

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.