Уведомления о событиях

Примечание

Описанная функциональность впервые появилась в версии 4.11.1.

В CS-Cart реализован механизм многоканальных уведомлений о происходящих в системе событиях: создании заказа, смене его статуса, отправке товаров на модерацию, создании отгрузки в заказе, и пр.

Основные компоненты данного механизма:

  • события;
  • диспетчер событий;
  • сообщения;
  • транспорты;
  • получатели;
  • настройки уведомлений.

Важно

У нас есть пример модуля, который полностью реализует описанный механизм расширения уведомлений: https://github.com/cscart/addon-notification-events-example.

События

Событие представляет из себя:

  • уникальный текстовый идентификатор, обозначающий событие;
  • набор данных, относящийся к этому событию.

Пример: событие “Изменение деталей заказа” имеет идентификатор 'order.updated'; в него передаётся набор данных о заказе $order_info, полученый из функции fn_get_order_info.

Как добавить собственное событие

Все события, получатели и транспорты сообщений, зарегистрированные в системе, описаны в схеме notification/events.php.

Схема доступна через сервис Tygh::$app['event.events_schema'].

Каждый элемент схемы имеет следующую структуру:

(string) EventId => [
    'id' => (string) EventId,
    'group' => (string) GroupId,
    'name' => [
        'template' => (string) TemplateLanguageVariable,
        'params' => [
            (string) SubstitutionName => (string) Substitution,
            ...
        ],
    ],
    'receivers' => [
        (string) ReceiverId => [
            (string) TransportId => (callable) MessageProvider,
            ...
        ],
        ...
    ],
],
  • EventId — идентификатор события;
  • GroupId — идентификатор группы событий. Он используется на странице настроек уведомлений для более удобной навигации;
  • TemplateLanguageVariable — имя языковой переменной, которая используется для обозначения события в настройках уведомлений;
  • SubstitutionName и Substitution — имя и значение параметров, используемых для адаптации языковой переменной под особенности события;
  • ReceiverId — идентификатор получателя;
  • TransportId — идентификатор транспорта;
  • MessageProvider — провайдер сообщения.

Чтобы зарегистрировать событие:

  1. Выберите уникальный идентификатор события (EventId).

  2. Выберите, к какой группе событий новое событие относится.

    Если событие относится к новой группе — создайте языковую переменную с идентификатором, совпадающим с GroupId, и значением — названием группы событий.

  3. Создайте языковую переменную, в которой хранится шаблон для формирования названия события (TemplateLanguageVariable).

  4. Сформируйте список подстановок в шаблон названия события (SubstitutionName, Substitution).

    Если название события не имеет подстановок, массив 'params' должен быть оставлен пустым.

  5. Укажите идентификаторы типов пользователей, которые должны получать уведомление о событии (ReceiverId).

  6. Для каждого типа получателей укажите, каким образом им должны приходить уведомления (TransportId), и каким образом из данных о событии формируется отправляемое сообщение (MessageProvider).

Диспетчер событий

Диспетчер — системный компонент, который запускает события. Результат запуска события — отправка уведомлений получателям.

Диспетчер событий зарегистрирован в сервисе Tygh::$app['event.dispatcher'].

Как запустить событие

В тех местах, где требуется отправить уведомления, необходимо добавить вызов диспетчера событий:

Tygh::$app['event.dispatcher']->dispatch('EventId', $order_info, $user_info, $settings);

Сообщения

Сообщения формируются на основе события из данных, переданных в нём. Сообщения являются переносчиком информации между событием и транспортом, который будет отправлять уведомления о событии.

Примеры реализации:

  • \Tygh\Notifications\Messages\MailMessage — сообщение, отправляемое на почту;
  • \Tygh\Notifications\Messages\InternalMessage — сообщение, отправляемое в Центр уведомлений.

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

