Last active
July 21, 2020 14:39
-
-
Save merkle-sitecore-gists/a701bd3c5f37316f9d0770310ac00f83 to your computer and use it in GitHub Desktop.
Export Sitecore item data in json to compare it with your preferred comparison tool
This file contains 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
############################################################ | |
# This Script can be used for export Sitecore Item tree data | |
# This can be used for comparison scenarios like | |
# 1. Compare content of different databases eg: "master and web" | |
# 2. Compare content between environments eg: "local, dev, staging, prod" | |
# 3. Versions or languages | |
# Benefints: only export field you want to compare/inspect (less noise, like update fields and so on) | |
# Note: the scripts only deliverys the export. Comparision have to be done with a different tool (winmerge, baretail, kdiff etc. | |
# Preconditions: Powerhshell Sitecore Extensions installed | |
############################################################ | |
$helixCustomSolution = ("/sitecore/templates/Project/*", "/sitecore/templates/Feature/*", "/sitecore/templates/Foundation/*", "/sitecore/layout/Layouts/Foundation/*", "/sitecore/layout/Layouts/Feature/*", "/sitecore/layout/Layouts/Project/*", "/sitecore/layout/Models/Foundation/*", "/sitecore/layout/Models/Feature/*", "/sitecore/layout/Models/Project/*", "/sitecore/layout/Renderings/Foundation/*", "/sitecore/layout/Renderings/Feature/*", "/sitecore/layout/Renderings/Project/*", "/sitecore/layout/Placeholder Settings/Foundation/*", "/sitecore/layout/Placeholer Settings/Feature/*", "/sitecore/layout/Placeholder Settings/Project/*" ); | |
# Sitecore specific field lists | |
$standardTemplateFields = ("__Enable item fallback", "__Tracking", "__Source", "__Source Item", "__Enforce version presence", "__Standard values", "__Read Only", "__Sortorder", "__Editor", "__Originator", "__Style", "__Subitems Sorting", "__Preview", "__Hidden", "__Context Menu", "__Thumbnail", "__Skin", "__Editors", "__Display name", "__Ribbon", "__Icon", "__Long description", "__Short description", "__Help link", "__Final Renderings", "__Presets", "__Controller", "__Renderings", "__Page Level Test Set Definition", "__Content Test", "Controller Action", "__Hide Version", "__Valid from", "__Valid to", "__Facets", "__Boosting Rules", "__Boost", "__Masters", "__Insert Rules", "__Bucket Parent Reference", "__Bucketable", "__Quick Actions", "__Persist Bucket Filter", "__Should Not Organize In Bucket", "__Enable Views", "__Default Bucket Query", "__Is Bucket", "__Publish", "__Unpublish", "__Never publish", "__Publishing groups", "__Owner", "__Security", "__Created by", "__Created", "__Updated", "__Revision", "__Updated by", "__Semantics", "__Archive date", "__Reminder date", "_Archive Version date", "__Reminder recipients", "__Reminder text", "__Workflow Validation Rules", "__Suppressed Validation Rules", "__Validator Bar Validation Rules", "__Validate Button Validation Rules", "__Quick Action Bar Validation Rules", "__Workflow state", "__Workflow state", "__Workflow", "__Lock", "__Default workflow") | |
$presentationFields = ("__Renderings", "__Final Renderings"); | |
$publishingFields = ("__Publish", "__Unpublish", "__Never publish", "__Publishing groups", "__Workflow Validation Rules", "__Suppressed Validation Rules", "__Validator Bar Validation Rules", "__Validate Button Validation Rules", "__Quick Action Bar Validation Rules", "__Workflow state", "__Workflow state", "__Workflow", "__Lock", "__Default workflow") | |
$excludedFieldNames = $standardTemplateFields; | |
#if includedFieldNames are used excluded will be ignored | |
$includedFieldNames = $null | |
# Global configurations which can be activated or deactivated for your needs but please make sure if you use export for comparition that you use the same settings | |
$globalConfig = @{}; | |
$globalConfig.UseFullPath = $true; | |
$globalConfig.UseName = $true; | |
$globalConfig.UseId = $false; | |
$globalConfig.UseTemplate = $false; | |
$globalConfig.UseLanguage = $true; | |
$globalConfig.UseVersion = $true; | |
# The extraction methods | |
function Get-ItemRepresentation($item, $excludedFields, $includedFields) | |
{ | |
# Global configuration intepretation | |
Write-Host "Process item: " + $item.Name | |
$representation = @{}; | |
if ($globalConfig.UseName -eq $true) | |
{ | |
$representation.Add("Name", $item.Name) | |
} | |
if ($globalConfig.UseId -eq $true) | |
{ | |
$representation.Add("ID", $item.ID.Guid) | |
} | |
if ($globalConfig.UseFullPath -eq $true) | |
{ | |
$representation.Add("Path", $item.FullPath) | |
} | |
if ($globalConfig.UseTemplate -eq $true) | |
{ | |
$representation.Add("Template", $item.TemplateID.Guid) | |
} | |
$version = [ordered]@{}; | |
if ($globalConfig.UseVersion -eq $true) | |
{ | |
$version.Add("Version", $item.Version) | |
} | |
if ($globalConfig.UseLanguage -eq $true) | |
{ | |
$version.Add("Language", $item.Language) | |
} | |
$fullpath = $item.FullPath | |
Write-Host "Fields on item: $fullpath" | |
$orderedFields = $item.Fields | Sort-Object -Property Key | |
foreach($field in $orderedFields) | |
{ | |
if($includedFields -ne $null) | |
{ | |
if ($includedFields -contains $field.Name) | |
{ | |
#Write-Host "Process field: " + $field.Name | |
$version.Add($field.Name, $field.Value) | |
} | |
} | |
else | |
{ | |
if ($excludedFields -cnotcontains $field.Name) | |
{ | |
#Write-Host "Process field: " + $field.Name | |
$version.Add($field.Name, $field.Value) | |
} | |
} | |
} | |
$representation.Add("Version", $version) | |
return $representation; | |
} | |
function Export-Trees($paths, $excludedFieldNames, $includedFieldNames, $db, $exportFileName) | |
{ | |
if ($exportFileName -eq $null) | |
{ | |
$exportFileName = "export.json" | |
} | |
$results = @(); | |
foreach ($path in $paths) | |
{ | |
if ($db -eq $null) | |
{ | |
$db = "master" | |
} | |
Write-Host "Path will be executed: $path"-ForegroundColor Green | |
$pathWithDatabase = $db + ":" + $path; | |
if ($path.StartsWith("query:")) | |
{ | |
$querypath = $db + ":" | |
$items = Get-Item -Path $querypath -Query $path.TrimStart("query:") -Language * -Version * | |
foreach ( $queryItem in $items) | |
{ | |
$results += Get-ItemRepresentation $queryItem $excludedFieldNames $includedFieldNames | |
} | |
} | |
else | |
{ | |
$recurse = $path.StartsWith("!") -or $path.EndsWith("*") | |
$path = $path.TrimStart("!") | |
$path = $path.TrimEnd("*") | |
$self = Get-Item $path -Language * -Version * -Database $db | |
foreach ( $selfversion in $self) | |
{ | |
$results += Get-ItemRepresentation $selfversion $excludedFieldNames $includedFieldNames | |
} | |
# definition to also process subitems recursivly | |
if ($recurse) | |
{ | |
$children = Get-ChildItem $pathWithDatabase -Language * -Version * -Recurse; | |
foreach ( $child in $children) | |
{ | |
$child | |
$results += Get-ItemRepresentation $child $excludedFieldNames $includedFieldNames | |
} | |
} | |
} | |
} | |
Write-Host "Browser download startet. If you receive no download check if browser is blocking your download." -ForegroundColor Yellow | |
ConvertTo-Json $results -Depth 2 | Out-Download -Name $exportFileName | |
} | |
$fieldNameTemplatePaths = ("/sitecore/templates/Foundation", "/sitecore/templates/Feature", "/sitecore/templates/Project"); | |
function Get-TemplatesFieldNamesFromTemplateRoot($paths) | |
{ | |
$collectedFieldNames = @(); | |
[string]$collectedFieldNamesString = "(" | |
foreach ($path in $paths) | |
{ | |
# templates must be created in english | |
$children = Get-ChildItem $path -Language "en" -Recurse; | |
foreach ( $child in $children) | |
{ | |
if ($child.TemplateId.Guid -eq "{455A3E98-A627-4B40-8035-E683A0331AC7}") | |
{ | |
$fieldName = $child.Name | |
$collectedFieldNames += $fieldName; | |
$collectedFieldNamesString += ", '$fieldName'" | |
} | |
} | |
} | |
$collectedFieldNamesString += ")" | |
$collectedFieldNamesString = $collectedFieldNamesString.Replace("(,", "(") | |
Write-Host $collectedFieldNamesString | |
return $collectedFieldNames; | |
} | |
# Extract from windows powershell console the flat item structure to separated language version files in filesystem structure | |
function Create-FolderStructure($inputFilePath, $folderDestination){ | |
if (Test-Path $inputFilePath) | |
{ | |
if (Test-Path $folderDestination) | |
{ | |
$json = Get-Content $inputFilePath | Out-String | ConvertFrom-Json | |
for ($i; $i -lt $json.Count; $i++) | |
{ | |
$fileObject = $json.Item($i) | |
$path = $fileObject.Path.Replace("/", "\") | |
$name = $fileObject.Name | |
$content = ConvertTo-Json $fileObject | |
$folder = $folderDestination.TrimEnd("\") + $path | |
if (Test-Path $folder) | |
{ | |
} | |
else | |
{ | |
New-Item -ItemType "directory" -Path $folder -Force | |
} | |
# include name if you want + "\" + $name + "_" | |
$filePath = $folder.TrimEnd("\") + "\" + $fileObject.Version.Language + "_" + "v" + $fileObject.Version.Version + ".json" | |
New-Item -ItemType "file" -Path $filePath -Value $content -Force | |
} | |
} | |
} | |
else | |
{ | |
Write-Host "InputFile Path not valid" -ForegroundColor Red | |
} | |
} | |
# Export all data for a path | |
$pathsWithChildren = ("/sitecore/content/home/*", "/sitecore/content/system/languges/*") | |
Export-Trees $pathsWithChildren $excludedFieldNames $null "master" "export_master.json" | |
# Export only paths without children | |
$pathsWithoutChildren = ("/sitecore/content/home/", "/sitecore/content/system/languges/") | |
Export-Trees $pathsWithoutChildren $excludedFieldNames $null "master" "export_master.json" | |
# Export items by query | |
$pathsQuery = ("/sitecore/content/home//*[@@templatename='Sample Page']") | |
Export-Trees $pathsQuery $excludedFieldNames $null "master" "export_master.json" | |
# Compare custom data of the project only cases (to find missconfiguration) only appears on custom data fields of items | |
$customFields = Get-TemplatesFieldNamesFromTemplateRoot $fieldNameTemplatePaths # this searches for template fields under helix folder paths | |
Export-Trees $mypaths $excludedFieldNames $customFields "master" "customfieldsexport_master.json" | |
Export-Trees $mypaths $excludedFieldNames $customFields "web" "customfieldsexport_web.json" | |
# Compare files | |
# Publish database case | |
Export-Trees $mypaths $excludedFieldNames $includedFieldNames "master" "master.json" | |
Export-Trees $mypaths $excludedFieldNames $includedFieldNames "web" "web.json" | |
# Compare files | |
# Environment comparision case | |
# 1. Execute script on environment 1 | |
Export-Trees $mypaths $excludedFieldNames $includedFieldNames "master" "env1.json" | |
# 2. Execute script on environment 2 | |
Export-Trees $mypaths $excludedFieldNames $includedFieldNames "master" "env2.json" | |
# Compare files | |
# You can generate a filesystem folder structure form the flat exported file | |
Create-FolderStructure "export.json" "C:\temp\" | |
# Compare folders afterwards |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment