As you may (or may not) know, any given page on a Sitecore site can be made up of content from both the page Item as well as any number of datasource Items stored throughout the content tree. Especially given the component-driven nature of SXA, the content really could be anywhere. This not only enables much of the personalizing power of Sitecore, but also allows for content reuse.
But as with any content management system with more than one user, you need a way to manage concurrency. That is, you need to make sure that content edited by one user isn’t overwritten by someone modifying the same content around the same time. In Sitecore, this is handled by the locking and unlocking of content items. When you edit a content item, that item is locked. No one else can edit that item until you have unlocked it.
However, with a component-driven content model, where there are multiple content items in play for any given page, managing the locking, unlocking and workflow of all of this can get a bit tricky. Fortunately, Sitecore has documented how you can configure item locking, as well as many other fantastic members of the community. This can be done through these settings:
- RequireLockBeforeEditing
- AutomaticLockOnSave
- AutomaticUnlockOnSaved
It would be a great idea to configure these settings so that your items lock and unlock in a workflow that supports your content authors.
That way, you don’t have an author create and edit a new page, then unlock it, only to discover that the dozen or so datasources split between the local and global data folders are still locked.

However, I ran across a scenario today where, on an SXA site we just launched, we hadn’t configured this locking behavior.

Well, it’s easy enough to add that setting through a patch file and deploy, but that wouldn’t help content authors that were trying to edit content, still locked by others, right now.
That’s where Sitecore Powershell Extensions comes in!

I wrote a script that will read all the renderings on a given page, including any snippet or composite renderings, and unlock them.
function Get-DatasourceDetails {
param (
[string] $parentPath,
[string] $datasourceId,
[switch] $unlockItems
)
if ($datasourceId -ne "") {
if ($datasourceId.StartsWith("local:")) {
$datasourceItem = Get-Item -path ($datasourceId -replace "local:", $parentPath)
} elseif ($datasourceId.StartsWith("/sitecore/content")) {
$datasourceItem = Get-Item -path $datasourceId
} else {
$datasourceItem = Get-Item master: -id $datasourceId
}
$renderings = Get-Rendering -item $datasourceItem -FinalLayout
if ($($renderings.Count) -gt 0) {
Get-Renderings -item $datasourceItem -unlockItems $unlockItems
}
if ($unlockItems -and $($datasourceItem.Locking.IsLocked())) {
Unlock-Item -item $datasourceItem
write-host "$($datasourceItem.ItemPath) :: Item Unlocked"
} else {
write-host "$($datasourceItem.ItemPath) :: $($datasourceItem.Locking.IsLocked())"
}
}
}
function Get-Renderings {
param (
[Sitecore.Data.Items.Item] $item,
[switch] $unlockItems
)
$renderings = Get-Rendering -item $item -FinalLayout
foreach($rendering in $renderings) {
Get-DatasourceDetails -parentPath $item.ItemPath -datasourceId $rendering.Datasource -unlockItems:$unlockItems
}
}
$item = Get-Item -path "path-to-page"
Get-Renderings $item -unlockItems
Run this without the -unlockItems
switch and it will show you all of the datasource items and the lock status. Or, if you’re feeling brave, -unlockItems
away!
This was all done on version 9.3. YMMV.
Happy Sitecore trails, my friend!