Добавляем свои переменные в шаблоны писем Joomla 5+

Шаблоны писем в Joomla. Вступление

С недавнего времени (с выходом Joomla 4) в CMS Joomla появился замечательный функционал — шаблоны писем. Эти шаблоны позволяют администратору настроить «под себя» все системные уведомления, которые отсылает CMS как пользователям, так и администраторам.

Шаблоны писем CMS Joomla

Шаблоны писем CMS Joomla

В предыдущих версиях Joomla, все это было реализовано через языковые переменные, что было крайне неудобно и максимально ограничивало администратора в «творческом полёте», именно администратора или контент менеджера, которые ни чего не понимают в разработке и им было практически невозможно поменять дизайн писем без привлечения разработчика. Слава Богу, это в прошлом!

На данный момент (Joomla 5) функционал шаблонов писем значительно расширен (и это, конечно же, не предел). Теперь администратор из админ. панели может отредактировать в удобном HTML редакторе (TinyMCE) любое системное письмо, которое отправляет Joomla. Может добавить любой текст, изображения, файлы — это круто!

Так же CMS позволяет вставлять необходимые переменные в тело письма (имя пользователя, почту, имя сайта и т.д.) так, как нужно в конкретном случае. Поддерживается редактирование для разных языков, то есть предусмотрена полная мультиязычность, как и в остальном функционале Joomla.

Редактор и переменные

Редактор и переменные

И все это предлагается «под капотом» Joomla и отлично работает!

Но, как это всегда бывает, стандартного функционала может не хватить для определенных задач. Именно об этом и пойдет речь в этой статье.

Не хватает переменных…

В каждом наборе переменных, любого шаблона письма, содержится необходимый минимум, который Joomla предлагает «из коробки».

Естественно, что для каждого конкретного случая этот набор должен быть скорректирован и доработан. СMS Joomla предоставляет нам такую возможность с помощью использования плагинов.

Ко мне обратился заказчик, с просьбой расширить список переменных в шаблонах, а, конкретно, добавить поля пользователей в шаблон письма об успешной активации пользователя. Далее я расскажу, как я это реализовал.

Спасибо, Бро!

Успешной реализации задачи очень помог Сергей Толкачев. В своем посте на Хабре он описал триггеры событий, которые позволяют добавить новые переменные к шаблонам писем.

И в целом, моя статья, это только расширенное описание поста Сергея. За что ему огромное спасибо!

Кстати, не забудем поблагодарить и заказчика расширения, который спонсировал все это производство, а так же дал согласие на публикацию решения в свободном доступе — это веб студия Креативные Бизнес Системы.

Триггеры для плагина

И так… Задача поставлена: добавить в шаблоны писем переменные, которые будут содержать значения полей пользователей.

Для решения нам нужно:

  1. Вывести переменные, в нашем случае это поля пользователей, в шаблоны писем в панели администратора Joomla. Для этого в Joomla предусмотрен триггер BeforeRenderingMailTemplateEvent.

  2. Передать новые переменные в письмо администратору. Для этого предусмотрен триггер onMailBeforeRendering.

Давайте рассмотрим каждое событие отдельно.

onMailBeforeTagsRendering

Это событие поможет нам добавить переменные (шорт-коды) в шаблон письма в панели администратора.

Шорт-коды шаблона письма

Шорт-коды шаблона письма

В моем случае нужно добавить к стандартным переменным поля пользователя. В качестве шорт-кодов будем использовать имя (не заголовок) полей.

Поля пользователя

Поля пользователя

Для получения всех полей пользователей используем

use \Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
$user_fields = FieldsHelper::getFields('com_users.user', true);

Вся функция будет выглядеть так

    public function onMailBeforeTagsRendering(Event $event): void
    {
        $template = $event->getArgument(1); //получаем весь объект 
        $tags =  $template->params['tags']; //получаем стандартные шорт-коды
        $user_fields = FieldsHelper::getFields('com_users.user', true); //получаем все поля пользователя
        $newtags = [];
        foreach($user_fields as $field) {
            $newtags[] = $field->name; //формируем массив с полями по имени поля
        }
        $tags = array_merge($tags, $newtags); //добавляем поля пользователя к стандартным шорт-кодам
        $template->params['tags'] = $tags;// добавляем все в объект
    }

Теперь в шаблонах писем, в переменных, у нас отображаются и шорт-коды полей пользователей.

Новые шорт-коды

Новые шорт-коды

Но этого еще не достаточно, нужно еще «заставить» Joomla понимать, какие данные отправлять, используя эти шорт-коды.

onMailBeforeRendering

Это событие позволит нам научить Joomla понимать новые шорт-коды и корректно отправлять данные по ним в письма.

Аргументом $event для этой функции является экземпляр класса BeforeRenderingMailTemplateEvent

подключаем

use Joomla\CMS\Event\Mail\BeforeRenderingMailTemplateEvent;

