Небольшая заметка, надеюсь, кому-то будет полезна.
Интро.
Временами приходится работать с CMS bitrix, и так как я студент 3-его курса и это моя первая работа так или иначе «около специальности», то многому я учусь. И сегодня предо мной встала такая задача: кастомизировать определённым образом компонент news.list, и передать данные из него на другую страницу, где лежит такой же news.list. Вообще, эти 2 news.list’а реализуют подобие галереи. Почему я не использую стандартную галерею или не возьму комплексный компонент — даже не спрашивайте. Первый news.list — это аналог catalog.section.list — он просто выводит данные из инфоблока, причём специфично. В инфоблоке находятся разделы (это вроде как альбомы с видеозаписями). В каждом разделе будет много видеозаписей. У каждого альбома задаётся preview-изображение и само-собой название. Вывести нужно было и изображение, и название, и последние 2 добавленных видео. В качестве видео выступают элементы инфоблока, лежащие в текущем разделе. У них заданы preview-картинка и ссылка на youtube-видео.
Сначала я начал реализацию на catalog.section.list, не думая о том, что буду делать потом. Когда всё было примитивно свёрстано в подобии адаптива, был написан вывод строчек так в 50, я столкнулся с тем, что (ВНЕЗАПНО,ага) catalog.section.list несёт в себе свойства только разделов, но никак не элементов в этих разделах. А GetList мне отправлять отчего-то не захотелось, и я решил использовать news.list (хотя как выяснилось далее, catalog.section.list обошёлся бы мне гораздо менее затратно). В общем, что получилось:
Сначала мой кривой адаптив, чтобы вы понимали, выглядит примерно так:
Примерно так я себе это накидал. Потом дизайнер с верстальщиком будут стилизовать. Теперь действия, которые были вынесены в result_modifier.php:
<? /*получение превью-изображений у внутренних элементов раздела*/ define("IBLOCK_ID", $arParams["IBLOCK_ID"]); $arSectionsByID = array(); foreach ($arResult['ITEMS'] as $arItem) { if (!isset($arSectionsByID[$arItem['IBLOCK_SECTION_ID']]) OR !is_array($arSectionsByID[$arItem['IBLOCK_SECTION_ID']])){ $buffer = CIBlockSection::GetByID($arItem['IBLOCK_SECTION_ID'])->GetNext(); /*получаем данные о секции текущего элемента инфоблока*/ $picture = CFile::GetPath($buffer["PICTURE"]); /*получаем ссылку на preview изображение раздела*/ $arSectionsByID[$arItem['IBLOCK_SECTION_ID']]['ID'] = $buffer["ID"]; /*сохраняем ID*/ $arSectionsByID[$arItem['IBLOCK_SECTION_ID']]['PICTURE'] = $picture; /*сохраняем имагу*/ $arSectionsByID[$arItem['IBLOCK_SECTION_ID']]['NAME'] = $buffer["NAME"]; /*сохраняем имя*/ /*в качестве ключа в этом массиве выступает как раз ID раздела*/ } } $arImages = array(); foreach ($arSectionsByID as $key=>$section) { /*для каждой секции получаем все её элементы и запоминаем 2 последних добавленных*/ $arFilter = Array( "IBLOCK_ID" => IBLOCK_ID, "SECTION_ID" => $key, "ACTIVE"=>"Y" ); $res = CIBlockElement::GetList(Array(), $arFilter, Array("PREVIEW_PICTURE", "IBLOCK_SECTION_ID", "PROPERTY_ATR_LINK")); $count = 0; $id = 0; $atr_link = ""; while($ar_fields = $res->GetNext()) { if ($count == 2) break; $arImages["PICTURE"][] = CFile::GetPath($ar_fields["PREVIEW_PICTURE"]); /*получаем preview-изображение для видео*/ $id = $ar_fields["IBLOCK_SECTION_ID"]; /*запоминаем ID секции*/ $atr_link = $ar_fields["PROPERTY_ATR_LINK_VALUE"]; /*запоминаем ссылку на видео*/ if (!empty($atr_link) and isset($atr_link)) $arImages["ATR_LINK"][] = $atr_link; /*к каждому preview ставим в соответствие ссылку на видео*/ else $arImages["ATR_LINK"][] = "none"; /*если видео нет - то пишем none*/ $count++; } $arImages["ID"] = $id; /*ID, чтобы потом можно было проверить, к какому разделу относятся эти 2 элемента*/ $arResult["IMAGES"][] = $arImages; /*записываем этот подмассив в arResult*/ unset($arImages); /*unset'им и по-новой*/ } $arResult["CUSTOM_SECTIONS"] = $arSectionsByID; /*сохраняем данные о секциях, полученные в начале*/ foreach ($arResult["IMAGES"] as $index => $item) { /*блок кода дальше парсит код из ссылки на видео*/ foreach ($item["ATR_LINK"] as $i => $it) { if ($it == "none") $it = ""; else { if (strpos($it, 'http://youtu.be/') !== false) { $code = explode('/youtu.be/', $it); $code = $code[1]; } elseif (strpos($it, 'iframe') !== false) { $code = explode('/embed/', $it); $code = explode('"', html_entity_decode($code[1])); $code = $code[0]; //$code = $code[0]; } elseif (strpos($it, 'watch?v=') !== false) { $code = explode('watch?v=', $it); $code = $code[1]; } else { $code = $it; } $arResult["IMAGES"][$index]["ATR_LINK"][$i] = $code; } } } $arResult["CUSTOM_SECTIONS"] = array_reverse($arResult["CUSTOM_SECTIONS"]); /*получаем массивы в обратном порядке, т.к нам нужно получить 2 последних, а не 2 первых*/ $arResult["IMAGES"] = array_reverse($arResult["IMAGES"]); ?>
На этом обработка массивов закончилась. Дальше внедряем всё это в вёрстку:
<div class="container"> <? $i = 0; foreach ($arResult["CUSTOM_SECTIONS"] as $index => $arItem) { ?> <div class="row video_main_row"> <div class="col-md-3 col-sm-12"> <div class="center-sm-block"> <img src="<? echo $arItem["PICTURE"] ?>" class="example"> </div> </div> <div class="col-md-9 col-sm-12"> <div class="row"> <div class=" col-sm-12"> <h3 class="video_h3" data-id="<?echo $arItem["ID"]?>"><? echo $arItem["NAME"] ?></h3> </div> </div> <div class="row"> <? foreach ($arResult["IMAGES"][$i]["PICTURE"] as $key => $arItem_) {?> <div class="col-md-6 col-sm-12"> <div class="center-sm-block youtube"> <a class="single_image fancybox.iframe" href="https://www.youtube.com/v/<? echo $arResult["IMAGES"][$i]["ATR_LINK"][$key] ?>?autoplay=1"> <img src="<? echo $arItem_ ?>" alt="" class="my-video"> </a> </div> </div> <? } ?> </div> </div> </div> <? $i++; } ?> </div>
А вот дальше я столкнулся (как оказалось — не с проблемой, а просто с доселе неизвестной мне вещью) с проблемой: как передать ID раздела из этого шаблона в другой? Иначе говоря, как передать ID секции, по которой второй news.list должен сделать фильтрацию, собственно говоря, во второй news.list?
Как можно заметить — у заголовка h3 есть атрибут data-id, где хранится ID раздела, заголовок которого мы просматриваем. И тут подключилась js. А вернее — jQuery и POST-запрос. Был создан небольшой файлик, который в массив $_SESSION записывает данные, которые пришли из массива $_POST:
session_start(); $buffer = print_r($_POST, true); $_SESSION["TEST"] = $buffer;
Зачем файлик? Затем, что при клике на заголовок я могу задействовать только js, потому что заголовок уже сгенерирован и лежит на стороне клиента, как и скрипты. Далее. JS может отправить запрос, например POST, который уйдёт в некоторый файл .php, где что-то выполнится и что-то вернётся. В моём случае ответ мне не нужен, т.к. я пишу в массив $_SESSION, откуда потом смогу прочитать. В общем, такой получился скрипт:
$('.video_h3').click(function() { var data = $(this).attr('data-id'); $.ajax({ type: "POST", url: "https://имя.сайта/.../файл.php", data: {'data_id_sections' : data}, success:function (data) { document.location.href = "куда будем делать redirect"; } }); });
Я redirect делаю на ту страницу, где вызывается второй news.list. Перед его вызовом из $_SESSION я вытаскиваю полученный раздел, фильтрую news.list по этому разделу и вывожу видео только из него.
Ну и чтобы всё было законченным, приведу ещё настройку fancybox’а, позволяющую открывать видео в модальном окне прямо на сайте:
$(".single_image").fancybox({ 'padding' : 0, 'autoScale' : false, 'transitionIn' : 'none', 'transitionOut' : 'none', 'title' : this.title, 'width' : 640, 'height' : 385, 'type' : 'swf', 'swf' : { 'wmode' : 'transparent', 'allowfullscreen' : 'true' } });
Если вдруг это кому-то пригодится — я буду рад. Если кто-то хочет что-то высказать — я буду рад ещё больше, высказывайте! Ведь сам только учусь, а опыт — сын ошибок трудных, которых я, возможно, не вижу 🙂