Created
June 4, 2025 20:03
-
-
Save MartinMiles/d8dc3ac2c54e5b62836ee00e583d943a to your computer and use it in GitHub Desktop.
Used to help mapping rederings to the placeholders
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[string]$itemPath = "/sitecore/content/Zont/Habitat/Home/AAA" | |
) | |
Set-Location -Path $PSScriptRoot | |
$config = Get-Content -Raw -Path ./config.LOCAL.json | ConvertFrom-Json | |
# Write-Output "ConnectionUri: $($config.connectionUri)" | |
# Write-Output "Username : $($config.username)" | |
# Write-Output "SPE Remoting Secret : $($config.SPE_REMOTING_SECRET)" | |
# Write-Output "Get item fields of '$itemPath'..." | |
Import-Module -Name SPE | |
$session = New-ScriptSession -ConnectionUri $config.connectionUri -Username $config.username -SharedSecret $config.SPE_REMOTING_SECRET | |
Invoke-RemoteScript -Session $session -ScriptBlock { | |
# ----------------------------------------------- | |
# Script: Export-PageLayoutHierarchyAsJson-Final-Minified.ps1 | |
# Purpose: Produce nested JSON for “/sitecore/content/Zont/Habitat/Home/AAA”, | |
# with "uid" first, then "placeholders", and output minified JSON. | |
# ----------------------------------------------- | |
# 1. MOUNT MASTER: PSDrive IF NOT ALREADY PRESENT | |
if (-not (Get-PSDrive -Name master -ErrorAction SilentlyContinue)) { | |
New-PSDrive -Name master -PSProvider Sitecore -Root "/" -Database "master" -ErrorAction Stop | Out-Null | |
} | |
# 2. GET MASTER DB & PAGE ITEM | |
$database = [Sitecore.Configuration.Factory]::GetDatabase("master") | |
if (-not $database) { return } | |
$pageItem = $database.GetItem($Using:itemPath) | |
if (-not $pageItem) { return } | |
# 3. IDENTIFY “DEFAULT” DEVICE (or fallback) | |
$allDevices = $database.Resources.Devices.GetAll() | |
if (-not $allDevices) { return } | |
$deviceItem = $allDevices | Where-Object { $_.Name -eq "Default" } | |
if (-not $deviceItem) { $deviceItem = $allDevices[0] } | |
# 4. GET ALL RENDERING REFERENCES (incl. inherited standard-values) | |
$renderingRefs = $pageItem.Visualization.GetRenderings($deviceItem, $true) | |
if (-not $renderingRefs) { | |
$emptyTree = @{ | |
UID = $pageItem.ID.ToGuid().ToString("D") | |
placeholders = @() | |
} | |
($emptyTree | ConvertTo-Json -Depth 5) -replace "\s+", "" | |
return | |
} | |
# 5. COLLECT UNIQUE PLACEHOLDER PATHS (no leading slash) | |
$allPlaceholderPaths = $renderingRefs | | |
Where-Object { $_.Placeholder } | | |
ForEach-Object { $_.Placeholder.TrimStart("/") } | | |
Sort-Object -Unique | |
# 6. HELPER: Build placeholder object | |
function Build-PlaceholderObject { | |
param( | |
[string]$placeholderPath, | |
[Sitecore.Layouts.RenderingReference[]]$allRefs | |
) | |
$refsHere = $allRefs | Where-Object { $_.Placeholder.TrimStart("/") -ieq $placeholderPath } | |
$renderingNodes = @() | |
foreach ($ref in $refsHere) { | |
$renderingNodes += Build-RenderingObject -ref $ref -allPaths $allPlaceholderPaths -allRefs $allRefs | |
} | |
return @{ | |
placeholder = $placeholderPath | |
renderings = $renderingNodes | |
} | |
} | |
# 7. HELPER: Build rendering object (uid first, then placeholders) | |
function Build-RenderingObject { | |
param( | |
[Sitecore.Layouts.RenderingReference]$ref, | |
[string[]]$allPaths, | |
[Sitecore.Layouts.RenderingReference[]]$allRefs | |
) | |
$renderingNode = [ordered]@{ uid = $ref.UniqueId.ToString() } | |
$ph = $ref.Placeholder.TrimStart("/") | |
$childKeys = @() | |
foreach ($candidate in $allPaths) { | |
if ($candidate -like "$ph/*") { | |
$relative = $candidate.Substring($ph.Length + 1) | |
$segment = $relative.Split("/")[0] | |
$childKey = "$ph/$segment" | |
if (-not ($childKeys -contains $childKey)) { $childKeys += $childKey } | |
} | |
} | |
if ($childKeys.Count -gt 0) { | |
$childPlaceholderObjects = @() | |
foreach ($child in $childKeys) { | |
$childPlaceholderObjects += Build-PlaceholderObject -placeholderPath $child -allRefs $allRefs | |
} | |
$renderingNode["placeholders"] = $childPlaceholderObjects | |
} else { | |
$renderingNode["placeholders"] = @() | |
} | |
return $renderingNode | |
} | |
# 8. TOP-LEVEL PLACEHOLDER KEYS (no "/") | |
$topLevelKeys = $allPlaceholderPaths | Where-Object { $_ -notlike "*/?*" } | |
# 9. BUILD TREE | |
$placeholderArray = @() | |
foreach ($top in $topLevelKeys) { | |
$placeholderArray += Build-PlaceholderObject -placeholderPath $top -allRefs $renderingRefs | |
} | |
# 10. WRAP WITH ROOT UID | |
$result = [ordered]@{ | |
UID = $pageItem.ID.ToGuid().ToString("D") | |
placeholders = $placeholderArray | |
} | |
# 11. OUTPUT MINIFIED JSON | |
($result | ConvertTo-Json -Depth 10) -replace "\s+", "" | |
} | |
Stop-ScriptSession -Session $session |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ----------------------------------------------- | |
# Script: Export-PageLayoutHierarchyAsJson-Final-Minified.ps1 | |
# Purpose: Produce nested JSON for “/sitecore/content/Zont/Habitat/Home/AAA”, | |
# with "uid" first, then "placeholders", and output minified JSON. | |
# ----------------------------------------------- | |
param( | |
[string]$PageItemPath = "/sitecore/content/Zont/Habitat/Home/AAA" | |
) | |
# 1. MOUNT MASTER: PSDrive IF NOT ALREADY PRESENT | |
if (-not (Get-PSDrive -Name master -ErrorAction SilentlyContinue)) { | |
New-PSDrive -Name master -PSProvider Sitecore -Root "/" -Database "master" -ErrorAction Stop | Out-Null | |
} | |
# 2. GET MASTER DB & PAGE ITEM | |
$database = [Sitecore.Configuration.Factory]::GetDatabase("master") | |
if (-not $database) { return } | |
$pageItem = $database.GetItem($PageItemPath) | |
if (-not $pageItem) { return } | |
# 3. IDENTIFY “DEFAULT” DEVICE (or fallback) | |
$allDevices = $database.Resources.Devices.GetAll() | |
if (-not $allDevices) { return } | |
$deviceItem = $allDevices | Where-Object { $_.Name -eq "Default" } | |
if (-not $deviceItem) { $deviceItem = $allDevices[0] } | |
# 4. GET ALL RENDERING REFERENCES (incl. inherited standard-values) | |
$renderingRefs = $pageItem.Visualization.GetRenderings($deviceItem, $true) | |
if (-not $renderingRefs) { | |
$emptyTree = @{ | |
UID = $pageItem.ID.ToGuid().ToString("D") | |
placeholders = @() | |
} | |
($emptyTree | ConvertTo-Json -Depth 5) -replace "\s+", "" | |
return | |
} | |
# 5. COLLECT UNIQUE PLACEHOLDER PATHS (no leading slash) | |
$allPlaceholderPaths = $renderingRefs | | |
Where-Object { $_.Placeholder } | | |
ForEach-Object { $_.Placeholder.TrimStart("/") } | | |
Sort-Object -Unique | |
# 6. HELPER: Build placeholder object | |
function Build-PlaceholderObject { | |
param( | |
[string]$placeholderPath, | |
[Sitecore.Layouts.RenderingReference[]]$allRefs | |
) | |
$refsHere = $allRefs | Where-Object { $_.Placeholder.TrimStart("/") -ieq $placeholderPath } | |
$renderingNodes = @() | |
foreach ($ref in $refsHere) { | |
$renderingNodes += Build-RenderingObject -ref $ref -allPaths $allPlaceholderPaths -allRefs $allRefs | |
} | |
return @{ | |
placeholder = $placeholderPath | |
renderings = $renderingNodes | |
} | |
} | |
# 7. HELPER: Build rendering object (uid first, then placeholders) | |
function Build-RenderingObject { | |
param( | |
[Sitecore.Layouts.RenderingReference]$ref, | |
[string[]]$allPaths, | |
[Sitecore.Layouts.RenderingReference[]]$allRefs | |
) | |
$renderingNode = [ordered]@{ uid = $ref.UniqueId.ToString() } | |
$ph = $ref.Placeholder.TrimStart("/") | |
$childKeys = @() | |
foreach ($candidate in $allPaths) { | |
if ($candidate -like "$ph/*") { | |
$relative = $candidate.Substring($ph.Length + 1) | |
$segment = $relative.Split("/")[0] | |
$childKey = "$ph/$segment" | |
if (-not ($childKeys -contains $childKey)) { $childKeys += $childKey } | |
} | |
} | |
if ($childKeys.Count -gt 0) { | |
$childPlaceholderObjects = @() | |
foreach ($child in $childKeys) { | |
$childPlaceholderObjects += Build-PlaceholderObject -placeholderPath $child -allRefs $allRefs | |
} | |
$renderingNode["placeholders"] = $childPlaceholderObjects | |
} else { | |
$renderingNode["placeholders"] = @() | |
} | |
return $renderingNode | |
} | |
# 8. TOP-LEVEL PLACEHOLDER KEYS (no "/") | |
$topLevelKeys = $allPlaceholderPaths | Where-Object { $_ -notlike "*/?*" } | |
# 9. BUILD TREE | |
$placeholderArray = @() | |
foreach ($top in $topLevelKeys) { | |
$placeholderArray += Build-PlaceholderObject -placeholderPath $top -allRefs $renderingRefs | |
} | |
# 10. WRAP WITH ROOT UID | |
$result = [ordered]@{ | |
UID = $pageItem.ID.ToGuid().ToString("D") | |
placeholders = $placeholderArray | |
} | |
# 11. OUTPUT MINIFIED JSON | |
($result | ConvertTo-Json -Depth 10) -replace "\s+", "" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Write a SPE (Sitecore PowerShell Extensions) script that does the following, exactly as described: | |
1. Mount the “master” PSDrive if it doesn’t already exist. | |
2. Load the master database and retrieve the item at `/sitecore/content/Zont/Habitat/Home/AAA`. If the database or item can’t be found, exit quietly. | |
3. Identify the “Default” device under `/sitecore/layout/Devices`. If no device named “Default” exists, fall back to the first device in the list. | |
4. Call `GetRenderings($deviceItem, $true)` on the page item’s `Visualization` property so that you get all `RenderingReference` objects—including any inherited from standard values. | |
5. Build a nested JSON structure with this exact format: | |
{ | |
"UID": "<page-item-guid-without-braces>", | |
"placeholders": [ | |
{ | |
"placeholder": "<full-placeholder-path>", | |
"renderings": [ | |
{ | |
"uid": "{<rendering-uid>}", | |
"placeholders": [ | |
{ | |
"placeholder": "<child-placeholder-path>", | |
"renderings": [ | |
{ "uid": "{<child-rendering-uid>}" }, | |
… | |
] | |
}, | |
… | |
] | |
}, | |
… | |
] | |
}, | |
… | |
] | |
} | |
- Top‐level key `"UID"` must be the page item’s GUID (no braces, standard “D” format). | |
- Under `"placeholders"`, list each unique placeholder path (no leading slash) that appears in any `RenderingReference.Placeholder`. For example, `"headless-main"`, `"footer"`, etc. | |
- For each placeholder object: | |
- Create a `"renderings"` array containing one object per rendering whose `Placeholder` equals exactly that path. | |
- Each rendering object must list `"uid"` first (the rendering’s GUID, with braces) and then `"placeholders"`. | |
- Determine child placeholders by finding any placeholder path that begins with `"<this-placeholder>/"`, stripping off the parent prefix, taking the next segment, and reconstructing the full child path. Recursively build placeholder objects under each rendering object in the same format. | |
- Ensure that even if a rendering has no children, it still has a `"placeholders": []` key after its `"uid"`. | |
6. Output the final JSON as a single minified string (no spaces, tabs, or line breaks) by piping the result of `ConvertTo-Json -Depth 10` into a regex replacement that removes all `\s+`. | |
7. Use ordered hashtables (`[ordered]@{ ... }`) whenever you need to guarantee that `"uid"` appears before `"placeholders"` in each rendering object, and that `"UID"` appears before `"placeholders"` at the root. | |
8. If there are no renderings at all (e.g. `GetRenderings()` returned zero), output a JSON object with `"UID"` set to the page item’s GUID and `"placeholders": []`, also minified. | |
The final script should be copy-and-paste–ready in Sitecore PowerShell ISE. |
Author
MartinMiles
commented
Jun 4, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment