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

Примечание

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

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

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

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

Важно

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

События

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

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

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

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

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

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

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

(string) EventId => [
    'group' => (string) GroupId,
    'name' => [
        'template' => (string) TemplateLanguageVariable,
        'params' => [
            (string) SubstitutionName => (string) Substitution
            ...
        ],
    ],
    'data_provider' => (callable) DataProvider,
    'receivers' => [
        (string) ReceiverId => [
            (string) TransportId => BaseMessageSchema::create([
                'area'            => (string) area,
                'from'            => (string) from,
                'to'              => (callable) DataValue::create(key),
                'template_code'   => (string) template_code,
                ...
                'language_code'   => (callable) DataValue::create(parent_key.key, default_value),
                'data_modifier'   => (callable) function (array $data) {
                    return array_merge($data, $added_data_value);
                }
            ]),
            ...
        ],
        ...
    ],
],
  • EventId — идентификатор события. Он используется в качестве первого аргумента в \Tygh\Notifications\EventDispatcher::dispatch.
  • GroupId — идентификатор группы событий. Он используется на странице настроек уведомлений, для более удобной навигации.
  • TemplateLanguageVariable — имя языковой переменной, которая используется для обозначения события на странице настроек уведомлений.
  • SubstitutionName и Substitution — имя и значение параметров, используемых для адаптации языковой переменной под особенности события.
  • DataProvider — реализует интерфейс Notification\DataProviders\DataProvider используется для получения специфичных для события полей на основе data переданных в \Tygh\Notifications\EventDispatcher::dispatch.
  • ReceiverId — идентификатор получателя. Все существующие в системе идентификаторы получателей могут быть получены из Tygh::$app['event.receivers_schema']
  • TransportId — идентификатор транспорта. Транспорты должны предоставлять его в \Tygh\Notifications\Transports\ITransport::getId.
  • BaseMessageSchema — Создает инстанс класса схемы, с подготовленными для отправки данными. Входящие параметры должны содержать преобразованные данные, которые необходимы для отправки уведомления. Могут быть представлены как текст (area, from, template_code) или как инстанс класса DataValue.
  • DataValue - класс, позволяющий получить данные из входного массива по ключу. Если переданный ключ не содержится в массиве, то будет взято default_value, по умолчанию null.
  • data_modifier — этот callable-параметр позволяет в рамках функции выполнить дополнительные преобразования полей, переданных в data .

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

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

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

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

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

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

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

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

  6. Укажите название реализованного DataProvider для обработки специфичных для этого события данных, приходящих из data.

  7. Для каждого типа получателей укажите:

    • каким образом им должны приходить уведомления (TransportId);
    • данные, специфичные для текущего получателя, и преобразованные в инстанс класса BaseMessageSchema (с использованием DataValue, если необходимо).

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

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

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

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

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

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

Сообщения

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

Массив данных, подготовленных для отправки, получается на основании правил из схемы события events.php.

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

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

    'receivers' => [
        UserTypes::ADMIN => [
            MailTransport::getId() => MailMessageSchema::create([
                'area'            => 'A',
                'from'            => 'company_users_department',
                'to'              => 'company_users_department',
                'reply_to'        => DataValue::create('user_data.email'),
                'template_code'   => 'activate_profile',
                'legacy_template' => 'profiles/activate_profile.tpl',
                'company_id'      => DataValue::create('user_data.company_id'),
                'language_code'   => Registry::get('settings.Appearance.backend_default_language'),
                'data_modifier'   => function (array $data) {
                    return array_merge($data, [
                        'url' => fn_url('profiles.update?user_id=' . $data['user_data']['user_id'], 'A'),
                    ]);
                }
            ]),
        ],
    ],
    

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

За создание сообщения отвечает схема сообщения. Схема получает преобразованные данные о событии, проверяет их валидность.

Схема реализована для конкретного транспорта:

  • \Tygh\Notifications\Transports\Mail\MailMessageSchema — схема для сообщения, отправляемого на почту;
  • \Tygh\Notifications\Transports\Internal\InternalMessageSchema — схема для сообщения, отправляемого в Центр уведомлений.

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

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

  1. Добавьте провайдер для данных сообщения, реализующий интерфейс \Tygh\Notifications\DataProviders\IDataProvider или расширяющий существующий класс базового провайдера данных.
  2. Укажите этот провайдер в схеме событий для конкретного транспорта.
  3. Задайте в схеме событий правила для преобразования входящих данных, переданных в диспетчер.

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

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

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

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

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

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

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

  1. Задайте в схеме событий правила для подготовки данных, переданных в \Tygh\Notifications\Transports\Internal\InternalMessageSchema.

  2. Массив, переданный в метод create схемы, содержит следующий набор свойств:

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

      • template — имя языковой переменной;
      • params — список подстановок в шаблон заголовка уведомления; если название события не имеет подстановок, массив должен быть оставлен пустым;
    • message — текст уведомления;

      • template — имя языковой переменной;
      • params — список подстановок в шаблон текста уведомления; если название события не имеет подстановок, массив должен быть оставлен пустым;
    • 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\MailMailTransport — отправляет сообщения на почту; работает с сообщениями, удовлетворяющими схеме \Tygh\Notifications\Transports\Mail\MailMessageSchema.
  • \Tygh\Notifications\Transports\InternalTransport — отправляет сообщения в Центр уведомлений; работает с сообщениями, удовлетворяющими схеме \Tygh\Notifications\Transports\Internal\InternalMessageSchema.

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

Список идентификаторов транспортов, использующихся в системе, доступен через сервис 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().