Вывод новостей сразу в нескольких новостных лентах
Актуально для версии 2.9.1
Содержание
Задача
Иногда необходимо, чтобы одна и та же новость отображалась в нескольких лентах новостей, стандартными средствами можно создавать виртуальные или просто копии новости и перетаскивать их через модуль "Структура" по нужным разделам, а если на сайте сложная структура новостных лент, это не совсем удобно.
Поэтому, нам нужно реализовать функционал, который позволит указывать на странице конкретной новости, в каком разделе её выводить.
Решение
Со стороны административной панели, нам понадобиться создать в типе данных 'Новость' поле типа "ссылка на дерево" с идентификатором 'rubric_link', все эти действия производятся в модуле "Шаблоны данных", в результате мы получим примерно следующее:
Теперь мы можем у каждой новости указать раздел для вывода:
Разделы мы указали, теперь нам понадобиться кастомный макрос, который будет выводить новости из конкретной ленты новостей, плюс новости из всех лент, у которых в поле с идентификатором 'rubric_link' выбрана эта лента новостей. Код данного макроса и его описание даны ниже.
Описание макроса
%news customNewsList()% — выводит новости из выбранной ленты и новости из всех лент новостей, у которых в поле типа "ссылка на дерево" с идентификатором 'rubric_link' указана выбранная лента.
Параметры: customNewsList($elementPath,[$template = "default", $per_page = false, $ignore_paging = false])
$elementPath
Принимает id или путь до ленты новостей, новости из которой будут выводиться макроса
$template
Принимает имя шаблона, по которому выводится результат макроса. В XSLT-шаблонизаторе игнорируется.
$per_page
Принимает число, которое обозначает максимальное количество новостей. Если этот параметр не указывать, будет взято значение, указанное в настройках модуля «Новости».
$ignore_paging
Принимаем булево значение («1» или «0»), указывающее макросу игнорировать значение текущей страницы списка вывода (параметр http-запроса p). То есть, если указать «1», макрос будет всегда выводить только первую страницу списка новостей
Для применения этого макроса скопируйте содержимое листинга макроса в файл /classes/modules/news/__custom.php, и не забудьте указать имя метода в permissions.custom.php.
Листинг макроса
public function customNewsList($elementPath, $template = "default", $per_page = false, $ignore_paging = false){
if(!$per_page){
(int) $per_page = $this->per_page;
}
list($template_block, $template_block_empty, $template_line) = def_module::loadTemplates("news/".$template, "items_block", "items_block_empty", "item_block");
$currPageNum = (int) getRequest('p');
$parentId = $this->analyzeRequiredPath($elementPath);
if($parentId === false){
throw new publicException(getLabel('error-page-does-not-exist', null, $elementPath));
}
$itemsFromCurrLent = array();
$currLentItems = new selector('pages');
$currLentItems->types('object-type')->name('news', 'item');
$currLentItems->where('hierarchy')->page($parentId);
$itemsFromCurrLent = $currLentItems->result();
unset($currLentItems);
$itemsWithCurrLink = array();
$allLentsItems = new selector('pages');
$allLentsItems->types('object-type')->name('news', 'item');
$allLentsItems->where('rubric_link')->equals($parentId);
$itemsWithCurrLink = $allLentsItems->result();
unset($allLentsItems);
$resultItems = array();
$resultItems = array_unique(array_merge($itemsFromCurrLent, $itemsWithCurrLink));
(int) $total = count($resultItems);
if($total>0){
$limitedItems = array();
if($ignore_paging){
$limitedItems = $resultItems;
}else{
$offset = $currPageNum * $per_page;
$limitedItems = array_slice($resultItems, $offset, $per_page);
}
unset($resultItems);
usort($limitedItems, function($a, $b){
$a_publishTime = $a->getValue('publish_time');
$b_publishTime = $b->getValue('publish_time');
if ($a_publishTime == $b_publishTime) {
return 0;
}
return ($a_publishTime > $b_publishTime) ? -1 : 1;
});
$lines = Array();
$block_arr = Array();
foreach ($limitedItems as $item){
$line_arr = array();
$itemId = $item->id;
$line_arr['attribute:id'] = $item->id;
$line_arr['attribute:link'] = $item->link;
$line_arr['xlink:href'] = "upage://" . $itemId;
$line_arr['void:header'] = $lines_arr['name'] = $item->getName();
$line_arr['node:name'] = $item->getName();
if($publish_time = $item->getValue('publish_time')){
$line_arr['attribute:publish_time'] = $publish_time->getFormattedDate("U");
}
unset($item);
$lines[] = def_module::parseTemplate($template_line, $line_arr, $itemId);
unset($line_arr);
$this->pushEditable("news", "rubric", $itemId);
unset($itemId);
}
if(is_array($parentId)) {
list($parentId) = $parentId;
}
$block_arr['subnodes:items'] = $block_arr['void:lines'] = $lines;
unset($lines);
$block_arr['total'] = $total;
$block_arr['per_page'] = $per_page;
return def_module::parseTemplate($template_block, $block_arr, $parentId);
}else{
return $template_block_empty;
}
}