The Sitecore PowerShell Extensions (SPE) module is a Sitecore development accelerator that can drastically increase your productivity and curtail the amount of time it takes to deliver a Sitecore solution.
The module provides a command line (CLI) and a scripting environment (ISE) for automating tasks. SPE works with the Sitecore process, capable of making native calls to the Sitecore API and manipulating files. Running commands and writing scripts follow the standard and well-known Windows PowerShell syntax. Windows PowerShell is a common tool used in IT for desktop and server management, so we decided to stick with that as a framework to build upon.
You can read more about Sitecore Powershell Extensions here.
The scripts that I have posted below can be pasted and directly executed on the Powershell ISE provided by SPE.
Please modify the variables as per your requirement before executing them.
This method is the most simple, and the one I often use. As sometimes the result of a certain query/filter can be a single item, I use ToArray to ensure that the result will be an array.
Script:
function ToArray
{
Begin {$output = @(); }
Process { $output += $_; }
End { return ,$output; }
}
Usage:
$AllItems = Get-ChildItem $ParentItem.ID -Language $Language -Recurse | Where-Object { $_.TemplateName -eq $TemplateName } | ToArray
# After the child items are filtered based on the template id,
# There's always a chance that the resulting item may be a single item
# ToArray ensures that the result will always be an array
# We can further write the script assuming $AllItems will be an array
As we are very much used to Object-Oriented Programming, we are used to creating classes for every entity we use in our code. When scripting with Powershell, creating classes can make the code more readable and help us write the logic efficiently.
Class Redirection
{
[string] $From;
[string] $To;
Redirection([string] $fromIn, [string] $toIn)
{
$this.From = $fromIn.Trim();
$this.To = $toIn.Trim();
}
}
Usage:
$item = [Redirection]::new("/from/url", "/to/url")
The class used in the below example will have to be changed as per your needs.
Script:
Class Redirection
{
[string] $From;
[string] $To;
Redirection([string] $fromIn, [string] $toIn)
{
$this.From = $fromIn.Trim();
$this.To = $toIn.Trim();
}
}
function Read-ItemsFromCsv
{
$File = Receive-File $SitecoreTempFolder
if($File -ne "cancel" -and $File.EndsWith(".csv"))
{
$CsvData = Import-Csv $File
[Redirection[]]$AllItems = @()
foreach($entry in $CsvData)
{
if($entry -ne $null -and $entry.From -ne $null -and $entry.To -ne $null)
{
$item = [Redirection]::new($entry.From, $entry.To)
if($item -ne $null)
{
$AllItems += $item
}
}
}
}
Remove-Item $File
return $AllItems
}
The variable $SitecoreTempFolder used in the above script is a global variable provided by SPE itself, which gives the path to the temp folder of the Sitecore instance.
Usage:
$AllRedirections = Read-ItemsFromCsv
We always have certain items that need to be always created under a specific type of item. For example, we always have the local-data item under every page for an SXA site. This method can be specifically used in these cases.
The Select -First 1 in the script is the Powershell equivalent for the LINQ First(), and the Where-Object is the Powershell equivalent for LINQ Where().
Script:
function GetOrCreate-ItemWithTemplate
{
Param([Sitecore.Data.Items.Item] $ParentItem,[System.String] $TemplateId, [System.String] $Language, [System.String] $Name, [bool] $CheckForName = $False)
Process
{
if($CheckForName -eq $False)
{
$ItemRequired = Get-ChildItem $ParentItem.ID -Language $Language | Where-Object { $_.TemplateId -eq $TemplateId} | Select -First 1
}
else
{
$ItemRequired = Get-ChildItem $ParentItem.ID -Language $Language | Where-Object { $_.TemplateId -eq $TemplateId -and $_.Name.Trim() -eq $Name.Trim()} | Select -First 1
}
if($ItemRequired -eq $null)
{
$ItemRequired = New-Item -Path $ParentItem.Paths.Path -ItemType $TemplateId -Name $Name -Language $Language
}
}
End
{
return $ItemRequired
}
}
Usage:
When the child item is needed, but the name if that item doesn’t matter.
$RequiredItem = GetOrCreate-ItemWithTemplate -ParentItem $ParentFolderItem -TemplateId $ItemTemplateId -Name $ItemName -Language $Language
When the name of the child item matters.
$RequiredItem = GetOrCreate-ItemWithTemplate -ParentItem $ParentFolderItem -TemplateId $ItemTemplateId -Name $ItemName -Language $Language -CheckForName $True
This method can be used in cases where you need to recursively select items under a parent folder and filter them based on a template.
Script:
function ToArray
{
Begin {$output = @(); }
Process { $output += $_; }
End { return ,$output; }
}
function Read-ItemsUnderParent
{
Param([System.String] $ParentItemPath, [System.String] $TemplateName, [System.String] $Language, [System.Boolean] $IncludeParent = $False)
Begin
{
$ParentItem = Get-Item -Path $ParentItemPath -Language $Language
}
Process
{
$AllItems = Get-ChildItem $ParentItem.ID -Language $Language -recurse | Where-Object { $_.TemplateName -eq $TemplateName} | ToArray
if($IncludeParent)
{
$AllItems += $ParentItem
}
}
End
{
return $AllItems
}
}
Usage:
When you do not want to include the parent item in the selection.
e.g. Select all Products under a bucket folder.
$AllProducts = Read-ItemsUnderParent -ParentItemPath $ParentItemPath -TemplateName $TemplateNameOfItems -Language $LanguageOfItem
When you want to include the parent item as well in the selection
e.g. Select all pages under a Home item, include Home as well as it is a page.
$AllPages = Read-ItemsUnderParent -ParentItemPath $HomeItemPath -TemplateName $PageTemplateName -Language $LanguageOfItem -IncludeParent $True
Script:
function Get-ItemWithMatchingField
{
Param([Sitecore.Data.Items.Item[]] $ItemCollection, [System.String] $FieldName, [System.String] $ValueToMatch)
Process
{
$MatchingItem = $ItemCollection | Where-Object { $_.[$FieldName].Trim() -eq $ValueToMatch.Trim()} | | Select -First 1
}
End
{
return $MatchingItem
}
}
Usage:
$RequiredArticle = Get-ItemWithMatchingField -ItemCollection $AllArticles -FieldName "Article Name" -ValueToMatch "My Article"
Script:
function Update-MediaField
{
Param([Sitecore.Data.Items.Item] $Item, [System.String] $FieldName, [System.String] $TargetId)
Process
{
$Item.Editing.BeginEdit()
[Sitecore.Data.Fields.ImageField]$field = $Item.Fields[$FieldName]
$field.Alt = $Item.Name
$field.MediaID = $TargetId
$Item.Editing.EndEdit()
}
}
Usage:
Update-MediaField -Item $ItemToUpdate -FieldName $FieldToUpdate -TargetId $MediaItem.ID
Script:
function Add-RenderingToPage
{
Param([Sitecore.Data.Items.Item] $PageItem,[System.String] $RenderingPath, [System.String] $Placeholder, [Sitecore.Data.Items.Item] $DataSourceItem = $null, [System.String] $Database = "master")
Process
{
$RenderingItem = Get-Item -Database $Database -Path $RenderingPath | New-Rendering -Placeholder $Placeholder
if($DataSourceItem -eq $null)
{
Add-Rendering -Item $PageItem -PlaceHolder $Placeholder -Instance $RenderingItem -DataSource $DataSourceItem.Paths.Path
}
else
{
Add-Rendering -Item $PageItem -PlaceHolder $Placeholder -Instance $RenderingItem -DataSource ""
}
}
}
Usage:
Add-RenderingToPage -PageItem $CurrentPage -RenderingPath $MyRenderingPath -Placeholder "main" -DataSourceItem $MyDataSourceItem
I will keep adding more and more scripts as and when I can to this post. Feel free to bookmark this page and refer as needed.
Also, do let me know in the comments if you feel a particular use case is missing and you need it in the article.
Feedback and Suggestions welcome!
Happy Sitecoring!!