На сайте клиента должны появляться все нововведения, пришедшие в обновлениях продукта.
Доработки должны быть максимально изолированы от процесса импорта. Чтобы можно было их отключить, подтвердить, что проблема не у нас на канале, и отправить баг-репорт в саппорт.
Работы по мержингу доработок с обновлённым сайтом должны либо отсутствовать, либо быть минимальными в особо критичных ситуациях.
Из этих требований вытекают условия — совсем не трогать класс CIBlockCMLImport и стараться не трогать catalog.import.1c. Практически во всех наших задачах этого можно достичь с помощью обработчиков.
iblock.OnStartIBlockElementAdd / iblock.OnStartIBlockElementUpdate Знакомые, наверное, почти каждому события. Вызываются перед добавлением/обновлением элемента инфоблока до валидации полей и свойств, первым аргументом передаётся &$arFields. С помощью них можно назначать обязательные, но отсутствующие значения характеристик товаров, давать уникальные символьные коды по своим алгоритмам и менять привязку к разделам.
iblock.OnAfterIBlockElementAdd / iblock.OnAfterIBlockElementUpdate События вызываются после создания/обновления элемента инфоблока. В обработчик первым аргументом передаётся &$arFields. При использовании OnAfterIBlockElementAdd стоит помнить, что оно вызывается в любом случае — хоть при успешно созданном элементе, хоть при ошибке. Поэтому надо обязательно проверять ключ RESULT и корректировать логику в зависимости от него. Через эти обработчики можно производить действия постфактум — создать вспомогательные записи в БД, что-то где-то обновить и т.п. Например, создать элемент в ИБ «Производители» и привязать к нему товар, если в выгрузке значение свойства — строка, а не ссылка на справочник. Или пронаследовать некоторые характеристики всех торговых предложений в основной товар для более быстрой фильтрации в каталоге.
catalog.OnSuccessCatalogImport1C Самое вкусное оставил напоследок. Данное событие появилось около года назад. Вызывается оно в компоненте catalog.import.1c в самом конце импорта — перед отдачей строки success, сигнализирующей 1Ске об успешном окончании обмена. С помощью этого события можно организовать пост-обработку импортированных товаров/ТП - перегенерировать неуправляемый кеш, вычислить диапазон цен для товара с торговыми предложениями, импортировать скидки как нативные битриксовые скидки. Стоит заметить, что на этом шаге весь xml-файл ещё доступен в таблице b_xml_tree, поэтому потенциал события огромен. А если прибавить к этому ещё и возможность реализации пошаговости, то можно сделать свой маленький изолированный импорт без каких-либо модификаций основного так, что 1Ска ничего и не заподозрит:-) Собственно, это событие и его обсуждение тут и сподвигло написать данный пост — показать, как можно на основе этого события реализовать пошаговость. Пример (с подсветкой):
AddEventHandler('catalog', 'OnSuccessCatalogImport1C', 'customCatalogImportStep');
function customCatalogImportStep()
{
$stepInterval = (int) COption::GetOptionString("catalog", "1C_INTERVAL", "-");
$startTime = time();
// Флаг импорта файла торговых предложений
$isOffers = strpos($_REQUEST['filename'], 'offers') !== false;
$NS = &$_SESSION["BX_CML2_IMPORT"]["NS"];
if (!isset($NS['custom']['lastId'])) {
// Последний отработанный элемент для пошаговости.
$NS['custom']['lastId'] = 0;
$NS['custom']['counter'] = 0;
}
// Условия выборки элементов для обработки
$arFilter = array(
'IBLOCK_ID' => 1024,
'ACTIVE' => 'Y',
);
$res = CIBlockElement::GetList(array('ID' => 'ASC'), array_merge($arFilter, array('>ID' => $NS['custom']['lastId'])));
$errorMessage = null;
while ($arItem = $res->Fetch()) {
/*
// Что-нибудь делаем
if (updateElement($arItem['ID']) === false) {
$error = true;
}
*/
if ($error === true) {
$errorMessage = 'Что-то случилось.';
break;
}
$NS['custom']['lastId'] = $arItem['ID'];
$NS['custom']['counter']++;
// Прерывание по времени шага
if ($stepInterval > 0 && (time() - $startTime) > $stepInterval) {
break;
}
}
if ($arItem != false) {
if ($errorMessage === null) {
print "progress\n";
print "Обработано " . $NS['custom']['counter'] . ' элементов, осталось ' . $res->SelectedRowsCount();
} else {
print "failure\n" . $errorMessage;
}
$contents = ob_get_contents();
ob_end_clean();
if (toUpper(LANG_CHARSET) != "WINDOWS-1251") {
$contents = $GLOBALS['APPLICATION']->ConvertCharset($contents, LANG_CHARSET, "windows-1251");
}
header("Content-Type: text/html; charset=windows-1251");
print $contents;
exit;
}
}
В примере происходит выборка из некоего инфоблока и совершение действий над элементами этого инфоблока. Если при обновлении произошла ошибка, 1Ске вернётся статус failure с текстом ошибки. Если всё успешно прошло, происходит выход из обработчика и компонент catalog.import.1c завершает работу (обнуляет сессию и возвращает success).
Заключение Вот как-то так мы и работаем с 1ской — пишем тз, рисуем таблички, генерим примеры и изворачиваемся подобными способами в особых ситуациях:-)
День добрый. Подскажите пожалуйста. В 1Ске позиции поменяю на Снят с продажи, но на сайт все равно данные позиции, после обмена попадают активными, помечаю, на удаление, тоже не спасает особо. Ни программист 1С ни программисты на сайте не могут мне, помочь, как корректно выгружать данные из 1С на сайт(
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».