Recently on a project I had a need to tidy up the Content tree. In this particular project, renderings on pages made use of Datasource items (best practice, of course!), however rather than keep these items locally to the page in a nested folder, they were all located in a Global folder.

This can certainly work, and it all depends on how you use items, but in this instance it lead to MANY items sitting under that Global folder, most of which were only used by a single item.

To tidy this up, I prepared an SPE script that would find items that are only used by a single page and then move them to sit under that item, inside a Content folder.

This is the script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#
# Identifies Datasource items that only have one single referrer and moves them to
# a _Content folder that item, creating the folder if necessary.
#
# Item path to find content items within. The script will include all descendants.
$itemPath = "master:/sitecore/content/MyWebsite/Global Content/StandardText"
# Add template IDs here that you want picked up
$validTemplates = @(
#"{43DB35A0-E104-4165-B4E9-6E393528B27B}"
)
# The template path to use for the Content folder under page items
$contentFolderTemplatePath = "User Defined/MyWebsite/Folder Templates/Page Content Folder"
# What to name the Content folder when creating
$contentFolderName = "_Content"
# -------- Script follows --------
$items = Get-ChildItem $itemPath -Recurse
$moveCollection = @()
foreach ( $item in $items )
{
if (!($validTemplates -contains $item.TemplateID)) {
continue
}
# Get the item referrers. As multiple versions of the same referrer will be
# returned separately, just get the unique IDs.
$itemReferrers = $item | Get-ItemReferrer -ItemLink | Select -Expand SourceItemID -Unique
if ($itemReferrers.Count -eq 0)
{
Write-Host "$($item.FullPath) has no referrers so can't be moved."
} elseif ($itemReferrers.Count -gt 1)
{
Write-Host "$($item.FullPath) has more than one referrer and will be left. (Count = $($itemReferrers.Count))"
} else
{
# Item has a single referrer, it's a candidate to move.
$destinationItem = Get-Item -Path master: -ID $itemReferrers[0].Guid -ErrorAction SilentlyContinue
if ($destinationItem)
{
$moveItem = New-Object System.Object
$moveItem | Add-Member -type NoteProperty -name DatasourceItem -value $item
$moveItem | Add-Member -type NoteProperty -name DestinationItem -value $destinationItem
$moveCollection += $moveItem
}
else
{
Write-Host "$($item.FullPath) has a single referrer, but that item could not be found."
}
}
}
# How many items we've identifed to move
Write-Host $moveCollection.Count
# If you just want to identify items, uncomment this return.
#return
# Now perform the move.
foreach ( $moveItem in $moveCollection )
{
$itemContentFolderPath = "master:" + $moveItem.DestinationItem.FullPath + "/" + $contentFolderName
$contentFolder = Get-Item -Path $itemContentFolderPath -ErrorAction SilentlyContinue
if (!$contentFolder) {
# Need to create content folder
$contentFolder = New-Item -Path $itemContentFolderPath -ItemType $contentFolderTemplatePath
Write-Host "Created content folder for $itemContentFolderPath"
}
Write-Host "Moving $($moveItem.DatasourceItem.FullPath)"
Move-Item -Path $moveItem.DatasourceItem.FullPath -Destination $contentFolder.FullPath
}

That’s all there is. The general flow of the script is:

  • Recurse through all items in the content folder specified
  • Find items that have only 1 referrer. Multiple referrals from different versions of the same item count as 1.
  • Move those content items to sit under the referrer in a _Content folder. Create the folder if it doesn’t exist.

The top-half of the script can be executed (uncomment the return line) if you just want to identify which items can and can’t be moved.