Немного о недокументированной функции CIBlockFormatProperties::GetDisplayValue
Итак, в Битрикс существует недокументированная (вернее плохо документированная) функция CIBlockFormatPropertiesCustom::GetDisplayValue. Что она делает? Она добавляет к массиву, например, в news.detail пару пунктов, в которых содержатся отформатированные значения свойств текущего элемента.
Вот тут человек радостно рассказывает, как круто, что она есть. Однако мне вот тут стало недостаточно функционала. Что мне лично странно: почему у функции форматирования чего бы то ни было в таком фреймворке как Битрикс нет возможности передавать шаблон вывода входящим параметром. Объяснение тут в архитектуре: формат напрямую связан с типом свойства. Например, тип данных "Привязка к элементам" - обозначается буквой E, для это буковки указано в switch, что надо вернуть массив со ссылками! То есть внутренняя функция возвращает закопанный где-то в недрах HTML-код. Против всякой логики отделения логики от представления... Простите тавтологию.
Задача в том, чтобы захачить Битрикс, но не потерять целостность системы. Чтоб при обновлении все не вылетело в трубу, да и вообще хачить ядро Битрикс - дело неблагодарное, сами знаете.
Входящие данные: я хочу показывать на главной странице аккордеон из картинок товаров, вручную подобранных управляющим сайта. Для этого я создал инфоблок, в инфоблоке для удобства раздел, в разделе элемент. Инфоблоку дал свойство Привязка к элементам (другого инфоблока) - множественное. То есть один элемент хранит информацию о привязанных элементах, которые в свою очередь уже имеют картинки для моего аккордеона.
Решение: решение достаточно хитрое, но зато кошерное.
Я создал новый компонент путем прямого копирования родного компонента news.detail. Кто не знает, делается это так: в папке /bitrix/components/ создаем папочку под свои компоненты, например /bitrix/components/my/ - в нее копируем целиком папку /bitrix/components/bitrix/news.detail и переименовываем. Получилось: /bitrix/components/my/news.detail.custom/
Открываем /bitrix/components/my/news.detail.custom/component.php и ищем в нем строку, которая содержит CIBlockFormatProperties::GetDisplayValue. Она там одна должна быть. И именно она отвечает за форматирование свойств элемента инфоблока.
Держим файл открытым и открываем еще один /bitrix/php_interface/init.php. Как известно, это файл, который в логике Битрикс может и должен содержать все наши кастомные настройки, надстройки и хаки. Здесь мы и подменим родной класс форматирования свойств элемента.
Он находится тут: /bitrix/module/iblock/classes/general/comp_formatprops.php. Я сделал так: скопировал весь класс в init.php и переименовал сам класс в CIBlockFormatPropertiesCustom. Таким образом у меня теперь есть свой класс с другим именем, но методы его полностью сохранены. Ядро мы так и не тронули.
Возвращаемся к /bitrix/components/my/news.detail.custom/component.php и редактируем только одну строчку, ту самую где CIBlockFormatProperties - меняем имя класса на CIBlockFormatPropertiesCustom.
Теперь у нас в наличии весь нужный нам функционал - хачим свой класс как угодно и имеем что угодно.
В моем случае получилось вот что:
Ищем:
$rsLink = CIBlockElement::GetList(array(), $arLinkFilter, false, false, array("ID","IBLOCK_ID","NAME","DETAIL_PAGE_URL")); $CACHE["E"][$val] = $rsLink->GetNext();
Заменяем на:
// BOF modification
if($arProperty['CODE'] == 'elements'){
$rsLink = CIBlockElement::GetList(array(), $arLinkFilter, false, false, array("ID","IBLOCK_ID","NAME","PREVIEW_PICTURE","DETAIL_PICTURE","DETAIL_PAGE_URL"));
$CACHE["E"][$val] = $rsLink->GetNext();
$CACHE["E"][$val]['PREVIEW_PICTURE'] = CFile::GetFileArray($CACHE["E"][$val]["PREVIEW_PICTURE"]);
$CACHE["E"][$val]['DETAIL_PICTURE'] = CFile::GetFileArray($CACHE["E"][$val]["DETAIL_PICTURE"]);
} else {
// EOF modification
$rsLink = CIBlockElement::GetList(array(), $arLinkFilter, false, false, array("ID","IBLOCK_ID","NAME","DETAIL_PAGE_URL"));
$CACHE["E"][$val] = $rsLink->GetNext();
// BOF modification
}
// EOF modification
Ищем:
if(is_array($CACHE["E"][$val]))
$arDisplayValue[]='<a href="'.$CACHE["E"][$val]["DETAIL_PAGE_URL"].'">'.$CACHE["E"][$val]["NAME"].'</a>';
Заменяем на:
// BOF modification
if($arProperty['CODE'] == 'elements'){
if(is_array($CACHE["E"][$val]))
$arDisplayValue[] = array(
'PREVIEW_PICTURE' => $CACHE["E"][$val]["PREVIEW_PICTURE"],
'DETAIL_PICTURE' => $CACHE["E"][$val]["DETAIL_PICTURE"],
'DETAIL_PAGE_URL' => $CACHE["E"][$val]["DETAIL_PAGE_URL"]
);
} else {
// EOF modification
if(is_array($CACHE["E"][$val]))
$arDisplayValue[]='<a href="'.$CACHE["E"][$val]["DETAIL_PAGE_URL"].'">'.$CACHE["E"][$val]["NAME"].'</a>';
// BOF modification
}
// EOF modification
Размещаем наш кастомный компонент на странице.
Теперь логика такова: один элемент хранит несколько привязанных элементов в свойстве elements - news.detail.custom берет этот элемент, в свойстве PROPERTY_CODES компонента установлен elements - компонент выполняет обычную работу, но в момент получения отформатированных данных из значений свойств в случае если имя свойства elements создает не обычный массив со ссылками, а массив содержащий пути к превьюшке, пути к большой картинке и ссылки на соответствующие элементы. Дело за малым - создать шаблон для нашего компонента.
ЗЫ. Очевидно, что это не самое оптимальное решение с точки зрения производительности, однако оно наиболее правильно в логике Битрикс. Если вы очень озабочены производительностью - можно спокойно урезать кастомный компонент, убрав лишние запросы.
Гудлак.
Понравилась статья?
Нет обратных ссылок на эту запись.