Примеры реализации:

  • Провайдер, создающий сообщение о состоянии заказа, отправляемое на почту администратора:

    \Tygh\Notifications\Messages\Order\OrderAdminMailMessage::createFromOrderForAdmin
    
  • Провайдер, создающий сообщение об одобрении товаров, показывающееся в Центре уведомлений продавца:

    \Tygh\Addons\VendorDataPremoderation\Notifications\Messages\PremoderationInternalMessage::createApprovedFromProducts
    

Как добавить собственное сообщение

Чтобы добавить сообщение:

  1. Создайте класс, реализующий интерфейс \Tygh\Notifications\Messages\IMessage или расширяющий существующий класс сообщений.
  2. Добавьте провайдер сообщения — фабричный метод в классе сообщения или метод в отдельной фабрике сообщений.
  3. Реализуйте провайдер сообщения — напишите всю необходимую логику получения данных, необходимых транспорту, из данных события (MessageProvider).
  4. Укажите этот провайдер в схеме событий для конкретного транспорта.

Как создать сообщение, отправляемое на почту

Такие сообщения содержат в себе набор данных, которые необходимы для отправки письма на электронную почту (выполняется через сервис Tygh::$app['mailer']).

Чтобы создать новое почтовое сообщение:

  1. Создайте класс, расширяющий \Tygh\Notifications\Messages\MailMessage.
  2. Реализуйте провайдер сообщения, который вернёт экземпляр класса-сообщения с заполненными свойствами:
    • $to — получатель сообщения;
    • $from — отправитель сообщения;
    • $reply_to — Reply-to сообщения;
    • $data — данные для подстановки в шаблон письма;
    • $template_code — код шаблона email-уведомления;
    • $legacy_template — название шаблона письма (используется, если в магазине выбран старый режим редактирования email-уведомлений);
    • $language_code — код языка, на котором отправляется письмо;
    • $company_id — идентификатор компании, от имени которой отправляется письмо;
    • $area — откуда отправляется письмо: из панели администрирования или из витрины.

Как создать сообщение, отправляемое в Центр уведомлений

Такие сообщения содержат в себе набор данных, которые необходимы для создания уведомлений в Центре уведомлений (выполняется через сервис Tygh::$app['notifications_center']).

Чтобы создать новое почтовое сообщение:

  1. Создайте класс, расширяющий \Tygh\Notifications\Messages\InternalMessage.

  2. Реализуйте провайдер сообщения, который вернёт экземпляр класса-сообщения с заполненными свойствами:

    • $title — заголовок уведомления;

    • $message — текст уведомления;

    • $severity — важность сообщения (см. \Tygh\Enum\NotificationSeverity);

    • $section — вкладка Центра уведомлений, на которой отображается уведомление;

    • $tag — тэг, которым будет отмечено уведомление;

    • $area — где показывать уведомление: в панели администрирования или на витрине;

    • $action_url — ссылка, по которой должен произойти переход при нажатии на уведомления;

    • $timestamp — время создания уведомления;

    • $recipient_search_method — способ поиска пользователей, для которых нужно создавать уведомления (см. \Tygh\Enum\RecipientSearchMethods).

      Доступны следующие способы поиска:

      • \Tygh\Enum\RecipientSearchMethods::USER_ID — по ID пользователя;
      • \Tygh\Enum\RecipientSearchMethods::UGERGROUP_ID — по ID пользовательской группы (уведомления будут созданы для всех пользователей в этой группе);
      • \Tygh\Enum\RecipientSearchMethods::EMAIL — по e-mail пользователя;
    • $recipient_search_criteria — критерий поиска пользователей:

      • для $recipient_search_method = \Tygh\Enum\RecipientSearchMethods::USER_ID — ID пользователя;
      • для $recipient_search_method = \Tygh\Enum\RecipientSearchMethods::UGERGROUP_ID — ID пользовательской группы;
      • для $recipient_search_method = \Tygh\Enum\RecipientSearchMethods::EMAIL — e-mail пользователя.

Транспорты

Транспорты выполняют непосредственно отправку сообщений конкретных типов.

