1С-Битрикс. Модифицирование таблицы товаров в форме заказа в админке
Речь пойдёт о новом сконвертированном магазине и новой форме просмотра/редактирования заказа в нём.
Суть задачи в том, что фотографии товаров хранятся не в привычных свойствах битрикса, а в собственном CDN.
Получается, что нам нужно как-то вмешаться в рендер таблицы товаров в форме заказа и подменить «Нет фото» на полученные фотографии из CDN.
Первым делом я, конечно, написал техническую поддержку 1С-Битрикс с вопросом: есть ли такая возможноть. На что проследовал ответ:
На самом деле ответ был предсказуем. Тп не всегда компетентна в новом функционале.
Что ж, можно забить и наговнокодить на том же jquery: при загрузке подменять ячейки таблицы с картинками на свои.
Но я обычно надеюсь, что разработчики всё-таки предусматривают расширение функционала партнёрами и это просто не документировано. За подсказками сходим в код страницы формы заказа. Ура, такая возможность нашлась :) Выглядит она в виде метода BX.Sale.Admin.OrderEditPage.registerFieldsUpdaters()
Нам остаётся написать и подвесить наш класс-обработчик на 2 события OnAdminSaleOrderView и OnAdminSaleOrderEdit. В нём мы получим адреса картинок и заменим их в объекте данных с товарами. Код обработчика ниже.
Класс обработчика
/** * Created by olegpro.ru. * User: Oleg Maksimenko <ya@olegpro.ru> * Date: 15.10.2016 0:08 */ namespace Olegpro\Handler\Admin; use CatalogHelper; use Bitrix\Sale\Order; use Bitrix\Main\Loader; use Bitrix\Sale\BasketItem; use Bitrix\Main\Page\Asset; use Bitrix\Main\Page\AssetLocation; use Bitrix\Main\Web\Json; class OrderPage { /** * @param int $id */ public static function onAdminSaleOrder($id) { /** @var Order $order */ if ( $id <= 0 || !(Loader::includeModule('sale') && Loader::includeModule('iblock')) || ($order = Order::load($id)) === null ) { return; } $productsData = []; /** @var BasketItem $basketItem */ foreach ($order->getBasket()->getBasketItems() as $basketItem) { $productsData[$basketItem->getProductId()] = []; } if (sizeof($productsData) <= 0) { return; } $elementIterator = \CIBlockElement::GetList( [], [ 'ID' => array_keys($productsData), ], false, false, [ 'ID', 'IBLOCK_ID', 'PROPERTY_NOMCODE' ] ); while ($element = $elementIterator->Fetch()) { $productsData[$element['ID']]['IMAGE'] = CatalogHelper::getProductPicture( $element['PROPERTY_NOMCODE_VALUE'], 'h100', false, [ 'width' => 80, 'height' => 80 ] ); } Asset::getInstance()->addString( "<script> BX.ready(function () { BX.Sale.Admin.OrderEditPage.registerFieldsUpdaters({ 'BASKET': function (basket) { if (!!basket.ITEMS) { var customDataProducts = " . Json::encode($productsData) . " || {}; if (customDataProducts) { for(var i in basket.ITEMS) { if(basket.ITEMS.hasOwnProperty(i)) { if ( !!customDataProducts[basket.ITEMS[i].PRODUCT_ID] && !!customDataProducts[basket.ITEMS[i].PRODUCT_ID].IMAGE && !!customDataProducts[basket.ITEMS[i].PRODUCT_ID].IMAGE.src ) { basket.ITEMS[i].PICTURE_URL = customDataProducts[basket.ITEMS[i].PRODUCT_ID].IMAGE.src; } } } } } } }); }); </script>", AssetLocation::AFTER_JS ); } }
Функция CatalogHelper::getProductPicture как раз и возвращаем нам адрес картинки из CDN по артикулу товара.
Сохраняем класс-обработчика в файл /local/php_interface/classes/handler/admin/OrderPage.php
Добавляем в /local/php_interface/init.php
\Bitrix\Main\Loader::registerAutoLoadClasses(null, array( '\Olegpro\Handler\Admin\OrderPage' => '/local/php_interface/classes/handler/admin/OrderPage.php', )); $eventManager = \Bitrix\Main\EventManager::getInstance(); $eventManager->addEventHandler( 'main', 'OnAdminSaleOrderView', ['\Olegpro\Handler\Admin\OrderPage', 'onAdminSaleOrder'] ); $eventManager->addEventHandler( 'main', 'OnAdminSaleOrderEdit', ['\Olegpro\Handler\Admin\OrderPage', 'onAdminSaleOrder'] );
Здесь мы добавляем класс в автозагрузку и начинаем слушать 2 события.
8 комментариев
Смешно читать фразы про наговнокодить на jquery смотря на ваше решение.
Разрабы битрикса конечно тупорылые - вместо того чтобы предоставить нормальные способы взаимодействия через js - лепят какие то велосипеды. Менять dom через js это как раз нормально и идиоиматично.
Имелось в виду, что нормального решения в текущей ситуации нет. Можно было на js пройтись по таблице товаров, каким-то образом вытащить id товаров и подменить картинку на свою. А jquery тут лишь сократит количество кода. Так как dom может меняться от релиза к релизу, то такой вариант, не вариант.
Я бы посторонился таких громких заявлений. Такие заявления надо подкреплять аргументами и предоставлять свой «правильный» вариант реализации. А пока это - пускание пыли в глаза. Чем реализация вендора плоха?
Не забывайте про настройку колонок таблицы, drag & drop блоков, перерисовку нужных блоков после определённых событий и т.п.
Безусловно. Но когда этот самый dom собирал ты, а не вендор. Как уже писал выше, вендор его может смело сменить и ваше решение перестанет работать.
С API надежды на работающее решение больше. Хоть и тоже не 100%.
Воу — воу, вот это дебаты, ребята. Полегче) В поисках истины и отстаивании своих "единственно верных" точек зрения, не забываем о том что разработчики битрикс тоже люди. И не заслуживают, чтобы их называли «тупорылыми».
Считаю, что тот, кто делает такие утверждения, имеет в своем портфолио более лучшую систему? Если нет, то и говорить так не следует :)
А можно таким подходом, если нет изображения у торгового предложения вставлять из товара, которому они принадлежат?
Сергей, можно.
Спасибо, за статью, сделал сегодня на одном проекте если нет изображения у торгового предложения вставлять из товара, которому они принадлежа. Без этой инфы не смог бы
Спасибо за статью!
Было полезно, благодарю! А то уже думал на jq костыли лепить, а тут через API можно.