Блог на MODx Revolution: как сделать архив

()

Дорабатывая свой сайт, обнаружил, что на просторах отечественных интернетов тема MODx освещена весьма скудно, а там где освещена - в основном статьи по MODx Evolution, в то время как MODx Revolution широкой поступью набирает силу и мощь. Поэтому я решил написать несколько статей по MODx Revolution в ключе практических задач. Первая задача - организовать архив записей (фильтрацию по месяцам), как это сделано в небезызвестном Wordpress.

Начнем с начала: определимся с задачей и составим небольшую спецификацию, а-ля ТЗ.

Пользователь приходит на блог и просматривает записи. В специальном месте расположены ссылки на архивные записи по месяцам вида Декабрь 2010 (4), при нажатии на которую пользователю показываются только те блого-записи, которые были написаны в декабре 2010 года. В скобочках рядом с месяцем приведено количество записей за этот месяц (в данном примере - 4). Из описанного выше видно, что для наших целей необходимо каким-то образом передать выбранный месяц, пусть это будет параметр GET запроса с названием bymonth со значениями вида 201012, т.е. четыре цифры года и две цифры месяца. Также нам потребуется две функции, одна будет считать количество записей за месяц, проходя по всем блого-записям, чтобы сформировать ссыки архива, а другая - для выбора их базы данных только тех записей, которые были опубликованы в заданном месяце.

Сниппет getArchiveMonths для формирования ссылок архива:

$collection = $modx->getCollection('modResource', array(  
    'published' => 1,  
    'parent' => '2')  
);

setlocale(LC_TIME, 'ru_RU.UTF8');  
$output = "";  
$months = array();

foreach ($collection as $resourceId => $resource) {  
    $strmonth = date("Ym", $resource->publishedon);  
    if(array_key_exists($strmonth, $months))  
        $months[$strmonth]['count']++;  
    else  
    {  
        $months[$strmonth]['count'] = 1;  
        $months[$strmonth]['text'] = strftime("%B %Y", $resource->publishedon);  
    }  
}

krsort($months);

foreach ($months as $month => $count) {          
    $output .= $modx->getChunk($tpl, array(    
        'month' => $month,  
        'text' => $count['text'] . ' (' . $count['count'] . ')'  
    ));    
}

return $output;

В первом запросе мы получаем все документы, имеющие определенного родителя и опубликованные (при желании условия можно изменить, например на номер шаблона, который имеют блого-записи). Далее идет формирование словаря, ключом которого является месяц, а значением - пара значений: колчество записей в этот месяц и отформатированное название месяца. Потом этот словарь сортируется так, чтобы самые последние месяца шли раньше, и на его основе, а так же переданного чанка, генерируется кусок html-кода.

Вызов сниппета в моем случае (пробел между [ и [ сделан, чтобы MODx не обрабатывал его как вызов сниппета):

<ul>  
    [ [getArchiveMonths? &tpl=`archiveMonthRow`]]  
</ul>

Пример чанка:

<li><a href="/blog/?bymonth=[[+month]]">[[+text]]</a></li>

Прекрасно. Теперь у нас есть набор ссылок, по которым пользователь может нажать, осталось обработать эти запросы.

Т.к. для отображения документов в большинстве своем используется сниппет getResources, то для того, чтобы он показал лишь определенные записи достаточно задать ему параметр resources:

if (!empty($_GET['bymonth'])) {  
    $month = (int)$_GET['bymonth']; // для защиты от всякой дряни  
    $ids = $modx->runSnippet('getResourcesIds',array(  
          'month' => $month  
    ));  
    $scriptProperties['resources'] = $ids;  
}

Сниппет getResourcesIds возвращает список id ресурсов, опубликованных в заданном месяце:

$collection = $modx->getCollection('modResource', array(  
    "EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(`publishedon`)) = '$month'",  
    'published' => 1,  
    'parent' => '2'));  
$output = "";  
foreach ($collection as $resourceId => $resource) {  
    $output.=$resourceId.',';  
    }  
if(strlen($output)>0)  
    $output = substr($output, 0, -1);  
return $output;

Вот таким образом я решил вопрос с организацией архива на своем блоге. Самое забавное то, что в процессе работы над статьей, я наткнулся на уже готовое решение данной проблемы от комманды MODx, называется Archivist (недоступен) · копия в Web Archive. Как я его не заметил несколько месяцев назад, когда делал сайт - уму непостижимо. Ну ничего. Изобрел свой велосипед - стал умнее и опытнее =)