Выборка данных из разных типов данных с фильтрацией по определенному свойству в режиме ИЛИ
Актуально для 2.9
Задача: Получить страницы в результате выборки по различным типам данных (страница контента, лента новостей, фотоальбом и др.) с фильтрацией по определенному свойству в режиме ИЛИ.
Решение: Для решения данной задачи использовать Usel-выборку не получится, так как usel будет работать в режиме ИЛИ только до тех пор, пока не задана фильтрация в теге <property /> . В этом случае, свойство, указанное в данном теге, будет искаться только в том типе, который указан в первом теге <type />, т.е. следующая выборка не принесет ожидаемого результата:
<?xml version="1.0" encoding="utf-8"?>
<selection>
<target expected-result="pages">
<type module="content" method="page"/>
<type module="news" method="rubric"/>
<type module="photoalbum" method="albums" />
<category depth="1">{1}</category>
</target>
<property name="pokazyvat" value="1" />
</selection>
Для решения задачи необходимо написать кастомный макрос с использованием API Selector. Для данного примера в типах данных "Страница контента", "Лента новостей" и "Фотогалерея" было создано поле "Показывать" с типом "кнопка-флажок" и данное свойство было отмечено у некоторых страниц указанных типов:
public function sortMultiType($parentId, $template = "default") {
if(!$template) $template = "default";
list($templateBlock, $templateItem) = self::loadTemplates("data/".$template, "sortblock", "sortitem");
$items = array();
// Получаем id текущей страницы
$currentElementId = cmsController::getInstance()->getCurrentElementId();
// поиск объектов каталога в текущем разделе
for ($i=0; $i < 3; $i++) {
$sel = new selector('pages');
if ($i==0) $sel->types('hierarchy-type')->name('content', 'page');
if ($i==1) $sel->types('hierarchy-type')->name('news', 'rubric');
if ($i==2) $sel->types('hierarchy-type')->name('photoalbum', 'album');
$sel->where('hierarchy')->page($parentId)->childs(1);
$sel->where('pokazyvat')->equals(1);
$result = $sel->result();
foreach($result as $page){
$item = Array();
$item['@id'] = $page->id;
// Если страница текущая, то помечаем её классом
if ($page->id == $currentElementId) $item['@active'] = "class = 'active'";
else $item['@active'] = '';
$item['@link'] = $page->link;
$item['node:name'] = $page->name;
$items[] = self::parseTemplate($templateItem, $item);
}
}
$blockItems = Array();
$blockItems['subnodes:items'] = $items;
return def_module::parseTemplate($templateBlock, $blockItems);
}
Результат работы макроса в XML-виде: udata://custom/sortMultiType/33
<?xml version="1.0" encoding="utf-8"?>
<udata xmlns:xlink="http://www.w3.org/TR/xlink" module="custom" method="sortMultiType" generation-time="0.039474">
<items>
<item id="68" link="/obychnaya_stranica/test/">test</item>
<item id="32" link="/obychnaya_stranica/akcii/">Акции</item>
<item id="27" link="/obychnaya_stranica/fotogalereya/">Фотогалерея</item>
</items>
</udata>
<!-- This page generated in 1.172077 secs by XSLT, HTTP SCHEME MODE -->
Для TPL, необходимо в шаблоне /tpls/data/default.tpl создать два блока:
$FORMS['sortblock'] = <<<END
%items%
%scope%
END;
$FORMS['sortitem'] = <<<END
%scope%
END;