Событие перед изменением элемента инфоблока
[OnBeforeUpdateItem] Событие перед изменением элемента инфоблока
Событие OnBeforeUpdateItem вызывается перед обновлением конкретного элемента инфоблока через CIblockElement::Update(). Позволяет модифицировать данные, которые будут записаны в элемент.
Событие вызывается, только если модуль собрал для элемента хотя бы одно поле на обновление. На практике это почти каждый элемент порции: MODIFIED_BY добавляется всегда, когда в настройках задан пользователь, а ACTIVE, описания и раздел — часто без сравнения с текущим значением (подробности ниже).
- Исключение из обработчика модуль не перехватывает — оно обрывает шаг импорта. Оборачивайте код в
try/catch. - Параметры последнего обработчика, вернувшего
EventResult::SUCCESS, целиком заменяютarUpdateItemFields. Ответы не сливаются: каждый обработчик получает исходный массив модуля. EventResult::ERRORигнорируется — отменить обновление им нельзя.- Возврат пустого массива тоже не отменяет обновление: модуль всё равно вызовет
CIBlockElement::Update()с пустым набором полей и посчитает элемент обновлённым. SUCCESSбез параметров даётnull, который уходит вCIBlockElement::Update(). Всегда возвращайте полный массив, а если менять нечего — не возвращайте ничего.
- Описание события
- Пример кода
Параметры события
| Параметр | Тип | Описание |
|---|---|---|
entity | string | Сущность в МойСклад: product, variant, bundle, service |
currentItem | array | Данные о текущем элементе (содержит BX и MS) |
arUpdateItemFields | array | Массив данных для передачи в CIblockElement::Update() |
Структура currentItem
[
'BX' => [ // элемент инфоблока Битрикс
'ID' => 1234,
'IBLOCK_ID' => 5,
'NAME' => 'Название товара',
'XML_ID' => 'abc123externalcode',
'ACTIVE' => 'Y',
'CODE' => 'nazvanie-tovara',
'SORT' => 500,
'PREVIEW_TEXT' => 'Краткое описание',
'DETAIL_TEXT' => 'Подробное описание',
'PREVIEW_PICTURE' => 100,
'DETAIL_PICTURE' => 101,
'PREVIEW_TEXT_TYPE' => 'text',
'DETAIL_TEXT_TYPE' => 'html',
// у каждого поля есть пара с тильдой: '~NAME', '~DETAIL_TEXT' и т.д.
],
'MS' => $itemMs // объект из МойСклад, доступ к полям через свойства
]
BXМодуль выбирает только поля из примера выше — IBLOCK_SECTION_ID и других полей элемента в массиве нет. Строки получены через GetNext(): значения HTML-экранированы, исходные лежат под ключами с тильдой (~NAME, ~DETAIL_TEXT).
Структура ms-объекта (currentItem['MS'])
$item = $currentItem['MS'];
$item->name // 'Название товара'
$item->externalCode // 'abc123externalcode'
$item->archived // false
$item->description // 'Описание товара'
$item->weight // 0.5
$item->article // 'ART-001'
$item->variantsCount // 3 (для product)
$item->attributes // массив доп. атрибутов МС
$item->images // массив изображений
$item->productFolder // объект с meta->href группы товаров
Структура arUpdateItemFields
Содержит поля, собранные модулем по опциям обновления сущности. Сравнение с текущим значением есть не у всех полей — отсутствие поля в массиве не значит, что оно не изменилось, а присутствие не значит, что изменилось:
[
'MODIFIED_BY' => 1, // всегда, если в настройках задан пользователь
'NAME' => 'Новое название', // если изменилось имя
'ACTIVE' => 'N', // см. ниже
'IBLOCK_SECTION_ID' => 15, // ID раздела или false — «вне разделов»
'SORT' => 100, // если изменилось значение поля сортировки
'PREVIEW_TEXT' => 'Новое описание', // без сравнения, см. ниже
'PREVIEW_TEXT_TYPE' => 'html', // 'text' или 'html', если тип задан в настройках
'DETAIL_TEXT' => 'Новое полное описание', // без сравнения, см. ниже
'DETAIL_TEXT_TYPE' => 'html',
'CODE' => 'novoe-nazvanie', // если включена опция обновления символьного кода
'PREVIEW_PICTURE' => [...], // массив для CFile или ['del' => 'Y']
'DETAIL_PICTURE' => [...], // массив для CFile или ['del' => 'Y']
]
Как собираются поля:
ACTIVE— если активность управляется доп. полем МойСклад, ставится всегда:'Y', когда поле отмечено, иначе'N'. Иначе при опции архивности —'N'для архивного и'Y'для разархивированного товара; при опции активации по фильтру —'Y'для неактивного элемента. При опции «игнорировать активность» не ставится.IBLOCK_SECTION_ID— при опции обновления группы;false, если раздел для группы не найден. Текущий раздел элемента модуль не выбирает, поэтому найденный раздел попадает в массив практически всегда (кроме случая, когда включено сохранение нескольких разделов и элемент уже в нескольких).PREVIEW_TEXT/DETAIL_TEXT— ставятся без сравнения с текущим текстом: всегда, когда источник описания непуст, а при опции удаления описаний — и пустой строкой.CODE— при опции обновления символьного кода: транслит названия, при опции уникальности дополненный_<ID>при совпадении с другим элементом; ставится, только если отличается от текущего.PREVIEW_PICTURE/DETAIL_PICTURE— массив файла, если картинка в МойСклад сменилась;['del' => 'Y'], если картинок в МойСклад нет и включено удаление картинок.
Возвращаемое значение
Верните EventResult::SUCCESS с полным модифицированным массивом $arUpdateItemFields. Этот массив будет передан в CIblockElement::Update().
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, $arUpdateItemFields);
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'rbs.moyskladstocks',
'OnBeforeUpdateItem',
'OnBeforeUpdateItemHandler'
);
function OnBeforeUpdateItemHandler(\Bitrix\Main\Event $event)
{
$eventParams = $event->getParameters();
$entity = $eventParams['entity']; //сущность в МойСклад, которая обрабатывается (четыре варианта значения: product / variant / bundle / service)
$currentItem = $eventParams['currentItem']; //данные о текущем элементе, подробнее ниже
$itemBx = $currentItem['BX']; //текущий элемент инфоблока, доступ к полям через массив
$item = $currentItem['MS']; //этот же товар из МС, доступ к полям через поля объекта
// Структура currentItem:
// [
// 'BX' => [ // элемент инфоблока Битрикс
// 'ID' => 1234,
// 'IBLOCK_ID' => 5,
// 'NAME' => 'Название товара',
// 'XML_ID' => 'abc123externalcode',
// // ... другие поля элемента инфоблока
// ],
// 'MS' => $itemMs // объект из МойСклад
// ]
//это массив данных, которые затем передаются в CIblockElement::Update();
$arUpdateItemFields = $eventParams['arUpdateItemFields'];
//можно модифицировать массив '$arUpdateItemFields' и затем его вернуть в качестве успеха события
//например сделаем элемент не активным
//$arUpdateItemFields['ACTIVE'] = 'N';
//Отправляем \Bitrix\Main\EventResult::SUCCESS для записи изменений в элемент инфоблока
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, $arUpdateItemFields);
}