Remove items from Resource File

Sitecore recently introduced Resource Files which contain Sitecore items. This is a great improvement and is beneficial when upgrading Sitecore especially while running on containers. There are some good resources out there to learn more about them for example this post by Martin Miles.

One limitation of this feature is that it is not possible to delete Sitecore items included this way. This makes sense in most cases, items included through this file are Sitecore system items and should generally not be deleted. However there are a few valid reasons why you would want to delete such an item.

The rest of this post describes how you can get rid off these items, without actually modifying the resource file itself. Modifying the resource file itself is not a good approach as you would get a new Resource File during an upgrade and any deleted items would be back.

The Resource files get read by the ProtobufDataProvider and it stores the items in a few dictionaries in memory. The solution below will remove the items from these dictionaries. Below code inherits the ProtobufDataProvider and adds the functionality to remove the items:

using Microsoft.Extensions.DependencyInjection;
using Sitecore.Abstractions;
using Sitecore.Configuration;
using Sitecore.Data.DataProviders.ReadOnly.Protobuf;
using Sitecore.DependencyInjection;
using System;
using System.Linq;

namespace Foundation.Providers
{
    public class RemoveItemsProtobufDataProvider : ProtobufDataProvider
    {
        public void RemoveItem(string item)
        {
            Guid itemGuid;

            if (Guid.TryParse(item, out itemGuid))
            {
                bool foundParent = false;

                if (base.DataSet.Definitions.ContainsKey(itemGuid))
                {
                    var parentID = base.DataSet.Definitions[itemGuid].ParentID;
                    foundParent = true;

                    //the item will also live as a child under the parent item, remove it from here as well
                    base.DataSet.Children[parentID] = base.DataSet.Children[parentID].Where(x => x.ID != itemGuid).ToArray();
                    base.DataSet.Definitions.Remove(itemGuid);
                }

                if (base.DataSet.Children.ContainsKey(itemGuid) && foundParent)
                {
                    base.DataSet.Children.Remove(itemGuid);
                }

                if (base.DataSet.ItemsByTemplate.ContainsKey(itemGuid) && foundParent)
                {
                    base.DataSet.ItemsByTemplate.Remove(itemGuid);
                }

                if (base.DataSet.LanguageData.ContainsKey(itemGuid) && foundParent)
                {
                    base.DataSet.LanguageData.Remove(itemGuid);
                }

                if (base.DataSet.SharedData.ContainsKey(itemGuid) && foundParent)
                {
                    base.DataSet.SharedData.Remove(itemGuid);
                }
            }
        }

        public RemoveItemsProtobufDataProvider(ObjectList filePaths) : base(filePaths.List.OfType<string>().Where(s => !string.IsNullOrEmpty(s)), ServiceLocator.ServiceProvider.GetRequiredService<BaseLog>())
        {
        }
    }
}

This dataprovider will need to be patched into Sitecore, below patch file will do this for the master database. The removeItems list, highlighted in the XML below, contains the list of the items which need to be removed:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
	<sitecore>
		<databases >
			<database id="master" role:require="ContentManagement or StandAlone">
				<dataProviders >
					<dataProvider>
						<param>
							<protobufItems>
								<patch:attribute name="type">Foundation.Providers.RemoveItemsProtobufDataProvider, Foundation</patch:attribute>
								<filePaths>
									<patch:delete/>
								</filePaths>
								<param desc="filePaths" hint="list">
									<filePath>$(dataFolder)/items/$(id)</filePath>
								</param>
								<!-- Add items which need to be removed below -->
								<removeItems hint="list:removeItem">									
									<item>{22222222-2222-2222-2222-222222222222}</item>
									<item>{33333333-3333-3333-3333-333333333333}</item>
								</removeItems>
							</protobufItems>
						</param>
					</dataProvider>
				</dataProviders>
			</database>
		</databases>
	</sitecore>
</configuration>

3 thoughts on “Remove items from Resource File

  1. Pingback: Upgrading Sitecore Platforms – Changes in Sitecore 10.x - Perficient Blogs

Leave a comment