Триггеры для Bitrix без привязки к конкретным событиям

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

AddEventHandler("sender",  "OnTriggerList",  ["EventListener", "onTriggerList"]);

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

use Bitrix\Main\Event;

class EventListener
{
 public static function OnTriggerList(Event $event): Event
    {
        Handlers\Sender\MyTrigger::addTriggerInList($event);

        return $event;
    }
 }

А вот сам код триггера, который надо обвешать нужной логикой.

namespace Handlers\Sender\MyTrigger;

use Bitrix\Main\Event;
use Bitrix\Main\Loader;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\EventResult;
use Bitrix\Sender\Trigger\TriggerConnectorClosed;

Loc::loadMessages(__FILE__);

Loader::includeModule('sender');

class MyTrigger extends TriggerConnectorClosed
{
    public static function addTriggerInList(Event &$event): Event
    {
        $event->addResult(new EventResult(0, [
            'TRIGGER' => [
                'Handlers\Sender\MyTrigger'
            ]
        ], 'my.module')); // Не передавать третье значение, если триггер находится не в модуле

        return $event;
    }

    public function getName(): string
    {
        return Loc::getMessage('TRIGGER_NAME');
    }

    public function getCode(): string
    {
        return 'my_trigger';
    }

    public static function canBeTarget(): bool
    {
        return false;
    }

    public function filter(): bool
    {
        $this->recipient = [];

        $field = $this->getFieldValue('FIELD') ?: null; // Получение переменных из формы создания триггера

       /*
        Тут какая-то логика по получению пользователей для рассылки
        */

        $this->recipient[] = [
            'EMAIL' => $user['EMAIL'],
            'NAME' => $user['NAME'],
            'USER_ID' =>  $user['ID'],
        ];

        if (!empty($this->recipient)) {
            return true;
        } else {
            return false;
        }
    }

    /*
    * Форма с опциями, при создании триггера, если нужна.
    */
    public function getForm(): string
    {
        $fieldLang = Loc::getMessage('FIELD');
        $fieldName = $this->getFieldName('FIELD');
        $fieldValue = htmlspecialcharsbx($this->getFieldValue('FIELD', ''));

        return <<HTML
                    {$fieldLang}
        HTML;
    }

    public function getRecipient()
    {
        return $this->recipient;
    }
}

Дополнительно не нужно забывать о нескольких вещах:

  • Триггеры такого типа создают агента. Его удобно использовать для дебага, а также можно руками поправить время запуска и его частоту, если необходим запуск триггера чаще чем раз в сутки.
  • Если в проекте используется composer или иной автолоад классов, и при этом агенты переведены на cron - путь к автолоадеру должен быть прописан абсолютный, так как переменная $_SERVER["DOCUMENT_ROOT"] пустая.