Packaging Items in Sitecore Based on Updated Date

We’re only a few weeks away from our client’s big site launch, and we’re in full content entry mode. We’ve been doing our content entry on our QA environment, and regularly copying it to our production environment.

As you can imagine, this can be quite a laborious process; pinpointing which items have updates, which items are new which items haven’t changed since the last time we moved them. Even taking the safe route and moving over entire content nodes was time consuming as the site has hundreds of pages and hundreds of images; packages were taking a long time to create, download and reupload.

While there are tools out there that facilitate this, I wanted to develop a quick and bloat-free option to quickly add updated items to a package. I ended up writing a PowerShell script that takes a pre-defined date and automatically whips up a package containing items that were updated past that date.

I started by looking to the Sitecore PowerShell documentation, particularly the New-Package page. On this page there was an easy-to-understand example on how to script the creation of a Sitecore package and add items to it. With this new information in hand, I got to work writing my script.

The logic follows as such:

  1. Create a new package using the New-Package function.
  2. Take a date and a content root and retrieve all items recursively under that root whose Updated field was more recent than the provided date.
  3. Add each returned item to the package.
  4. Generate a list of items deleted after the provided date.
  5. Export the package using the Export-Package function.
  6. Download the package.

The script was fairly straightforward to write. I simply followed the logic outlined above, performing the necessary comparisons to determine which items had updates and adding them to the package. I also examined the Recycle Bin to determine if any items had been deleted since the provided date. Finally, I implemented the functionality to export and download the package (Export-Package and Download-File respectively).

Items are added to the package based on their last updated date.

The script doesn’t take care of removing items from the target database if they need to be, but it does give a list of what those items are, so you can manually delete those from the target environment. I hope to make an improvement to this in the future to automatically take care of this. If you have any insight on how to accomplish this, let me know!

The full script is below. All in all, this saves me so much time and allows me to perform more frequent content updates to our production environment. This script can totally be expanded upon too to fit broader or more narrow use cases.

As always, let me know if you have any questions in the comments below!

Happy Sitecoring!

# Script written by Patt MacMillan.
# The Sitecore root you want to package items from.
$root = "/sitecore/media library/Images"

# Variables to help with the file name formatting.
$rootPartitions = $root -split "/"
$lastDirectory = $rootPartitions[$rootPartitions.Length - 1]
$currentDateTime = Get-Date -Format u
$currentDateTime = $currentDateTime.Replace(" ", "").Replace(":", "")

# The name of the content package.
$fileName = "NYPA_Content_Package_" + $lastDirectory + "_" + $currentDateTime

# The date threshold to add items to the package. Any items updated after this date will be added.
$lastUpdatedDate = "20240515T000000Z"
$updateThreshold = [datetime]::ParseExact($lastUpdatedDate, "yyyyMMddTHHmmssZ", $null)

Write-Host -ForegroundColor Yellow "Adding all items under" $root "updated after" $updateThreshold " to package..."
$package = New-Package $fileName

$package.Sources.Clear();

$package.Metadata.Author = "Patt MacMillan"
$package.Metadata.Publisher = "Velir"
$package.Metadata.Version = "1.0"
$package.Metadata.Readme = "This package was generated with items under " + $root + " that were updated after " + $updateThreshold + "."

# Loop through all items in the designated root and retrieve any whose update date is later than the $updateThreshold variable set above.
Get-ChildItem $root -Recurse | Where-Object { [datetime]::ParseExact($_["__Updated"], "yyyyMMddTHHmmssZ", $null) -gt $updateThreshold} | ForEach-Object {
    try{
        $itemPath = "master:" + $_.Paths.Path
        $itemName = $_.Paths.Path.Replace("/", " ")
        
        # Add the item to the package source, using a formatted variant of the item's path as the name.
        # NOTE: change the install mode here if you don't want to use the Overwrite option.
        $source = Get-Item $itemPath | New-ItemSource -Name $itemName -InstallMode Overwrite
        $package.Sources.Add($source);
        Write-Host -ForegroundColor Green "Successfully added" $itemPath "to package."
    }
    catch{
        Write-Host -ForegroundColor Red "Could not add" $itemPath "to package."
    }
}

# Export the package using the $fileName variable set above.
Export-Package -Project $package -Path "$($fileName).zip" -Zip

# Get a list of all items that were deleted from the Sitecore environment after the provided date.
$database = Get-Database -Name "master"

$archive = Get-Archive -Database $database -Name "recyclebin"
$archiveItems = Get-ArchiveItem -Archive $archive

Write-Host ""
Write-Host -ForegroundColor Yellow "The following items under the specified root were deleted recently. Consider removing these from the target environment."
ForEach($archiveItem in $archiveItems){
    if($archiveItem.ArchiveDate -gt $updateThreshold -and $archiveItem.OriginalLocation.Contains("$root")){
        Write-Host "- " $archiveItem.OriginalLocation
    }
}

# Download the package.
Download-File "$SitecorePackageFolder\$($fileName).zip"
Write-Host -ForegroundColor Green "Package creation complete!"

Leave a comment