Системные уведомления

Модуль "Системные уведомления" пользуется двумя типами сущностей: "Уведомление" (класс MailNotification, classes/system/subsystems/mailNotifications/MailNotification.php) и "Шаблон письма" (класс MailTemplate, classes/system/subsystems/mailTemplates/MailTemplate.php). Уведомление может включать в себя несколько шаблонов писем. Разработчики могут создавать свои уведомления и шаблоны через API системы.

Рассмотрим пример добавления нового уведомления. Это будет копия системного уведомления об изменении статуса заказа. Его можно будет использовать, например, при кастомизации системного метода отправки уведомления клиенту о сделанном заказе (EmarketNotification::SendCustomerNotification(), classes/components/emarket/notification.php).

Скрипт добавления уведомления:


<?php
include 'standalone.php';

$mailNotifications = UmiCms\Service::MailNotifications();
$mailNotificationsMap = $mailNotifications->getMap();

$mailTemplates = UmiCms\Service::MailTemplates();
$mailTemplatesMap = $mailTemplates->getMap();

$defaultLangId = langsCollection::getInstance()->getDefaultLang()->getId();
$defaultDomainId = domainsCollection::getInstance()->getDefaultDomain()->getId();

$newNotification = $mailNotifications->create([
$mailNotificationsMap->get('LANG_ID_FIELD_NAME') => $defaultLangId,
$mailNotificationsMap->get('DOMAIN_ID_FIELD_NAME') => $defaultDomainId,
$mailNotificationsMap->get('NAME_FIELD_NAME') => 'notification-emarket-status-change-custom',
$mailNotificationsMap->get('MODULE_FIELD_NAME') => 'emarket',
]);

$subjectTemplate = $mailTemplates->create([
$mailTemplatesMap->get('NOTIFICATION_ID_FIELD_NAME') => $newNotification->getId(),
$mailTemplatesMap->get('NAME_FIELD_NAME') => 'emarket-status-notification-subject-custom',
$mailTemplatesMap->get('TYPE_FIELD_NAME') => 'subject',
$mailTemplatesMap->get('CONTENT_FIELD_NAME') => '%header%',
]);

$contentBody = <<<CONTENT
<p>Ваш заказ #%order_number% %status%</p>
<div>
<hr/>
<p>Товары:</p>
%parse.emarket-status-notification-item.items%
<hr/>
<p>Всего товаров: %total_amount% шт.</p>
<p>На сумму: %total_price% %suffix%. </p>
</div>
Посмотреть историю заказов вы можете в своем <a href="http://%domain%/emarket/personal/">личном кабинете</a>.
CONTENT;

$contentTemplate = $mailTemplates->create([
$mailTemplatesMap->get('NOTIFICATION_ID_FIELD_NAME') => $newNotification->getId(),
$mailTemplatesMap->get('NAME_FIELD_NAME') => 'emarket-status-notification-content-custom',
$mailTemplatesMap->get('TYPE_FIELD_NAME') => 'content',
$mailTemplatesMap->get('CONTENT_FIELD_NAME') => $contentBody,
]);

$itemBody = <<<CONTENT
<p><a href="%link%">%name%</a></p>
<p>Цена: %price% %suffix%. Количество: %amount% шт.</p>
CONTENT;

$itemTemplate = $mailTemplates->create([
$mailTemplatesMap->get('NOTIFICATION_ID_FIELD_NAME') => $newNotification->getId(),
$mailTemplatesMap->get('NAME_FIELD_NAME') => 'emarket-status-notification-item-custom',
$mailTemplatesMap->get('TYPE_FIELD_NAME') => 'content',
$mailTemplatesMap->get('CONTENT_FIELD_NAME') => $itemBody,
]);


При создании новых сущностей используются потомки класса baseUmiCollectionConstantMap (classes/system/subsystems/constants/baseUmiCollectionConstantMap.php). Это просто коллекции констант, обычно в них содержатся названия полей в БД со свойствами сущностей. Например, для создания уведомления используется класс mailNotificationsConstantMap (classes/system/subsystems/constants/mailNotificationsConstantMap.php).

Свойства уведомления:

1) Идентификатор языковой версии сайта (lang_id)
2) Идентификатор домена (domain_id)
3) Название (name)
4) Модуль, в котором используется уведомление (module)

Свойства шаблона письма:

1) Идентификатор уведомления, в которое он входит (notification_id)
2) Название (name)
3) Тип (type). На данный момент в системе используется два типа - 'subject' и 'content'. Тип шаблона определяет формат его вывода на странице уведомления. Шаблоны типа 'subject' используются для темы письма и выводятся как простое поле с текстом. Шаблоны типа 'content' используются для содержания письма и выводятся как WYSIWYG-поле.
4) Содержимое (content)



Шаблоны писем могут содержать в себе другие шаблоны. Когда такой шаблон будет парситься, он запустит парсинг своих внутренних шаблонов. Чтобы передать переменные для внутренних шаблонов, используется вложенный массив переменных.

Синтаксис вызова вложенного шаблона:

%parse.emarket-status-notification-item.items%

где "parse" - ключевое слово, "emarket-status-notification-item" - название вложенного шаблона, "items" - название ключа массива, который указывает на массив значений для каждого вызова вложенного шаблона.

Клиентский код:


