Шаблоны ветви в оптимизированном CMS

Оптимизирует CMS изначально не поддерживает шаблоны филиалов, концепцию, известную из различных систем управления контентом. Шаблоны филиала полезны, если мы хотим помочь авторам контента автоматизировать повторные задачи с несколькими элементами контента, например, создание новых страниц продукта с подпаги, все с предопределенной макетой, содержащей различные блоки. Эта проблема может быть решена путем копирования и вставки страницы Essitng и настройки контента на копии, но это больше похоже на обходной путь, который решает проблему лишь частично. Для начальных значений блоков в оптимизации CMS мы можем использовать SetDefaultValues Метод, но управление им из кода для более крупных структур может быть болезненным, также не решает проблему создания автоматических подпажков. Мы можем решить обе проблемы, добавив функциональность шаблона ветви в CMS.

Мы можем достичь этого, добавив простой код, сначала давайте добавим новый шаблон элемента, мы будем использовать его только в качестве папки, поэтому нам не нужны никакие поля:

[ContentType(DisplayName = "White Label Template Folder",
        GUID = "2acce58b-41cc-4edc-a361-a1baa86b51bc",
        Description = "A folder which allows to structure new branch templates.",
        GroupName = TabNames.BranchTemplate, Order = 40)]
public class TemplateFolderPage : PageData
{
}

Мы также можем настроить значок папки:

[UIDescriptorRegistration]
public class TemplateFolderPageUIDescriptor : UIDescriptor
{
    public TemplateFolderPageUIDescriptor()
            : base(ContentTypeCssClassNames.Folder)
    {
    }
}

Чтобы реализовать основную функциональность, мы можем использовать код ниже. В двух словах, внутри CreatedContent Событие, мы сначала делаем предварительные проверки:
– Это событие “нового предмета”? (Мы не хотим выполнять код, например, при копировании/вставке Opetation).
– Есть ли у нас папка с нашими шаблонами ветви под корнем?
– Есть ли у нас элемент страницы с созданным в настоящее время типом в папке шаблонов корневой ветви?
Если все проверки прошли, мы создаем глубокую копию элемента из папки ветви и используем его для замены исходной страницы. Мы уверены, что имя страницы и урлсегмент уникальны:

[InitializableModule]
[ModuleDependency(typeof(InitializationModule))]
public class BranchTemplateInitialization : IInitializableModule
{
    private IContentRepository _contentRepository;
    private IContentLoader _contentLoader;
    private UrlSegmentOptions _urlSegmentOptions;
    private IUniqueIdentityCreator _uniqueIdentityCreator;

    public void Initialize(InitializationEngine context)
    {
        var contentEvents = ServiceLocator.Current.GetInstance();
        _contentRepository ??= ServiceLocator.Current.GetInstance();
        _contentLoader ??= ServiceLocator.Current.GetInstance();
        _urlSegmentOptions ??= ServiceLocator.Current.GetInstance();
        _uniqueIdentityCreator ??= ServiceLocator.Current.GetInstance();

        contentEvents.CreatedContent += ContentEvents_CreatedContent;
    }

    public void Uninitialize(InitializationEngine context)
    {
        var contentEvents = ServiceLocator.Current.GetInstance();
        contentEvents.CreatedContent -= ContentEvents_CreatedContent;
    }

    private void ContentEvents_CreatedContent(object sender, ContentEventArgs e)
    {
        var saveArgs = e as SaveContentEventArgs;
        if (e.Content == null || (saveArgs != null && saveArgs.MaskedAction == SaveAction.CheckOut))
        {
            // skip other actions like copying
            return;
        }

        var templateFolder = _contentLoader.GetChildren(ContentReference.RootPage).FirstOrDefault();
        if (templateFolder == null) 
        { 
            return; 
        }

        // this is simplified code which only take 1st branch template item with the given type. 
        var myTemplateItem = _contentLoader.GetChildren(templateFolder.ContentLink)?.FirstOrDefault(x => x.ContentTypeID == e.Content.ContentTypeID);
        if (myTemplateItem == null) 
        {
            return; 
        }

        var name = e.Content.Name;
        var oldItemLink = e.ContentLink;
        var parentLink = e.Content.ParentLink;
        var newItemLink = _contentRepository.Copy(myTemplateItem.ContentLink, parentLink, AccessLevel.NoAccess, AccessLevel.NoAccess, false);
        var newItem = _contentRepository.Get(newItemLink);
        _contentRepository.Delete(oldItemLink, true);

        // rename page name and url segment to the one entered by author
        var newPage = newItem.CreateWritableClone();
        // we need to rename to new name and before forcing uniqueness
        newPage.Name = name;
        newPage.URLSegment = name;
        newPage.Name = _uniqueIdentityCreator.CreateName(newPage, name);
        newPage.URLSegment = _uniqueIdentityCreator.CreateURLSegment(newPage, _urlSegmentOptions);
        _contentRepository.Save(newPage, SaveAction.Default, AccessLevel.NoAccess);

        // update content link to point to new item
        e.ContentLink = newItemLink;
        e.Content = newItem;
    }
}

Чтобы это работало, нам нужно создать папку типа TemplateFolderPage Под корнем (я назвал его «мастер продуктов»), затем внутри этой папки мы создаем новую страницу выбранного типа и предопределенного макета (я назвал его «простым шаблоном продукта» и использовал тип «страница продукта», но это всего лишь пример). Я также добавил субстраницу под названием «Галерея» с собственной макетом. Эта структура послужит шаблоном для всех новых страниц продукта:

Read more:  Как показать неопубликованные блоки в предварительном просмотре страницы (оптимизируемо CMS 12) ~ Код Аднана Nexus

С помощью кода теперь мы можем создать новый элемент «страница продукта», используя стандартный диалог «Новая страница». Он должен создать новую страницу продукта под заданным именем и сегментом URL, но с предопределенным макетом и подпадкой галереи внутри.

22 июля 2025 года

Ещё по этой теме

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.