Событие регистрации внешних агентов
[OnBuildAgentList] Свой агент в настройках модуля
На более ранних версиях событие не вызывается: внешний агент приходилось ставить своим CAgent::AddAgent() и рисовать для него блок состояния самостоятельно.
Событие позволяет добавить в модуль собственный агент — например импорт партий или любой другой периодический обмен с МойСклад, написанный в вашем модуле. Зарегистрированный агент модуль обслуживает так же, как свои:
- на странице настроек у него появляется блок агента — такой же, как у штатных: переключатель «включён», интервал, вкладки «Параметры» и «Информация», ID агента, время последнего и следующего запуска, кнопка сохранения параметров без общего «Сохранить»;
- в блок можно вывести свои параметры агента;
- модуль сам ставит и снимает агента в планировщике Битрикс при включении и выключении в блоке;
- галка «запускать по cron» уводит агента в общий cron-скрипт модуля (
cron/run_all.php); - состояние агента и его собственные опции не стираются при сохранении настроек модуля.
Модуль не решает, где показать блок: его выводит ваш код на своей вкладке, добавленной через OnBeforeAllOptionsBuild, вызовом OptionUtils::buildAgentOptionArray() (см. вкладку «Блок агента на вкладке»).
Событие вызывается на странице настроек и в каждом cron-хите модуля — один раз за хит, дальше модуль берёт результат из своего кеша. Обработчик должен только вернуть описание: без запросов к API МойСклад и тяжёлых выборок.
- Описание события
- Метод агента
- Блок агента на вкладке
- Пример кода
Параметры события
Событие не передаёт параметров.
Возвращаемое значение
EventResult::SUCCESS с ключом agents — списком описаний агентов:
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'agents' => [
[
'id' => 'my_consignment',
'name' => 'Импорт партий',
'callable' => '\My\Module\ConsignmentImport::agent',
'ready' => true,
'ready_message' => 'Импорт партий выключен на вкладке «Партии»',
'options' => ['ag_my_consignment_pages', 'my_consignment_last_sync'],
],
],
]);
Поля описания агента
| Поле | Обязательное | Тип | Описание |
|---|---|---|---|
id | да | string | Идентификатор агента: латиница, цифры, _. От него строятся имена опций агента ag_{id}_* |
name | да | string | Подпись блока агента на странице настроек |
callable | да | string | Статический метод агента в виде \Класс::метод — без скобок и аргументов |
ready | нет | bool | callable | Готов ли агент к работе. false — в блоке выводится предупреждение. Можно передать функцию, возвращающую bool; исключение из неё считается «не готов». По умолчанию true |
ready_message | нет | string | Текст предупреждения, когда агент не готов |
options | нет | string[] | Полные имена собственных опций агента: латиница, цифры, _ |
Ключи, которых нет в таблице, модуль не трогает и хранит в описании как есть.
Проверка описаний
- Описание, в котором не прошло проверку любое из полей
id,name,callable,ready,options, отбрасывается молча — остальные агенты при этом регистрируются. id, совпадающий со штатным агентом модуля (product,stocks,discountи т. д.), отбрасывается: штатный агент приоритетнее.- При повторе
idу двух описаний учитывается первое. - Учитываются только ответы с типом
EventResult::SUCCESS. - Исключение из обработчика модуль перехватывает: описания обработчиков, зарегистрированных до него, читаются как обычно, обработчики после него не вызываются.
Как модуль вызывает агента
В планировщик Битрикс агент ставится с номером профиля обмена, как и штатные агенты модуля:
\My\Module\ConsignmentImport::agent(0);
где 0 — номер профиля. Значит, метод агента:
- принимает номер профиля первым аргументом;
- как любой агент Битрикс, возвращает строку своего вызова, иначе планировщик его удалит;
- сам переключает модуль на свой профиль, если работает с его настройками или API.
namespace My\Module;
class ConsignmentImport
{
public static function agent($profileId = 0)
{
\Rbs\MoyskladStocks\Config::setProfileId((int)$profileId);
if (\Rbs\MoyskladStocks\Config::checkFeature('modulesync')) {
// Логика импорта — на стороне разработчика
self::importStep();
}
return '\\' . __METHOD__ . "({$profileId});";
}
}
Запуск по cron
Если в блоке агента включена галка «запускать по cron», cron/run_all.php вызывает внешний агент после всех штатных тем же правилом, что и их, — callable с номером профиля. Исключение агента перехватывается и не мешает остальным.
Какие опции модуль хранит за агента
| Опция | Что это |
|---|---|
ag_{id}_enabled, ag_{id}_interval, ag_{id}_is_cron и др. | Параметры блока агента — их модуль сохраняет сам |
ag_{id}_offset, ag_{id}_last, ag_{id}_last_full, ag_{id}_tag, ag_{id}_full_once, ag_{id}_pass_start | Состояние агента. Переживает кнопку «Сохранить» в настройках модуля |
имена из options | Собственные опции агента. Сохраняются кнопкой блока агента и тоже переживают «Сохранить» |
Опции читаются и пишутся через \Rbs\MoyskladStocks\Config::getOption() / Config::setOption() — с учётом текущего профиля.
Блок агента выводится вызовом OptionUtils::buildAgentOptionArray() внутри обработчика OnBeforeAllOptionsBuild. Последний, шестой аргумент $extraOptions — строки собственных параметров агента в формате $arAllOptions: они выводятся внутри блока, после штатных параметров.
\Rbs\MoyskladStocks\Internals\OptionUtils::buildAgentOptionArray(
$localTab, // массив строк вкладки, куда дописывается блок
$agentId, // id агента из OnBuildAgentList
$paramsCheckBox, // '' или 'disabled' — только чтение
$withHeader, // true — выводить заголовок «Настройка агента "..."»
$disabledOptions, // штатные параметры, которые не нужно показывать
$extraOptions // строки своих параметров агента
);
Штатные параметры блока, которые можно скрыть через $disabledOptions: enabled, interval, is_cron, limit, offset, updated, full_once, full_time, last_update, last_full_update.
Свои параметры. Строка вида ['имя_опции', 'Подпись', 'значение_по_умолчанию', ['тип', ...]], где тип — checkbox, text, number или selectbox; строка-заголовок тоже допускается. Чтобы кнопка сохранения в блоке агента записала параметр, его полное имя должно быть перечислено в options описания агента: необъявленные имена модуль не сохраняет.
//Пример кода нужно вставить в файл init.php
$eventManager = \Bitrix\Main\EventManager::getInstance();
// 1. Регистрируем агента
$eventManager->addEventHandler(
'rbs.moyskladstocks',
'OnBuildAgentList',
'OnBuildAgentListHandler'
);
function OnBuildAgentListHandler(\Bitrix\Main\Event $event)
{
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'agents' => [
[
'id' => 'my_consignment',
'name' => 'Импорт партий',
'callable' => '\My\Module\ConsignmentImport::agent',
// готовность можно вычислять — модуль вызовет функцию сам
'ready' => static function () {
return \Rbs\MoyskladStocks\Config::getOption('my_consignment_on', 'N') === 'Y';
},
'ready_message' => 'Импорт партий выключен на вкладке «Партии»',
'options' => ['ag_my_consignment_pages'],
],
],
]);
}
// 2. Выводим блок агента на своей вкладке
$eventManager->addEventHandler(
'rbs.moyskladstocks',
'OnBeforeAllOptionsBuild',
'MyConsignmentTabHandler'
);
function MyConsignmentTabHandler(\Bitrix\Main\Event $event)
{
$arAllOptions = $event->getParameter('arAllOptions');
$aTabs = $event->getParameter('aTabs');
$arAllOptions['my_consignment_tab'][] = 'Партии';
$arAllOptions['my_consignment_tab'][] = ['my_consignment_on', 'Импортировать партии', 'N', ['checkbox']];
\Rbs\MoyskladStocks\Internals\OptionUtils::buildAgentOptionArray(
$arAllOptions['my_consignment_tab'],
'my_consignment',
'',
true,
['full_once', 'full_time'],
[
['ag_my_consignment_pages', 'Страниц за запуск', '5', ['text', 5]],
]
);
$aTabs[] = [
'DIV' => 'my_consignment_tab',
'TAB' => 'Партии',
'ICON' => 'main_settings',
'TITLE' => 'Импорт партий',
];
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'arAllOptions' => $arAllOptions,
'aTabs' => $aTabs,
]);
}
Если ваш код должен работать и на версиях до 3.9.0, проверяйте наличие метода \Rbs\MoyskladStocks\Agent::resolveFunctionName(). Его нет — ставьте агента своим CAgent::AddAgent(), как раньше.
$hasAgentRegistry = method_exists('\Rbs\MoyskladStocks\Agent', 'resolveFunctionName');