0

I'm implementing the workflow setup in sitecore 10.2 version and the page has datasource items present. If the user clicks on Lock and edit options, then a new version will be created for page and datasource items. but the datasource item version will not be created.

Question: Create a datasource item version when a user clicks on Lock and edit options. Is it possible to write a custom script (powershell)?

3
  • Are you working on SXA?
    – ckhanna
    Commented Jun 28 at 18:08
  • yes, we are using SXA version (11400)
    – shivaraj
    Commented Jun 28 at 23:30
  • This is not possible in a direct script with a single Lock and Edit button click. There are 2 ways you can achieve this. 1. First create a custom PowerShell script button. Add the logic to fetch the datasource items. User has to click on the button again to activate this script and the Datsource items will be locked. 2. Customise the lock and Edit button pipeline to add your logic. Commented Jul 1 at 7:55

1 Answer 1

1

Whenever the page is locked, its version is added. Therefore, you can use Event Handler to listen to item:versionAdded event. On the triggering of this event, script can be executed in the background to create and lock datasource item versions as well, whenever the page item is locked.

  1. In order to listen to item:versionAdded event, you need to add the following patch:
<configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
  <sitecore>
    <events>
        <event name="item:versionAdded">
           <handler type="Spe.Integrations.Tasks.ScriptedItemEventHandler, Spe" method="OnEvent" />
        </event>
    </events>
  </sitecore>
</configuration>
  1. Thereafter, you can add the script to be executed to lock datasource items at the path Event Handlers -> Item -> VersionAdded as below.

enter image description here

  1. Inside the powershell script item, attach below snippet that reads the datasource items located on the page and then uses workflow helper method to lock and create the new versions of datasource items.
# Locks items depending on the user context
function LockItem {
  param([Sitecore.Data.Items.Item]$item , [bool]$isAdmin)
  Write-Log "Item with ID: $($item.ID) is locked"
  if ($isAdmin){
     $item.Locking.Lock();
  } elseif ($item.Access.CanWrite() -AND !$item.Locking.IsLocked() -AND !$item.Locking.HasLock()){
     [Sitecore.Context]::Workflow.StartEditing($item)
  }
}

try{
    $isAdmin = [Sitecore.Context]::User.IsAdministrator
    Write-Log "Current User is Admin : $($isAdmin)"
    $item = $eventArgs.Parameters[0]
    $language = $item.Language.Name
    Write-Log "Item with ID: $($item.ID) with version number $($item.Version.Number) and language $($language) was added" 
    
    # Get Site Context
    $instance = [Sitecore.DependencyInjection.ServiceLocator]::ServiceProvider
    $siteInfo = $instance.GetType().GetMethod('GetService').Invoke($instance, [Sitecore.XA.Foundation.Multisite.ISiteInfoResolver]).GetSiteInfo($item)
    $siteContext = New-Object Sitecore.Sites.SiteContext $siteInfo
    
    New-UsingBlock(New-Object Sitecore.Sites.SiteContextSwitcher $siteContext) {
        $defaultLayout = Get-LayoutDevice "Default"
        # Read the Final Layout
        $renderings = Get-Rendering -Item $item -Device $defaultLayout -FinalLayout
        $datasourceItems = @()
        if($renderings -ne $null -AND $renderings.Count -gt 0){
            foreach($rendering in $renderings){
                $datasource = $rendering.Datasource
                if($datasource -ne $null -AND ![string]::IsNullOrEmpty($datasource)){

                    # Fetch Datasource Item Path in SXA including local datasources
                    $datasourceArgs = [Sitecore.Pipelines.ResolveRenderingDatasource.ResolveRenderingDatasourceArgs]::new($datasource)
                    $datasourceArgs.CustomData["contextItem"] = $item             
                    [Sitecore.Pipelines.CorePipeline]::Run("resolveRenderingDatasource", $datasourceArgs)
                     
                    # Fetch Item from ID/Path
                    $datasourceArgsDataSource = $datasourceArgs.Datasource
                    $datasourceID = [System.Guid]::empty
                    if ([guid]::TryParse($datasourceArgsDataSource, [System.Management.Automation.PSReference]$datasourceID)){
                        $datasourceItem = Get-Item -Path "master:" -ID $datasourceArgsDataSource -Language $language
                    }else{
                        $datasourceItem = Get-Item -Path  $datasourceArgsDataSource -Language $language
                    }
                    
                    # Avoid Traversing Duplicate Items
                    if($datasourceItems -notcontains $datasourceItem.ID.ToString()){
                        # Helper function to Lock Item
                        LockItem $datasourceItem $isAdmin
                        $datasourceItems += $datasourceItem.ID.ToString()
                    }   
                }
            }
        }
        else{
            Write-Log "Item with ID: $($item.ID) is not a page item"
        }
    }   
} catch [System.Exception] {
    Write-Log $_
}        

Using the above approach, datasource items will be locked automatically whenever the page item is locked.

You can find more details on Event handlers here:

https://doc.sitecorepowershell.com/modules/integration-points/event-handlers

Let me know in case you have any doubts. Hope this helps!!!

2
  • 1
    thanks, I follow the above steps are working fine.
    – shivaraj
    Commented Jul 10 at 5:34
  • Glad to hear that @shivaraj!!!
    – ckhanna
    Commented Jul 10 at 5:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.