Customize default search in Sitecore experience editor

Many of today’s Sitecore implementations contain lots and lots of items. In many cases the items are stored in buckets and the editors are therefore totally dependent on finding what they are looking for by using the search functionality in Sitecore. When entering the search in Experience Editor the editors may become a bit overwhelmed with information since the default is to search for everything. Normally the editor could start filtering and then search for whatever is needed.

I did however want an easier solution that also allowed me to give different default searches to different types of editors. This is what I came up with. I think it is not too intrusive, but I also admit that it is a bit hack-ish.

Setting up Sitecore

I started by creating the necessary templates.
Search settings templates

With the following fields.
Search settings template fields

The idea is that the administrator should be able to point out which templates each role should be presented with when opening the search dialog in EE. I also added an option to add the current editing language as a filter as well. For simplicity the roles field is simply a single line text field. The Sitecore search settings template has the __SitecoreSearchSettings template as a base template.

In this example the page types “Article”, “News” and “Product” are available for the editors to use.

Now the settings items can be created.

In this example four settings for search have been created, one for each role that should use default search settings. The Editor role has a corresponding Editor search setting, the settings states that the editor should per default filter the search on Article and News, it should also filter on language.

Some sample items have also been created and placed in buckets.

The code to handle the custom default search

There was a bit of detective work to create this and some of the findings are somewhat hack-ish. If you have better suggestions please share them in the comments below.

I will not bore you with long texts on how to create the repos, factories and models needed to get the search settings, it should be straight forward. Short version: The SitecoreSearchSettingsRepository’s GetContext method simply finds the item in the settings that corresponds to the current users roles and return a nicely formatted model item based on that information.

public static class SitecoreSearchSettingsRepository
    {

        public static SitecoreSearchSettings GetContext(bool isAdministrator, UserRoles roles)
        {
	        var searchSettingsFolder = Factory.GetDatabase("master").GetItem(Constants.SitecoreSearchSettings.FolderInstanceId);

            if (searchSettingsFolder == null)
                return null;

            var list = new List();
            foreach (Item searchSettingsItem in searchSettingsFolder.Children)
            {
                var sitecoreSearchSettings = Get(searchSettingsItem);
                if (sitecoreSearchSettings != null)
                    list.Add(sitecoreSearchSettings);
            }

            foreach (SitecoreSearchSettings sitecoreSearchSettings in list)
            {
                if (isAdministrator && sitecoreSearchSettings.Roles.Contains(Constants.SitecoreSearchSettings.StaticRoles.Administrator))
                    return sitecoreSearchSettings;

                foreach (Role userRole in roles)
                {
                    if (sitecoreSearchSettings.Roles.Contains(userRole.Name.Substring(userRole.Name.LastIndexOf("\\") + 1)))
                        return sitecoreSearchSettings;
                }
            }

            return null;
        }

        public static SitecoreSearchSettings Get(Item item)
        {
            if (item == null)
                return null;

            return SitecoreSearchSettingsFactory.Create(item);
        }

    }

To do the actual work a pipeline that extends the SetDefaultSearchFilters pipeline and adds some functionality.

    public class SetCustomDefaultSearchFilters : SetDefaultSearchFilters
    {
        protected override Dictionary<string, string> GetSearchFilters(DialogSearchFiltersArgs args)
		{
			var searchFilters = base.GetSearchFilters(args);

			var sitecoreSearchSettings = SitecoreSearchSettingsRepository.GetContext(Sitecore.Context.User.IsAdministrator, Sitecore.Context.User.Roles);
			if (sitecoreSearchSettings == null)
				return searchFilters;

			var webEditSearchString = "+location:Content|0de95ae441ab4d019eb067441b7c2450";

			foreach (Item template in sitecoreSearchSettings.Templates)
			{
				webEditSearchString += ";template:" + template.ID;
			}

			var languageKey = FindLanguageKey(HttpContext.Current.Request.Params.Keys);
			var editingLanguage = HttpContext.Current.Request.Params[languageKey];
			if (sitecoreSearchSettings.FilterOnEditingLanguage && !string.IsNullOrEmpty(editingLanguage))
			{
				webEditSearchString += ";+custom:culture|" + editingLanguage;
			}

			searchFilters["Web Edit Search.aspx"] = webEditSearchString;
			return searchFilters;
		}

        private string FindLanguageKey(NameObjectCollectionBase.KeysCollection keys)
        {
            foreach (string key in keys)
            {
                if (key != null && key.EndsWith("#lang") && !key.StartsWith("shell"))
                    return key;
            }
            return "sv-SE";
        }
    }

So what happens here? Well first we want to tell Sitecore to only search in content and  we do that by adding the location string to the search. The location id in this case is the /sitecore/content item. To continue the templates that were found on the settings item are looped and each entry gets added to the search string. Finally the culture is added if that was set. The way to find the current culture is not the most elegant but it does seem to work.

Finally the configuration file that tells Sitecore to use this pipeline needs to be added.

<?xml version="1.0"?>

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <buckets.dialogSearchFilters>
        <processor patch:instead="*@type='Sitecore.Buckets.Pipelines.UI.DialogSearchFilters.SetDefaultSearchFilters, Sitecore.Buckets']" type="Feature.Search.Pipelines.SetCustomDefaultSearchFilters, Feature.Search"/>
      </buckets.dialogSearchFilters>
    </pipelines>
  </sitecore>
</configuration>

The results

Let’s have a look what the admin account gets presented with when entering the search dialog.
Admin search
It becomes quite obvious that this will become a problem. In a fairly empty Sitecore solution with only a few new templates defined already there is quite a large amount of information thrown back at the editor. It might become overwhelming and you would need to educate the editors in how to use the search efficiently.

If we log in as news editor and have a look at the same dialog it will now look something like this.
News editor customized default search
This looks easy to understand. The editor can easily see which templates are shown, the filter can be removed if the editor wishes to see more and also only the relevant language versions are shown. And again the nifty feature is that different editors can have different default searches shown to them. One could even set up roles that only have the purpose of setting which search settings should be shown.

Example with editor.
Editor search

Leave a Reply

Your email address will not be published. Required fields are marked *