Thursday, September 17, 2020

Shared placeholder settings in SXA

Sitecore SXA placeholder settings

In Sitecore you can can set "placeholder settings" to manage/restrict the renderings that can be added in a placeholder by the editors. This is no different in SXA, although you will edit those restriction settings in another way as you can read on https://doc.sitecore.com/developers/sxa/93/sitecore-experience-accelerator/en/set-placeholder-restrictions.html.

In SXA you can set placeholder restrictions per site. These restrictions can be found in the Presentations folder of the SXA site and are applied on all pages in the site.




Sharing placeholder settings from a shared site

I was working on a setup for a multi-site solution where we have a tenant which includes many (mini-)sites that share almost everything except content (and sometimes the theme). We followed the SXA best practices for multi-site setups and have a shared site to manage all page designs, partial designs, themes, styles, variants and some content in delegated areas. We also have a master site to clone when creating new sites. 

When I was setting the placeholder settings for the mini-sites, I could have set them in the master site. But I know that all my site level placeholder settings will be the same for all those sites and it seemed an idea to set them in the shared site instead of copying them all over the sites. This was not possible ootb, but SXA is extensible and so.. with a little bit of custom code I made this work.

My code will first check if the current site has any placeholder settings defined. If no settings are found, we check the shared site(s) and get all settings from there. This works for us, but can be altered of course (e.g. to use a site setting to determine to use the shared restrictions or not).

public class LayoutsPageContext : Sitecore.XA.Foundation.PlaceholderSettings.Services.LayoutsPageContext, ILayoutsPageContext
{
  public override Item GetSxaPlaceholderItem(string placeholderKey, Item currentItem)
  {
    var result = base.GetSxaPlaceholderItem(placeholderKey, currentItem);
    if (result == null || !result.Children.Any())
    {
      foreach (var site in ServiceLocator.ServiceProvider.GetService<ISharedSitesContext>().GetSharedSitesWithoutCurrent(currentItem))
      {
        result = base.GetSxaPlaceholderItem(placeholderKey, site);
        if (result != null && result.Children.Any())
        {
           return result;
        }
      }
    }

    return result;
  }
}
We are implementing ILayoutsPageContext and inheriting from Sitecore.XA.Foundation.PlaceholderSettings.Services.LayoutsPageContext to keep the ootb functionality. In our case we want to extend the functionality that fetches the root item for placeholder settings - we need to override GetSxaPlaceholderItem

First thing to do is check the setting items in the current site which can be done by using the base (ootb) function. If that has no result we loop through the available shared sites (using Sitecore.XA.Foundation.Multisite) and call the base function for each site item. As the base function uses the item parameter to search for an item with the "Placeholder Settings Folder" template, this works fine and gets us what we want: the first folder with placeholder settings will be used.

Register this new context class with your dependency injection framework and your Sitecore solution will use it. And you are able to share placeholder restriction settings across sites - defining them in one place in a shared site.


Conclusion

This solution is not something you will want in all multi-site setups. But in our case we really benefit from having -next to all the other shared stuff- our placeholder settings in one place. For one tenant of course, not for the other tenants. If you also have a solution where your sites within a tenant could share the placeholder settings, this might be something for you. 

This post is the second one in a series inspired by our multi-mini-site setup. The first one handled the language selector. Stay tuned for more SXA knowledge sharing...


No comments:

Post a Comment