Модуль "Яндекс.Маркет для продавцов" является бесплатным и часто используется не только для интеграции с Яндекс.Маркетом, но и вообще для формирования самых разных yml-фидов. При этом документации для его api не так много.
В примерах ниже используется два события модуля yandex.market: onExportOfferExtendData и onExportOfferWriteData.
Событие onExportOfferExtendData срабатывает на этапе формирования данных для записи в XML. В нем можно модифицировать данные, которые заданы в настройках выгружаемого прайс-листа. Но все модификации будут далее валидироваться модулем и поэтому нельзя модифицировать данные таким образом, чтобы они не соответствовали бы требованиям самого модуля. К примеру, через это событие нельзя убрать цену у товара - такой offer просто не будет добавлен в итоговый файл.
Событие onExportOfferWriteData срабатывает на этапе записи offer в XML. По сути, здесь мы работаем с XML-объектом и можно сказать, что модифицируем сам текст yml-фида. В итоге, здесь мы ограничены только требованиями валидности самого XML. Здесь мы можем обходить требования модуля к фиду.
В примерах ниже используется $context["SETUP_ID"]. В нем содержится ID прайс-листа в модуле. Если вам требуется внести изменения только в какой-то конкретный фид, то вы можете это сделать условием по данному значению. Если же изменение должно попасть во все прайс-листы, то просто уберите данное условие.
Для получения названия прайс-листа можно использовать следующий код:
$setup = Yandex\Market\Export\Setup\Model::loadById($context["SETUP_ID"]);
$setupName = $setup->getField('NAME');
Примеры использования onExportOfferExtendData
Добавить обязательный тег, если значение не заполнено
К примеру, нужно, чтобы тег был бы обязательно заполнен, но не у всех товаров каталога заполнен производитель. Мы его должны заполнить значением по умолчанию.
$eventManager = Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('yandex.market', 'onExportOfferExtendData', function(Bitrix\Main\Event $event) {
$tagValueList = $event->getParameter('TAG_VALUE_LIST');
$context = $event->getParameter('CONTEXT');
if($context["SETUP_ID"] == 24) {//Это ИД прайс-листа
foreach ($tagValueList as $elementId => $tagValue) {
$vendorValue = $tagValue->getTagValue('vendor');
if (empty($vendorValue)) {
$tagValue->addTag('vendor', 'ООО Рога и Копыта');
}
}
}
});
Поменять атрибут тега
К примеру, товар с единичным остатком в фиде должен отображаться как недоступный.
$eventManager = Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('yandex.market', 'onExportOfferExtendData', function(Bitrix\Main\Event $event) {
$tagValueList = $event->getParameter('TAG_VALUE_LIST');
$context = $event->getParameter('CONTEXT');
if($context["SETUP_ID"] == 9) {//Это ИД прайс-листа
foreach ($tagValueList as $elementId => $tagValue) {
$productAmount = _getProductAmount($elementId);//некая функция, возвращающая остаток товара с ИД = $elementId
if($productAmount == 1) {
$tagValue->setTagAttribute('offer', 'available', 'false');
}
}
}
});
Поменять значение тега
В примере ниже приведены три ситуации, когда требуется модификация содержимого фида.
Во-первых, у товара есть розничная цена и цена для маркетплейса. В фиде мы настроили выгрузку розничной цены, но если установлена специальная цена для маркетплейса, то требуется указать её.
Во-вторых, у ряда товаров описания в виде текста. При выгрузке в yml-фид переносы строк теряются, нужно их задать тегом переноса строки.
В-третьих, название в выгрузке должно отличаться от названия товара на сайте.
$eventManager = Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('yandex.market', 'onExportOfferExtendData', function(Bitrix\Main\Event $event) {
$tagValueList = $event->getParameter('TAG_VALUE_LIST');
$context = $event->getParameter('CONTEXT');
if($context["SETUP_ID"] == 11) {//Это ИД прайс-листа
foreach ($tagValueList as $elementId => $tagValue) {
//begin: замена цены
$wb_price = 0;
$resWb = CPrice::GetList([],["PRODUCT_ID" => $elementId, "CATALOG_GROUP_ID" => 4]);//Это ИД нужного типа цен
if ($arrWb = $resWb->Fetch()) {
$wb_price = $arrWb["PRICE"];
}
if($wb_price > 0) {
$tagValue->setTagValue('price', $wb_price);
}
//end: замена цены
//begin: вернуть переносы строк
$res = CIBlockElement::GetList([], ['ID'=>$elementId], false, Array("nTopCount"=>1), ['DETAIL_TEXT', 'DETAIL_TEXT_TYPE']);
if($row = $res->GetNext()){
if($row['DETAIL_TEXT_TYPE'] == "text")
$tagValue->setTagValue('description', nl2br($row['~DETAIL_TEXT']));
}
//end: вернуть переносы строк
//begin: заменить название товара
$catalog_iblock_id = 11;//Это ИД инфоблока товаров
$db_props = CIBlockElement::GetProperty($catalog_iblock_id, $elementId, array("sort" => "asc"), Array("CODE"=>"WB_NAME"));
if($ar_props = $db_props->Fetch()) {
if($ar_props["VALUE"] != "") {
$tagValue->setTagValue('name', $ar_props['VALUE']); }
}
//end: заменить название товара
}
}
});
Примеры использования onExportOfferWriteData
Удалить обязательный тег из прайс-листа
Некоторые теги, к примеру, price - обязательны в модуле и не могут быть исключены из фида. Удалить такой тег можно следующим образом.
$eventManagerYml = Bitrix\Main\EventManager::getInstance();
$eventManagerYml->addEventHandler('yandex.market', 'onExportOfferWriteData', function(Bitrix\Main\Event $event) {
$tagResultList = $event->getParameter('TAG_RESULT_LIST');
$elementList = $event->getParameter('ELEMENT_LIST');
$context = $event->getParameter('CONTEXT');
if($context["SETUP_ID"] == 8) {//Это ИД прайс-листа
foreach($tagResultList as $elementId => $tagResult) {
if($tagResult->isSuccess()) {
$tagNode = $tagResult->getXmlElement();
$dom=dom_import_simplexml($tagNode->xpath('//price')[0]);
$dom->parentNode->removeChild($dom);
}
}
}
});
Убрать ограничение на длину описания
По умолчанию в описании 3000 символов. Кроме того, удаляются html-теги таблиц и многие другие теги. Допустимые теги: <b><br><p><ol><ul><li><div><h1><h2><h3><h4><h5><h6></b>.
Использовать onExportOfferExtendData не получится, так как после замены описания оно будет модифицировано самими модулем в соответствии с указанными выше параметрами по умолчанию.
$eventManagerYml = Bitrix\Main\EventManager::getInstance();
$eventManagerYml->addEventHandler('yandex.market', 'onExportOfferWriteData', function(Main\Event &$event) {
$tagResultList = $event->getParameter('TAG_RESULT_LIST');
$elementList = $event->getParameter('ELEMENT_LIST');
$context = $event->getParameter('CONTEXT');
if($context["SETUP_ID"] == 2 || $context["SETUP_ID"] == 3) {//Это ИД прайс-листа
foreach($tagResultList as $elementId => $tagResult) {
if($tagResult->isSuccess()) {
$tagNode = $tagResult->getXmlElement();
if (strpos($tagNode->description, 'YANDEX_MARKET_XMLNODE_REPLACE') !== false) {
$i = preg_split("/YANDEX_MARKET_XMLNODE_REPLACE_/", $tagNode->description)[1];
$tagResult->addReplace('<![CDATA['.$elementList[$elementId]['DETAIL_TEXT'] .']]>', $i);
}
}
}
}
});
Добавить свои теги в yml-фид
В СберМегаМаркет нужно было передавать остатки товара через тег outlets.
$eventManagerYml = Bitrix\Main\EventManager::getInstance();
$eventManagerYml->addEventHandler('yandex.market', 'onExportOfferWriteData', function(Main\Event &$event) {
$tagResultList = $event->getParameter('TAG_RESULT_LIST');
$elementList = $event->getParameter('ELEMENT_LIST');
$context = $event->getParameter('CONTEXT');
if($context["SETUP_ID"] == 2 || $context["SETUP_ID"] == 3) {//Это ИД прайс-листа
foreach($tagResultList as $elementId => $tagResult) {
if($tagResult->isSuccess()) {
$tagNode = $tagResult->getXmlElement();
$outlets = $tagNode->addChild('outlets');
$outlet = $outlets->addChild('outlet');
$outlet->addAttribute('id', 0);
$outlet->addAttribute('instock', _getProductAmount($elementId));//_getProductAmount($elementId) - некая функция, возвращающая остаток товара
$tagResult->invalidateXmlContents();
}
}
}
});
Поменять значение атрибута тега
Раньше модуль не позволял задать нечисловое значение атрибута id у тега offer, а была потребность указать в этом атрибуте артикул товара.
Сейчас это реализуется настройками прайс-листа, но, возможно, пример ниже поможет в решении другой задачи.
Кроме того, в примере есть получение значения тега, что тоже может пригодиться.
$eventManagerYml = Bitrix\Main\EventManager::getInstance();
$eventManagerYml->addEventHandler('yandex.market', 'onExportOfferWriteData', function(Main\Event &$event) {
$tagResultList = $event->getParameter('TAG_RESULT_LIST');
$elementList = $event->getParameter('ELEMENT_LIST');
$context = $event->getParameter('CONTEXT');
if($context["SETUP_ID"] == 2 || $context["SETUP_ID"] == 3) {//Это ИД прайс-листа
foreach($tagResultList as $elementId => $tagResult) {
if($tagResult->isSuccess()) {
$tagNode = $tagResult->getXmlElement();
$article = $tagNode->vendorCode->__toString();//Получаем значение из тега vendorCode
if($article)
$tagNode['id'] = $article;
$tagResult->invalidateXmlContents();
}
}
}
});
