четверг, 20 марта 2008 г.

вопрос этикета

сегодня случайно наткнулся на любопытный ресурс infinitiv.org.ua. Это недоделанная копия моего текущего проекта. Домен infinitiv.org.ua зарегистрирован на Максима Рогальского, ранее принимавшего участие в жизни modx.ru.

Уважаемый Максим... какого черта происходит?

UPD:
а вот еще сайты...
http://intway.zp.ua/

вторник, 18 марта 2008 г.

"Гибридный" вывод новостей (дочерние документы+категории)

Мы привыкли делать вывод новостей, статей, каталога продукции и тд., находящихся в определенной папке. То есть, имеем мы категории новостей (например: Новости шоу-бизнеса, Интервью, Мнения ...), они же у нас родительские документы к самим этим новостям. Есть и другие способы вывода, может быть из других родительских документов, из множества родительских документов, но суть одна - мы всегда выводим статьи из каких-либо папок. А что если какие-то документы, находясь в одной папке, должны выводиться и в других категориях (папках)? Не дублировать же их всюду?

Недавно столкнувшись с такой вот задачей "кросспостинга", я придумал следующее решение. Сразу замечу, можно легко решить проблему "свалив" все документы в одну папку и настроить категории только с помощью 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, мы можем "подцепить" документы из других папок к выводу документов заданной папки :)

четверг, 13 марта 2008 г.

проверка на наличие привязаных документов

Дано: архив артистов, архив новостей и фоторепортажей, привязанных к артистам по идентификатору. Идентификатор артиста записан в соответствующем TV новостной статьи

Задача: выполнить проверку, существуют ли по данному артисту новости (хотябы одна) и вывести соответствующую кнопку на странице артиста и в каталоге артистов (шаблон Ditto)

Решение: нам всего-то нужно - проверить, есть ли в таблице modx_site_tmplvar_contentvalues запись со значением поля value равным идентификатору артиста и принадлежит ли соответствующий документ к категории новостей. Как известно, значения TV хранятся в БД MODx в одной таблице (modx_site_tmplvar_contentvalues), содержимое документов в другой (modx_site_content), а получить значение parent (для проверки принадлежности документа к новостям) мы можем только из таблицы содержимого. Поэтому здесь, для получения и проверки результата мы должны получить "объединенную" выдачу двух таблиц из базы. Для этого запросе к БД используем JOIN:
SELECT contentid, parent FROM modx_site_tmplvar_contentvalues JOIN modx_site_content ON modx_site_tmplvar_contentvalues.contentid = modx_site_content.id WHERE value = ".$output." AND tmplvarid = 5 AND parent IN ('4789','4794','4792')  LIMIT 1

Замечу, что IN проверяет на равенство одному из перечисленных в скобках значений (в моем проекте имеется три категории новостей) а tmplvarid = 5 гарантирует, что проверка производится только в нужном нам TV (привязка к артисту).

Привожу пример работающего phx-сниппета:
<?php
$query = "SELECT contentid, parent, pagetitle FROM modx_site_tmplvar_contentvalues JOIN modx_site_content ON modx_site_tmplvar_contentvalues.contentid = modx_site_content.id WHERE value = ".$output." AND tmplvarid = 5 AND parent IN ('4789','4794','4792') LIMIT 1";
$result = $modx->db->query($query);
$row = mysql_fetch_array($result);
$id = $row['contentid'];
return $id ? '<a class="news" title="Новости" href="[~4817~]?tags=[+pagetitle:name:common_name:url+]">Новости</a>' : '';
?>

я назвал сниппет 'news'. Теперь при вызове [+id:news+] (для шаблона Ditto) и при наличии привязанных новостей к артисту я получаю кнопку/ссылку на новости о нем. Примечание: в моем случае ссылка ведет на выдачу новостей по тегам а не по привязанным статьям - это специфика текущей ситуации и в дальнейшем будет исправлена :)