1С-Битрикс. Добавляем коллекцию из медиабиблиотеки в текст новости

В одном из проектов возникла необходимость сделать возможность добавления галереи в текст новости. Поскольку контент наполняют не программисты — пришлось сделать это максимально просто.

Фотографии для статьи будут загружаться в медиабиблиотеку. Для каждой статьи — отдельная коллекция с уникальным именем (почему объясню ниже). А добавляться они будут в текст с помощью тега #название коллекции#.

Во-первых для выборки фотографий из коллекции напишем компонент. Вот основные моменты в его коде:

component.php

<?

// подключаем медиабиблиотеку
CModule::IncludeModule("fileman");
CMedialib::Init();

//выбираем коллекцию по имени - имя коллекции будет предаваться компоненту как параметр 
$arResult['COLLECTIONS']    = CMedialibCollection::GetList(array('arFilter' => array('ACTIVE' => 'Y', 'ML_TYPE' => 1, 'NAME' => $arParams['NAME'])));
$arCollections             = array();

// на момент написания статьи фильтрация выборки в CMedialibCollection::GetList() весьма ограничена и
// фильтр в CMedialibCollection не срабатывает по точному совпадению имени ('=NAME' => $arParams['NAME']), 
// но все же ищет элементы с именем содержащим подстроку $arParams['NAME'] (%строка% в MYSQL).
// Поэтому, чтобы получить точное совпадение по имени, приходится исключать из первичной выборки элементы просто содержащие подстроку $arParams['NAME'] перебирая элементы 
foreach($arResult['COLLECTIONS'] as $key=>$val){
   if($val['NAME'] != $arParams['NAME']){
      unset($arResult['COLLECTIONS'][$key]);
   }else{
      $arCollections[] = $val['ID'];
   }
}


// далее, если мы нашли нужную коллекцию, выбираем из нее изображения
if(count($arCollections)){
   $arResult['ITEMS']    = CMedialibItem::GetList(array('arCollections'=>$arCollections));

   // и, если необходимо, изменяем их размер 
   if(count($arResult['ITEMS']) && ($arParams["WIDTH"] && $arParams["HEIGHT"])){

      foreach($arResult['ITEMS'] as &$val){

         $img = CFile::ResizeImageGet($val['SOURCE_ID'], array('width'=>$arParams["WIDTH"], 'height'=>$arParams["HEIGHT"]), BX_RESIZE_IMAGE_PROPORTIONAL, false); 
         $val['RESIZED'] = $img['src']; 
      }
   }

}
?>

Шаблон вывода template.php

<?if(!count($arResult['ITEMS'])) return false;?>

<div class="look_slider">
<div class="controls">
    <p>
    <a href= "" class="slide_bwd"></a> <span>1 из <?=count($arResult['ITEMS'])?></span>
    <a href= "" class="slide_fwd"></a>
   </p>
</div>

<ul>
    <?foreach($arResult['ITEMS'] as $val){?>
    <li>
       <div>
           <img src="<?if($val['RESIZED']) echo $val['RESIZED']; else echo $val['PATH'];?>" alt="<?=$val['DESCRIPTION']?>"/>
           <?if($val['DESCRIPTION']){?><p><?=$val['DESCRIPTION'];?></p><?}?>
       </div>
    </li>
    <?}?>
    
</ul>
</div>

Рядом с шаблоном script.js — скрипт простой листалки

$(function(){
   if(!window.look_slider_init){
      var photo_slider=$('.look_slider');
      photo_slider.each(function(){
            var cont=$(this);
            cont.find('li:eq(0)').addClass('active').siblings().hide();
            var size=cont.find('li').length;
            var bwd=cont.find('.slide_bwd');
            var fwd=cont.find('.slide_fwd');
            var state=cont.find('.controls span');
            state.text('1 из '+size);
            fwd.click(function(){
                  var a=cont.find('.active').index();
                  if(a<size-1){
                     cont.find('li:eq('+(a+1)+')').addClass('active').show().siblings().removeClass('active').hide();
                     state.text((a+2)+' из '+size);
                  }
                  return false;
            })
            bwd.click(function(){
                  var a=cont.find('.active').index();
                  if(a>0){
                     cont.find('li:eq('+(a-1)+')').addClass('active').show().siblings().removeClass('active').hide();
                     state.text(a+' из '+size);
                  }
                  return false;
            });
      });
      
      window.look_slider_init = true;
      
   }

});

и файл стиля style.css

.look_slider li{list-style-type:none;margin:0;padding:0 !important;margin:0 !important}
.look_slider .look_slider ul{margin:0 0 25px 0 !important;padding:0 !important}
.look_slider .look_slider li p{text-align:center;font:normal 11px/16px 'trebuchet ms';}
.look_slider .look_slider ul div{padding:10px 0 0 0;width:700px;}
.look_slider .controls .slide_bwd{display:inline-block;width:23px;height:23px;background:url(images/ar_left.gif) no-repeat left top;vertical-align:middle}
.look_slider .controls .slide_fwd{display:inline-block;width:23px;height:23px;background:url(images/ar_right.gif) no-repeat left top;;vertical-align:middle}
.look_slider .controls .slide_bwd:hover, .controls .slide_fwd:hover{background-position:left bottom}