if ($this->module->isUsingUmiNotifications()) {
$mailNotifications = UmiCms\Service::MailNotifications();
$notification = $mailNotifications->getCurrentByName('notification-emarket-status-change-custom');

if ($notification instanceof MailNotification) {
$subjectTemplate = $notification->getTemplateByName('emarket-status-notification-subject-custom');
$contentTemplate = $notification->getTemplateByName('emarket-status-notification-content-custom');

if ($subjectTemplate instanceof MailTemplate) {
$subject = $subjectTemplate->getProcessedContent(['header' => $header]);
}

if ($contentTemplate instanceof MailTemplate) {
$content = $contentTemplate->getProcessedContent($variables);
}
}
}


Содержимое $variables:


Array
(
[order_id] => 1606
[order_name] => Заказ #27
[order_number] => 27
[status] => поступил в обработку
[personal_params] => 25/0b01770f7740fa3b87452861485e243a
[total_amount] => 1
[total_price] => 1338
[suffix] => руб
[+items] => Array
(
[0] => Array
(
[link] => /shop/dvd_tehnika/dvd_pleery/sony_tg-2356
[name] => Sony TG-2356 (Красное дерево)
[price] => 878
[amount] => 1
[suffix] => руб
),
[1] => Array(...),
...
)

[domain] => test.local
)


Ключ 'items' (или '+items' для совместимости с TPL-шаблонизатором) здесь указывает на значения переменных для вложенного шаблона товарного наименования 'emarket-status-notification-item-custom'. Для каждого товарного наименования передается свой массив переменных.

Порядок вывода значений этих переменных в шаблоне настраивается в контенте шаблона. Контент шаблонов можно изменять на странице редактирования уведомления. Справа от каждого шаблона расположен блок с кнопками. При нажатии на кнопку в шаблон вставляется вывод соответствующей переменной в формате %имя-переменной%.



Чтобы блок с кнопками появился у кастомного уведомления, нужно переопределить метод def_module::getVariableNamesForMailTemplates() в кастомном коде модуля, которому принадлежит уведомление. Пример такого метода из модуля emarket (classes/components/emarket/class.php):


public function getVariableNamesForMailTemplates() {
$commonVariables = [
'order_id' => getLabel('mail-template-variable-order_id', 'emarket'),
'order_name' => getLabel('mail-template-variable-order_name', 'emarket'),
'order_number' => getLabel('mail-template-variable-order_number', 'emarket'),
'domain' => getLabel('mail-template-variable-domain', 'emarket'),
'total_amount' => getLabel('mail-template-variable-total_amount', 'emarket'),
'total_price' => getLabel('mail-template-variable-total_price', 'emarket'),
'suffix' => getLabel('mail-template-variable-suffix', 'emarket'),
];

$itemVariables = [
'link' => getLabel('mail-template-variable-link', 'emarket'),
'name' => getLabel('mail-template-variable-name', 'emarket'),
'price' => getLabel('mail-template-variable-price', 'emarket'),
'suffix' => getLabel('mail-template-variable-suffix', 'emarket'),
'amount' => getLabel('mail-template-variable-amount', 'emarket'),
];

$statusVariables = [
'parse.emarket-status-notification-item.items' => getLabel('mail-template-variable-items', 'emarket'),
'status' => getLabel('mail-template-variable-status', 'emarket'),
'personal_params' => getLabel('mail-template-variable-personal_params', 'emarket'),
];

$receiptVariables = [
'receipt_signature' => getLabel('mail-template-variable-receipt_signature', 'emarket'),
];

$neworderVariables = [
'parse.emarket-neworder-notification-item.items' => getLabel('mail-template-variable-items', 'emarket'),
'payment_type' => getLabel('mail-template-variable-payment_type', 'emarket'),
'payment_status' => getLabel('mail-template-variable-payment_status', 'emarket'),
'first_name' => getLabel('mail-template-variable-first_name', 'emarket'),
'last_name' => getLabel('mail-template-variable-last_name', 'emarket'),
'email' => getLabel('mail-template-variable-email', 'emarket'),
'phone' => getLabel('mail-template-variable-phone', 'emarket'),
'delivery' => getLabel('mail-template-variable-delivery', 'emarket'),
'address' => getLabel('mail-template-variable-address', 'emarket'),
];

$invoiceVariables = [
'domain' => getLabel('mail-template-variable-domain', 'emarket'),
'invoice_link' => getLabel('mail-template-variable-invoice_link', 'emarket'),
];

return [
'emarket-status-notification-subject' => [
'header' => getLabel('mail-template-variable-header', 'emarket'),
],
'emarket-status-notification-content' => $commonVariables + $statusVariables,
'emarket-status-notification-receipt' => $commonVariables + $statusVariables + $receiptVariables,
'emarket-status-notification-item' => $itemVariables,

'emarket-neworder-notification-subject' => [
'header' => getLabel('mail-template-variable-header', 'emarket'),
],
'emarket-neworder-notification-content' => $commonVariables + $neworderVariables,
'emarket-neworder-notification-item' => $itemVariables,

'emarket-invoice-subject' => $invoiceVariables,
'emarket-invoice-content' => $invoiceVariables
];
}


Метод возвращает массив в формате


'templateName' => [
'variableName' => 'variableLabel',
...
]


К перечисленным выше системным шаблонам нужно добавить переменные для кастомного шаблона. Для перевода названий нужно добавить языковые метки в кастомный файл i18n в модуле.