Примеры реализации:

  • \Tygh\Notifications\Transports\MailTransport — отправляет сообщения на почту, работает с сообщениями \Tygh\Notifications\Messages\MailMessage.
  • \Tygh\Notifications\Transports\InternalTransport — отправляет сообщения в Центр уведомлений, работает с сообщениями \Tygh\Notifications\Messages\InternalMessage.

Как добавить собственный транспорт

Список идентификаторов транспортов, использующихся в системе, доступен через сервис Tygh::$app['event.transports_schema'].

Чтобы добавить собственный транспорт:

  1. Выберите идентификатор, под которым транспорт будет зарегистрирован в системе (TransportId).
  2. Создайте класс, реализующий интерфейс \Tygh\Notifications\Transports\ITransport.
  3. В методе getId() этого класса укажите выбранный идентификатор.
  4. Зарегистрируйте провайдер данного транспорта в Tygh::$app['event.transports.{TransportId}'].
  5. Создайте языковую переменную с идентификатором event.transport.TransportId и значением — названием транспорта.

Получатели

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

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

Как добавить собственного получателя

Список идентификаторов получателей доступен через сервис Tygh::$app['event.receivers_schema'].

Чтобы добавить новый тип получателей:

  1. Напишите обработчик хука get_notification_rules, добавив идентификатор получателя в массив $force_notification.
  2. Создайте языковую переменную с идентификатором event.receiver.ReceiverId и значением — названием типа получателей.
  3. Добавьте данных получателей в схему событий, указав транспорты, которыми данным получателям доставляются уведомления.

Настройки уведомлений

По умолчанию считается, что если событие присутствует в схеме событий Tygh::$app['event.events_schema'], то оно требует уведомления по всем транспортам для всех получателей. Для изменения этого поведения используются настройки уведомлений. Они описывают, какой получатель по какому транспорту должен получать уведомления при возникновении событий.

Важно

Настройки уведомлений задаются на странице Настройки → Уведомления для всей системы. Уведомления настраиваются для каждого типа получателей для каждого события по каждому из транспортов.

Страница настройки уведомлений отображает только актуальные данные. На ней не отображаются:

  • события без получателей;
  • получатели, не привязанные ни к каким событиям;
  • транспорты, не отправляющие событий никаким получателям.

Правила из данной таблицы сохраняются при изменении в базе данных в таблице notification_settings и доступны через сервис Tygh::$app['event.notification_settings'].

Перегрузка правил уведомлений

Перегрузки позволяют предотвратить отправку уведомлений о событии отдельным получателям, даже если того требуют настройки уведомлений.

Набор перегрузок представляет из себя объект класса \Tygh\Notifications\Settings\Ruleset и создаётся фабрикой правил Tygh::$app['event.notification_settings.factory']. Набор перегрузок передается одним из параметров при запуске события.

Пример: на странице редактирования заказа присутствует набор флагов об уведомлении покупателя, отдела по работе с заказами и продавца. Они позволяют предотвратить отправку сообщения об изменении заказа, даже если правила уведомлений этого явно требуют.

$notification_rules = Tygh::$app['event.notification_settings.factory']->create([
    UserTypes::CUSTOMER => false,
    UserTypes::ADMIN    => true,
    UserTypes::VENDOR   => true,
]);

Tygh::$app['event.dispatcher']->dispatch(
    'order.updated',
    $order_info,
    $notification_rules
);

Как начать использовать новую систему уведомлений

  1. Найдите в своих модулях все места, где электронные письма отправляются с помощью сервиса mailer (Tygh::$app['mailer']->send()) или устаревшего класса TyghMailer (\Tygh\Mailer::sendMail()).
  2. Создайте события для этих ситуаций — см. «Как добавить собственное событие».
  3. (опционально) Реализуйте альтернативный механизм оповещения, используя уведомления в Центре уведомлений.
  4. Замените отправку писем на запуск события через сервис event.dispatcher: Tygh::$app['event.dispatcher']->dispatch().