.look_slider .controls{line-height:23px !important;text-align:center;width:700px;}
.look_slider .controls span{text-align:center;display:inline-block;height:23px;;vertical-align:middle;font:normal 12px/23px 'trebuchet ms';color:#000;padding:0 5px 0 5px;}

Теперь дописать компонент выводящий детальную новость

result_modifier.php добавляем строку

<?$this->__component->SetResultCacheKeys(array("CACHED_TPL"));?>

template.php обрамляем код шаблона строками

<?ob_start();?>

... Код шаблона ...

<? 
$this->__component->arResult["CACHED_TPL"] = @ob_get_contents();
ob_get_clean();
?>

component_epilog.php

<?
echo preg_replace_callback(
     "/#([^#]+)#/is".BX_UTF_PCRE_MODIFIER,
     create_function('$matches', 'ob_start();
      $GLOBALS["APPLICATION"]->IncludeComponent(
         "farrock:gallery",
         "",
         Array(
            "NAME" => trim($matches[1]),
            "WIDTH" => "700",
            "HEIGHT" => "450",
            "CACHE_TYPE" => "A",
            "CACHE_TIME" => "3600"
         )
      );
     $retrunStr = @ob_get_contents();
     ob_get_clean();
     return $retrunStr;'),
     $arResult["CACHED_TPL"]);


?>

Далее создаем коллекцию и добавляем в текст новости строку #Название коллекции#. Наслаждаемся результатом.

Оставить комментарий

Комментарии (7)

  1. Павел 11.09.2016 Ответить
    Спасибо за отличное решение!
    Возник один вопрос. В файле component_epilog.php у вас вызывается компонент farrock:gallery. Где взять этот компонент или чем его можно заменить? Используемая редакция "Старт".

    Заранее благодарю!
  2. Дмитрий
    Дмитрий 12.09.2016 Ответить
    День добрый!
    В начале статьи как раз описываются основные моменты создания данного компонента, файлы (component.php, template.php, script.js).
    Заменить данный компонент нечем, штатного решения нет, поэтому он и был написан.
  3. Павел 12.09.2016 Ответить
    Добрый день!
    Спасибо за ответ.
    Компонент я создал, он загружен в систему.
    Я, видимо, не так выразился. Я спрашивал про компонент farrock:gallery. Код вызова этого компонента присутствует в файле component_epilog.php.
    Пробовал использовать другую стороннюю галерею, но при вставке в текст новости #названия коллекции#, выводятся все фотографии из медиабиблиотеки.
  4. Дмитрий
    Дмитрий 15.09.2016 Ответить
    День добрый!
    Мы видимо кружим вокруг одной сосны.
    Последовательность ваших действия должна быть такая:
    1) СОЗДАЕМ компонент farrock:gallery, "farrock" - namespace, "gallery" - непосредственно компонент.
    2) МОДИФИЦИРУЕМ шаблон компонента bitrix:news.detail, тут в component_epilog.php вы вызываете ранее СОЗДАННЫЙ компонент gallery из namespace farrock.
    P.S. Мы уже 3 года не используем данное решение, поэтому компонент целиком выслать не смогу - не осталось ни одной копии =)
  5. Дмитрий 17.11.2016 Ответить
    Спасибо большое, выручили и сэкономили мне кучу времени.
    Сделал по Вашей инструкции и сразу получилось. Единственное, мне не пришлось делать собственный компонент вывода фотографий, а был взят гоовый бесплатный "Медиабиблиотека в публичном разделе (epir.medialibrarylight)" из Marketplace. Правда, тогда необходимо немного переделать файл component_epilog.php (приведу код, может кому пригодится).
    <?
    echo preg_replace_callback(
    "/#([^#]+)#/is".BX_UTF_PCRE_MODIFIER,
    create_function('$matches', 'ob_start();
    $GLOBALS["APPLICATION"]->IncludeComponent(
    "epir:medialibrary.list",
    "template1",
    Array(
    "CACHE_TIME" => "36000000",
    "CACHE_TYPE" => "A",
    "COLLECTION_VARIABLE" => "ID_COL",
    "COMPONENT_TEMPLATE" => ".default",
    "INCLUDE_FANCYBOX" => "Y",
    "INCLUDE_JQUERY" => "N",
    "INCLUDE_LAZY" => "N",
    "ROOT_COLLECTIONS" => array(0=>get_id(trim($matches[1])),),
    "SECTION_SORT" => "N",
    "SET_HEADER" => "Y",
    "SHOW_TITLE" => "Y",
    "SORT_BY" => "ID",
    "SORT_ORDER" => "ASC"
    )
    );
    $retrunStr = @ob_get_contents();
    ob_get_clean();
    return $retrunStr;'),
    $arResult["CACHED_TPL"]);

    function get_id($s) {
    CModule::IncludeModule("fileman");
    CMedialib::Init();
    $collections = CMedialibCollection::GetList(array('arFilter' => array('ACTIVE' => 'Y', 'ML_TYPE' => 1, 'NAME' => $arParams['NAME'])));
    foreach($collections as $key=>$val){
    if($val['NAME'] != $s){
    unset($arResult['COLLECTIONS'][$key]);
    }else{
    return $val['ID'];
    }
    }
    }
    ?>
  6. Константин 15.08.2017 Ответить
    Здравствуйте! Вроде решение мне кажется очень адекватным, но как только добавляю обертку в файл template.php то содержание новости пропадает. Текст, заголовок и все остальное. Не можете сказать в чем проблема, и как это можно исправить?
  7. Дмитрий
    Дмитрий 06.10.2017 Ответить
    Надо чуть больше данных.
    Вывод лога ошибок к примеру.