вторник, 5 февраля 2008 г.

счетчик посещений страницы и настройка рейтинга страниц по нему

Задача: Необходимо считать количество посещений страниц (пока без учета "уникальности" просмотра, то есть грубо говоря посетитель может "накручивать" просмотры, просто перезагружая страницу) и выстроить рейтинг страниц с учетом их посещений.

Решение: Начнем с того, что нам известно - вывод какого либо рейтинга страниц в 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 или с сессиями :)

пятница, 1 февраля 2008 г.

теговое облако для 4000 документов

Попробовав применить сниппет TvTagCloud к своей огромной базе документов, получил превышение ожидания запроса (или что то в этом духе). Мне необходимо было выводить определенное количество тегов из недавно созданных документов плюс минимизировать использование ресурсов базы/процессора. Пришлось погуглить и дописать свой код.
<?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. Может с моей задачей справился бы и он.