Мы привыкли делать вывод новостей, статей, каталога продукции и тд., находящихся в определенной папке. То есть, имеем мы категории новостей (например: Новости шоу-бизнеса, Интервью, Мнения ...), они же у нас родительские документы к самим этим новостям. Есть и другие способы вывода, может быть из других родительских документов, из множества родительских документов, но суть одна - мы всегда выводим статьи из каких-либо папок. А что если какие-то документы, находясь в одной папке, должны выводиться и в других категориях (папках)? Не дублировать же их всюду?
Недавно столкнувшись с такой вот задачей "кросспостинга", я придумал следующее решение.
Сразу замечу, можно легко решить проблему "свалив" все документы в одну папку и настроить категории только с помощью TV. Ditto при этом настроить элементарно. Однако в мою задачу входит сохранение уже существующей структуры папок и документов в них.
Для начала нужно определиться - документ в БД должен существовать в единственном экземпляре, никаких дублей! Задать категории, в которых он должен отобразиться помимо своей родительской мы можем с помощью TV (например типа список checkbox). Единственной проблемой теперь встает настройка вывода Ditto, который должен вывести все документы из родительского документа а также проверить принадлежность к заданной категории документов из других папок. На ум сразу же пришло использование параметра
&filter, который может "отсеять" документы не принадлежащие к заданной папке И (именно логическое AND) не содержащие в определенном TV "упоминаний" о текущей категории. Однако есть досадная деталь: множество фильтров Ditto (например &filter=`test1,34,2|test2,78,1` поддерживают лишь логическое ИЛИ). Единственным выходом оказалось изучение и написание собственного (custom) фильтра. Сделать это можно на основе примерного фильтра в файле
example.extender.inc.php. И подключить его параметром
&extenders. не буду вдаваться в подробности кода, там достаточно все элементрано:
<?php
// ---------------------------------------------------
// Group: Filters
// Define custom or basic filters within the extender to expand Ditto's filtering capabilities
// ---------------------------------------------------
$filters["custom"]["exampleFilter"] = array("parent,artist_category","exampleFilter");
// Variable: $filters["custom"]["exampleFilter"]
// Add the filter exampleFilter to the custom filters
// list with the source pagetitle and the callback
// exampleFilter
if (!function_exists("exampleFilter")) {
// wrap functions in !function_exists statements to ensure that they are not defined twice
// ---------------------------------------------------
// Function: exampleFilter
//
// Takes the resource array for an individual document
// and asks for the return of a 0 or 1 with 0 removing
// the document and 1 leaving it in the result set.
// In this case, if the lower case value of the pagetitle
// is foo, it is removed while all other documents are shown
// ---------------------------------------------------
function exampleFilter($resource) {
global $modx;
$id = $modx->documentObject['id'];
if (!stristr($resource['artist_category'], $id) && $resource['parent'] != $id) {
return 0;
} else {
return 1;
}
}
}
?>
(если не менять название этого файла, то в вызове Ditto теперь достаточно прописать &extenders=`example`)
Напомню, этот фильтр проверяет
отсутствие упоминания id категории в дополнительном параметре artist_category и
неравенство родителя этому же id категории, если оба условия верны - документ отфильтровывается. В противном случае документ выводится на страницу. Таким образом, расставив галочки в нашем TV artist_category, мы можем "подцепить" документы из других папок к выводу документов заданной папки :)