У меня стояла задача, передать поля пользователей в письме администратору о необходимости активации нового пользователя, поэтому следующий код будет немного не стандартный, но очень хорошо подойдет для примера

    public function onMailBeforeRendering(BeforeRenderingMailTemplateEvent $event): void
    {
        $templateId = $event->getTemplateId(); //id шаблона, как контекст
        $app = Factory::getApplication();

        if($templateId == 'com_users.registration.admin.verification_request') { //нужный мне шаблон письма
            $activiti = $app->input->get('token', '', 'string');//получение токена (ключа активации), который содержится в ссылке на активацию
            $db = Factory::getContainer()->get(DatabaseInterface::class); //подключаем базу
            $db->setQuery("SELECT `id` FROM `#__users` WHERE `activation` = '{$activiti}'");
            $user_id =  $db->loadResult(); //получаем id пользователя, что бы передать его поля
       } else {
            $user = $app->getIdentity();
            $user_id = $user->id; 
       }
        $user_fields = FieldsHelper::getFields('com_users.user', ['id' => $user_id], true); //получаем все поля пользователя
        $template = $event->getTemplate();//получаем весь объект письма
        foreach($user_fields as $field) {
            $data[$field->name] = $field->value; //получаем поля пользователя в нужном нам виде по имени поля
        }
        $template->addTemplateData($data);// передаем в объект новый массив шорт-кодов
    }

Давайте подробно рассмотрим $data — массив, который передает данные о новых переменных (шорт-кодах).

$template = $event->getTemplate();//получаем весь объект письма
$data = [
  'field_name' => 'field_vale',
];
$template->addTemplateData($data);// передаем в объект новый массив шорт-кодов

Теперь в шаблоне письма используем {field_name}, чтобы в самом письме получить field_value.

Всю логику разобрали. Далее соберем все в системный плагин, который позволит реализовать нужный функционал.

Системный плагин ShortMail

Структура плагина

- language
-- en-GB
--- plg_system_shortmail.ini
--- plg_system_shortmail.sys.ini
- services
-- provider.php
- src
-- Extension
--- Shortmail.php
- shortmail.xml

Файл манифеста shortmail.xml



    plg_system_shortmail
    Alexandr Novikov
    2025-01-20
    (C) 2025 Alexandr Novikov. All rights reserved.
    GNU General Public License version 2 or later
    support@joomlab.ru
    https://joomlab.ru
    1.0.0
    
    joomLab\Plugin\System\Shortmail
    
        services
        src
        language
    
    
        en-GB/plg_system_shortmail.ini
        en-GB/plg_system_shortmail.sys.ini
    
    
        
            

provider.php

set(
            PluginInterface::class,
            function (Container $container) {
                $plugin = new Shortmail(
                    $container->get(DispatcherInterface::class),
                    (array) PluginHelper::getPlugin('system', 'shortmail')
                );
                $plugin->setApplication(Factory::getApplication());
                return $plugin;
            }
        );
    }
}

shortmail.php

 'onMailBeforeRendering',
            'onMailBeforeTagsRendering' => 'onMailBeforeTagsRendering'
        ];
    }

    public function onMailBeforeRendering(BeforeRenderingMailTemplateEvent $event): void
    {
        $templateId = $event->getTemplateId();
        $app = Factory::getApplication();
        $activiti = '1';
        if($templateId == 'com_users.registration.admin.verification_request') {
            $activiti = $app->input->get('token', '', 'string');
            $db = Factory::getContainer()->get(DatabaseInterface::class);
            $db->setQuery("SELECT `id` FROM `#__users` WHERE `activation` = '{$activiti}'");
            $user_id =  $db->loadResult();
       } else {
            $user = $app->getIdentity();
            $user_id = $user->id;
       }
        $user_fields = FieldsHelper::getFields('com_users.user', ['id' => $user_id], true);
        $template = $event->getTemplate();
        foreach($user_fields as $field) {
            $data[$field->name] = $field->value;
        }
        $template->addTemplateData($data);
    }
    public function onMailBeforeTagsRendering(Event $event): void
    {
        $template = $event->getArgument(1);
        $tags =  $template->params['tags'];
        $user_fields = FieldsHelper::getFields('com_users.user', true);
        $newtags = [];
        foreach($user_fields as $field) {
            $newtags[] = $field->name;
        }
        $tags = array_merge($tags, $newtags);
        $template->params['tags'] = $tags;
    }

}

Контекст

Чуть не забыл про контекст. Структура шаблонов писем отличается от общей структуры CMS, где, помимо триггеров, в основном используется еще и $context для вывода плагина в нужном месте компонента.

В шаблонах писем вместо контекста используется template_id

$templateId = $event->getTemplateId();
//com_users.registration.admin.verification_request

template_id

template_id

Используя $template_id вы сможете добавить в разные шаблоны писем свои наборы полей.

Заключение

С помощью этого плагина вы сможете добавить в шаблоны писем поля пользователя. А на примере этого плагина вы сможете добавить в свои шаблоны писем абсолютно любые переменные (шорт-коды), при чем в разных шаблонах они могут быть разные!

Удачи!

© Habrahabr.ru