сегодня случайно наткнулся на любопытный ресурс infinitiv.org.ua. Это недоделанная копия моего текущего проекта. Домен infinitiv.org.ua зарегистрирован на Максима Рогальского, ранее принимавшего участие в жизни modx.ru.
Уважаемый Максим... какого черта происходит?
UPD:
а вот еще сайты...
http://intway.zp.ua/
дневник Максима Коринца (yentsun), разработчика MODx (блог на данный момент не поддерживается)
четверг, 20 марта 2008 г.
вторник, 18 марта 2008 г.
"Гибридный" вывод новостей (дочерние документы+категории)
Мы привыкли делать вывод новостей, статей, каталога продукции и тд., находящихся в определенной папке. То есть, имеем мы категории новостей (например: Новости шоу-бизнеса, Интервью, Мнения ...), они же у нас родительские документы к самим этим новостям. Есть и другие способы вывода, может быть из других родительских документов, из множества родительских документов, но суть одна - мы всегда выводим статьи из каких-либо папок. А что если какие-то документы, находясь в одной папке, должны выводиться и в других категориях (папках)? Не дублировать же их всюду?
Недавно столкнувшись с такой вот задачей "кросспостинга", я придумал следующее решение. Сразу замечу, можно легко решить проблему "свалив" все документы в одну папку и настроить категории только с помощью TV. Ditto при этом настроить элементарно. Однако в мою задачу входит сохранение уже существующей структуры папок и документов в них.
Для начала нужно определиться - документ в БД должен существовать в единственном экземпляре, никаких дублей! Задать категории, в которых он должен отобразиться помимо своей родительской мы можем с помощью TV (например типа список checkbox). Единственной проблемой теперь встает настройка вывода Ditto, который должен вывести все документы из родительского документа а также проверить принадлежность к заданной категории документов из других папок. На ум сразу же пришло использование параметра &filter, который может "отсеять" документы не принадлежащие к заданной папке И (именно логическое AND) не содержащие в определенном TV "упоминаний" о текущей категории. Однако есть досадная деталь: множество фильтров Ditto (например &filter=`test1,34,2|test2,78,1` поддерживают лишь логическое ИЛИ). Единственным выходом оказалось изучение и написание собственного (custom) фильтра. Сделать это можно на основе примерного фильтра в файле example.extender.inc.php. И подключить его параметром &extenders. не буду вдаваться в подробности кода, там достаточно все элементрано:
(если не менять название этого файла, то в вызове Ditto теперь достаточно прописать &extenders=`example`)
Напомню, этот фильтр проверяет отсутствие упоминания id категории в дополнительном параметре artist_category и неравенство родителя этому же id категории, если оба условия верны - документ отфильтровывается. В противном случае документ выводится на страницу. Таким образом, расставив галочки в нашем TV artist_category, мы можем "подцепить" документы из других папок к выводу документов заданной папки :)
Недавно столкнувшись с такой вот задачей "кросспостинга", я придумал следующее решение. Сразу замечу, можно легко решить проблему "свалив" все документы в одну папку и настроить категории только с помощью 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:
Замечу, что IN проверяет на равенство одному из перечисленных в скобках значений (в моем проекте имеется три категории новостей) а tmplvarid = 5 гарантирует, что проверка производится только в нужном нам TV (привязка к артисту).
Привожу пример работающего phx-сниппета:
я назвал сниппет 'news'. Теперь при вызове [+id:news+] (для шаблона Ditto) и при наличии привязанных новостей к артисту я получаю кнопку/ссылку на новости о нем. Примечание: в моем случае ссылка ведет на выдачу новостей по тегам а не по привязанным статьям - это специфика текущей ситуации и в дальнейшем будет исправлена :)
Задача: выполнить проверку, существуют ли по данному артисту новости (хотябы одна) и вывести соответствующую кнопку на странице артиста и в каталоге артистов (шаблон 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) и при наличии привязанных новостей к артисту я получаю кнопку/ссылку на новости о нем. Примечание: в моем случае ссылка ведет на выдачу новостей по тегам а не по привязанным статьям - это специфика текущей ситуации и в дальнейшем будет исправлена :)
вторник, 5 февраля 2008 г.
счетчик посещений страницы и настройка рейтинга страниц по нему
Задача: Необходимо считать количество посещений страниц (пока без учета "уникальности" просмотра, то есть грубо говоря посетитель может "накручивать" просмотры, просто перезагружая страницу) и выстроить рейтинг страниц с учетом их посещений.
Решение: Начнем с того, что нам известно - вывод какого либо рейтинга страниц в MODx в штатном порядке осуществляется с помошью Ditto. Ditto, как нам известно, может сортировать вывод по любому полю документа а также по доп. параметру (TV). Единственный выход - получать количество просмотров в TV и потом сортировать по нему.
В репозитарии modxcms.com лежит плагин Page Hit Counter от sottwell, который проверяет просматривает ли страницу менеджер, и не снята ли галочка "Регистрировать посещения" и записывает посещение в свою таблицу БД MODx. Также я вспомнил что в сниппете CSS Star Rating есть замечательная функция setTemplateVar, которая, как вы наверное догадались, записывает значение в TV.
Создаем TV типа "текст" (у меня он называется "count") и делаем гибрид плагина, который вместо записи количества посещений в БД, записывает его в наш TV (не забудьте поставить проверку на системное событие OnWebPagePrerender):
Теперь у нас есть TV с посещениями. Как настроить вывод Ditto по нему - выходит за рамки этой статьи :) Также, если вам нужно выводить количество посещений на самой странице, которая кэшируется, придется написать небольшой сниппет и вызывать его некешируемым.
PS. Был бы признателен за дополнение этого плагина, которое бы исключало "накрутку" посещений. Возможно с применением cookie или с сессиями :)
Решение: Начнем с того, что нам известно - вывод какого либо рейтинга страниц в MODx в штатном порядке осуществляется с помошью Ditto. Ditto, как нам известно, может сортировать вывод по любому полю документа а также по доп. параметру (TV). Единственный выход - получать количество просмотров в TV и потом сортировать по нему.
В репозитарии modxcms.com лежит плагин Page Hit Counter от sottwell, который проверяет просматривает ли страницу менеджер, и не снята ли галочка "Регистрировать посещения" и записывает посещение в свою таблицу БД MODx. Также я вспомнил что в сниппете CSS Star Rating есть замечательная функция setTemplateVar, которая, как вы наверное догадались, записывает значение в TV.
Создаем TV типа "текст" (у меня он называется "count") и делаем гибрид плагина, который вместо записи количества посещений в БД, записывает его в наш TV (не забудьте поставить проверку на системное событие OnWebPagePrerender):
if (!function_exists('setTemplateVar')) {
function setTemplateVar($value, $docID, $tplVarName) {
global $modx;
//-- get tmplvar id
$tplName = $modx->getFullTableName('site_tmplvars');
$tplRS = $modx->db->select('id', $tplName, 'name="' . $tplVarName . '"');
$tplRow = $modx->db->getRow($tplRS);
$tblName = $modx->getFullTableName('site_tmplvar_contentvalues');
$selectQuery = $modx->db->select('*', $tblName, 'contentid=' . $docID . ' AND tmplvarid=' . $tplRow['id']);
$updFields = array (
'value' => $value
);
$insFields = array (
'tmplvarid' => $tplRow['id'],
'contentid' => $docID,
'value' => $value
);
if ($modx->db->getRecordCount($selectQuery) < 1) {
$modx->db->insert($insFields, $tblName);
} else {
$modx->db->update($updFields, $tblName, 'contentid=' . $docID . ' AND tmplvarid=' . $tplRow['id']);
}
}
}
if(!isset($_SESSION['usertype'])) { $_SESSION['usertype'] = ''; }
if($modx->documentObject['donthit'] != 1 && $_SESSION['usertype'] != 'manager') {
$current = $modx->getTemplateVarOutput('count',$modx->documentIdentifier);
$current = $current['count']+1;
@ setTemplateVar("$current", $modx->documentIdentifier, 'count');
}
return;
Теперь у нас есть TV с посещениями. Как настроить вывод Ditto по нему - выходит за рамки этой статьи :) Также, если вам нужно выводить количество посещений на самой странице, которая кэшируется, придется написать небольшой сниппет и вызывать его некешируемым.
PS. Был бы признателен за дополнение этого плагина, которое бы исключало "накрутку" посещений. Возможно с применением cookie или с сессиями :)
Ярлыки:
счетчик посещений,
Ditto,
Page Hit Counter,
setTemplateVar
пятница, 1 февраля 2008 г.
теговое облако для 4000 документов
Попробовав применить сниппет TvTagCloud к своей огромной базе документов, получил превышение ожидания запроса (или что то в этом духе). Мне необходимо было выводить определенное количество тегов из недавно созданных документов плюс минимизировать использование ресурсов базы/процессора. Пришлось погуглить и дописать свой код.
К сожалению делалось все в спешке и не хватило времени добавить в код комментарии и вообще привести все в божеский вид. Буду очень благодарен тому, у кого найдется минутка оформить сие в нормальный сниппет для общего пользования (можно даже мое авторство не ставить:)).
Сниппет в действии: http://s31183.gridserver.com (не морщитесь - сайт в разработке)
PS. Только сейчас обнаружил еще один сниппет для тегового облака в репозитарии modxcms.com: http://modxcms.com/TagCloud-749.html. Может с моей задачей справился бы и он.
<?php
// connect to database
$tb1 = $modx->getFullTableName("site_tmplvar_contentvalues");
$query = "SELECT value";
$query .= " FROM ".$tb1;
$query .= " WHERE tmplvarid=6";
$query .= " GROUP BY value";
$query .= " ORDER BY id DESC";
$query .= " LIMIT 100;";
$result = $modx->db->query($query);
// here we loop through the results and put them into a simple array:
while ($row = mysql_fetch_array($result)) {
$tags = explode(', ',$row['value']);
$tag_mess = array_merge($tag_mess, $tags);
}
// determine the font-size increment
// this is the increase per tag quantity (times used)
$tags = array_count_values($tag_mess);
arsort($tags);
$tags = array_slice($tags, 0, 30);
ksort($tags);
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
// change these font sizes if you will
$max_size = 200; // max font size in %
$min_size = 100; // min font size in %
// get the largest and smallest array values
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
$spread = 1;
}
$step = ($max_size - $min_size)/($spread);
// loop through our tag array
foreach ($tags as $key => $value) {
$size = $min_size + (($value - $min_qty) * $step);
$output .= '<a href="/[~4817~]?tags='.urlencode($key).'" style="font-size: '.$size.'%" title="">'.$key.'</a> ';
}
return $output;
?>
К сожалению делалось все в спешке и не хватило времени добавить в код комментарии и вообще привести все в божеский вид. Буду очень благодарен тому, у кого найдется минутка оформить сие в нормальный сниппет для общего пользования (можно даже мое авторство не ставить:)).
Сниппет в действии: http://s31183.gridserver.com (не морщитесь - сайт в разработке)
PS. Только сейчас обнаружил еще один сниппет для тегового облака в репозитарии modxcms.com: http://modxcms.com/TagCloud-749.html. Может с моей задачей справился бы и он.
среда, 16 января 2008 г.
сортировка файлов по алфавиту в FCK-менеджере ресурсов
Очень и очень долго рыл по этому вопросу форум и ничего не нашел. Папки и файлы в менеджере ресурсов FCK-Editor (который стоит сейчас по умолчанию как менеджер файлов для TV и прочего) выводятся в соответствии с установками сервера на котором хостится сайт. В большинстве случаев сортировка идет по дате последнего изменения. Когда этих папок становится много, приятней было бы сортировать по алфавиту.
Повторюсь, что на форуме нашел много постов с этим же вопросом, но ни одного вменяемого ответа. Попробовал сам подредактировать mcpuck-коннектор - не осилил.
И вот, мои поиски увенчались успехом - отличное изящное решение от немецкого сообщества MODx (распакуйте архив в корень сайта)
Повторюсь, что на форуме нашел много постов с этим же вопросом, но ни одного вменяемого ответа. Попробовал сам подредактировать mcpuck-коннектор - не осилил.
И вот, мои поиски увенчались успехом - отличное изящное решение от немецкого сообщества MODx (распакуйте архив в корень сайта)
задание шаблона по умолчанию для дочерних документов определенного родителя
Очень давно меня беспокоила необходимость постоянно задавать шаблон для новых документов. Когда речь не идет о периодической информации - шаблон задать нетрудно, однако когда необходимо создавать по нескольку документов в минуту - вопрос стоит достаточно остро. К тому же, ваш заказчик, сам администрируя сайт, может просто забыть выставить нужный шаблон.
В последних версиях MODx появился плагин Inherit Parent Template, с помощью которого можно было создать неопубликованный контейнер и задать ему нужный шаблон, тогда все дочерние документы наследовали этот шаблон. Однако этот способ вынуждал делать лишние контейнеры для каждой категории и создавать иерархию меню отдельно от документов контента.
Итак, хочу представить более менее приемлемое решение. Мы немного изменим вышеупомянутый плагин, чтобы задать родительские документы, новые(!) дочерние документы которых будут автоматически принимать заданный шаблон. Сразу оговорюсь, в моем случае пришлось задавать суперродителей (родителей родителей), однако закомментировав одну строку плагина вы можете иметь возможность задавать просто родителей.
Код нового плагина "Inherit Parent Template" (его можно просто заменить поверх старого):
задать родительский документ и соответствующий шаблон можно в массиве
В последних версиях MODx появился плагин Inherit Parent Template, с помощью которого можно было создать неопубликованный контейнер и задать ему нужный шаблон, тогда все дочерние документы наследовали этот шаблон. Однако этот способ вынуждал делать лишние контейнеры для каждой категории и создавать иерархию меню отдельно от документов контента.
Итак, хочу представить более менее приемлемое решение. Мы немного изменим вышеупомянутый плагин, чтобы задать родительские документы, новые(!) дочерние документы которых будут автоматически принимать заданный шаблон. Сразу оговорюсь, в моем случае пришлось задавать суперродителей (родителей родителей), однако закомментировав одну строку плагина вы можете иметь возможность задавать просто родителей.
Код нового плагина "Inherit Parent Template" (его можно просто заменить поверх старого):
/*
* Inherit Template from Parent
* Written By Raymond Irving - 12 Oct 2006
*
* Simply results in new documents inherriting the template
* of their parent folder upon creating a new document
*
* Configuration:
* check the OnDocFormPrerender event
*
* Version 1.0
*
*/
global $content;
$e = &$modx->Event;
$parents_and_templates = array (
'4818' => '5', // id родителя => id шаблона (можно посмотреть в БД)
'4817' => '6'
);
switch($e->name) {
case 'OnDocFormPrerender':
if(($_REQUEST['pid'] > 0) && ($id == 0)) {
$parent = $modx->getPageInfo($_REQUEST['pid'],0,'id, parent, template');
$parent = $modx->getPageInfo($parent['parent'],0,'id, parent, template'); //закомментируйте эту строку, если вам нужен родитель первого уровня
$pid = $parent['id'];
if (array_key_exists($pid,$parents_and_templates)) {
$content['template'] = $parents_and_templates[$pid];
}
else {
$content['template'] = $parent['template'];
}
}
break;
default:
return;
break;
}
задать родительский документ и соответствующий шаблон можно в массиве
$parents_and_templates = array (
'4818' => '5',
'4817' => '6'
);
Подписаться на:
Сообщения (Atom)