0

We have been using Sitecore as CMS for quite some time. We would like to clean up the images and files which are not linked with any items and archive them.

Is there any approach you have used for this ? Please let us know.

2
5

You can achieve this by writing a Powershell script - https://michaellwest.blogspot.com/2014/10/sitecore-powershell-extensions-tip.html?_sm_au_=iVVB4RsPtStf5MfN

Below PowerShell script is for finding media items without reference to any other item. Please have a look.

<#
    .SYNOPSIS
        Lists all media items that are not linked to other items.

    .NOTES
        Michael West
#>

# HasReference determines if the specified item is referenced by any other item.
function HasReference {
    param(
        $Item
    )

    $linkDb = [Sitecore.Globals]::LinkDatabase
    $linkDb.GetReferrerCount($Item) -gt 0
}

<# 
    Get-MediaItemWithNoReference gets all the items in the media library
    and checks to see if they have references. Each item that does not
    have a reference is passed down the PowerShell pipeline.
#>
function Get-MediaItemWithNoReference {
    $items = Get-ChildItem -Path "master:\sitecore\media library" -Recurse | 
        Where-Object { $_.TemplateID -ne [Sitecore.TemplateIDs]::MediaFolder }

    foreach($item in $items) {
        if(!(HasReference($item))) {
            $item
        }
    }
}

# Setup a hashtable to make a more readable script.
$props = @{
    InfoTitle = "Unused media items"
    InfoDescription = "Lists all media items that are not linked to other items."
    PageSize = 25
}

# Passing a hashtable to a command is called splatting. Call Show-ListView to produce
# a table with the results.
Get-MediaItemWithNoReference |
    Show-ListView @props -Property @{Label="Name"; Expression={$_.DisplayName} },
        @{Label="Updated"; Expression={$_.__Updated} },
        @{Label="Updated by"; Expression={$_."__Updated by"} },
        @{Label="Created"; Expression={$_.__Created} },
        @{Label="Created by"; Expression={$_."__Created by"} },
        @{Label="Path"; Expression={$_.ItemPath} }

Close-Window
2

I always seemed to have problems with the PowerShell scripts so for our customer needs I created a simple .aspx script that can be accessible from CMS url. This script allows you to also pack the items you want to delete. For extra caution the items are move first in recycle bin, if everything goes well you can empty the recycle bin. txtRootId can point to media library or any other sitecore area that you want to clean. The cs code is the following:

private static StringBuilder sbResults = new StringBuilder();
private static List<Item> UnusedMedias;
private static Database masterDb = Factory.GetDatabase("master");

protected void Page_Load(object sender, EventArgs e)
{
  if (!Sitecore.Context.User.IsAuthenticated)
  {
    Response.Redirect("~/sitecore/login");
  }
}

protected void Go_Click(object sender, EventArgs e)
{
  lblResults.Text = "";
  using (new Sitecore.SecurityModel.SecurityDisabler())
  {
    string rt = txtRootId.Text;

    Item root = masterDb.GetItem(rt);
    if (root != null)
    {
      UnusedMedias = new List<Item>();
      sbResults = new StringBuilder();
      ProcessItem(root);
      lblResults.Text += sbResults.ToString();
    }
  }

}


private void ProcessItem(Item rt)
{
  try
  {
    lblResults.Text = "<b>Unused items:</b><br/>";
    var mediaItems = rt.Children;
    foreach (Item media in mediaItems)
    {
      if (media.Template.Key != "media folder" && !media.HasChildren && Globals.LinkDatabase.GetReferrerCount(media) == 0)
      {
        UnusedMedias.Add(media);
        sbResults.AppendFormat("{0}<br/>", media.Paths.FullPath);

      }
      ProcessItem(media);
    }

  }
  catch (Exception ex)
  {
    Sitecore.Diagnostics.Log.Info("Erorr at the following at item" + rt.Paths.ContentPath + ex.Message + ex.StackTrace, this);
    lblResults.Text += ex.ToString() + " <br/>";
  }

}


protected void Pack_Click(object sender, EventArgs e)
{
  try
  {
    Sitecore.Install.PackageProject document = new Sitecore.Install.PackageProject();
    document.Metadata.PackageName = "DeletedItems" + DateTime.Now.ToString("yyyyMMdd") + "-" + DateTime.Now.ToString("HH_mm");
    document.Metadata.Author = "mia";

    Sitecore.Install.Items.ExplicitItemSource source = new Sitecore.Install.Items.ExplicitItemSource(); //Create source – source should be based on BaseSource  
    source.Name = "items";

    foreach (Item media in UnusedMedias)
    {
      Item[] items = media.Axes.GetDescendants();
      source.Entries.Add(new Sitecore.Install.Items.ItemReference(media.Uri, false).ToString());

      foreach (Item item in items)
      {
        source.Entries.Add(new Sitecore.Install.Items.ItemReference(item.Uri, false).ToString());
      }


    }
    document.Sources.Add(source);
    document.SaveProject = true;
    //path where the zip file package is saved  
    using (Sitecore.Install.Zip.PackageWriter writer = new Sitecore.Install.Zip.PackageWriter(Settings.DataFolder + "/packages/DeletedItems" + DateTime.Now.ToString("yyyyMMdd") + "-" + DateTime.Now.ToString("HH_mm") + ".zip"))
    {
      Sitecore.Context.SetActiveSite("shell");

      writer.Initialize(Sitecore.Install.Installer.CreateInstallationContext());

      Sitecore.Install.PackageGenerator.GeneratePackage(document, writer);

      Sitecore.Context.SetActiveSite("website");
    }


  }
  catch (Exception ex)
  {
    Sitecore.Diagnostics.Log.Info("Erorr packing unsed media" + ex.StackTrace, this);
    this.lblResults.Text += ex.ToString() + " <br/>";
  }

}


protected void Delete_Click(object sender, EventArgs e)
{
  try
  {
    foreach (Item media in UnusedMedias)
    {
      media.Recycle();
      Response.Write("...");
    }

  }
  catch (Exception ex)
  {
    this.lblResults.Text += ex.ToString() + " <br/>";
  }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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