Начисляем автору статьи очки за каждое 1000 посещение его страницы.

Главные вкладки

Аватар пользователя beliy_snow beliy_snow 10 марта 2007 в 18:27

Начнем с того, что пойдем в админку и включим модуль Profile, если он ещё не включен. Для чего это нужно - читаем дальше.

Administer -> User management -> Profile. Тут создаем новое single-line textfield поле, в котором будем указывать сколько очков начислять пользователю за каждое 1000 посещение его ноды. Категорию для этого поля обзываем "Какие-нибудь preferences". Заголовок поля будет, например "Points per 1000 Article views" и его "form name" что-нибудь типа "profile_points". "Visibility" ставим "Public field, content shown on profile page but not used on member list pages." (это потом можно будет убрать). Чтобы админ мог редактировать это поле ему нужно будет зайти в профайл пользователя, там найти кнопку "Какие-нибудь preferences", ввести нужное значение и сохранить. Мы же сохраняем, едем дальше.

Дальше скачаем и установим модуль UserPoints, чтобы сохранять очки пользователя в базу и функционал для того, чтобы не изобретать велосипед.
Идем в настройки этого модуля (Administer -> Site configuration -> Userpoints) и устанавливаем все поинты в 0, нам ведь надо начислять очки только за просмотр, а не написание, комментирование и т.д.

Суть происходящего такова: модуль UserPoints имеет функцию "userpoints_nodeapi()". Это огромное для нас подспорье. Смотрим в код - обрабатываемые этой функцией операции следующие - insert, delete, update. Теперь идем в файлик modules/node/node.module, ищем функцию node_load(), листаем вниз и видим, ага - node_invoke_nodeapi($node, 'load'). А значит это примерно следующее - когда вызывается функция node_load(), а вызывается она часто, то node_invoke_nodeapi() ищет по всем установленным модулям функцию "имя_модуля_nodeapi()" и вызывает её с параметром 'load'. У нас эта функция есть, а обработки параметра 'load' - нету. Что нам остается? Правильно - добавить обработчик операции 'load' в функцию userpoints_nodeapi(). Что и сделаем.

<?php case 'load':
// берем статистику для нашей просматриваемой ноды
$stats_array = statistics_get($node->nid);

// проверяем - есть ли у автора ноды какие-нибудь начисленные очки, а именно когда они были начислены
$result = db_query("SELECT last_update FROM {userpoints} WHERE uid = %d", $node->uid);
if ($last_update_array = db_fetch_array($result))
// если были - сохраняем этот timestamp
$last_update = $last_update_array['last_update'];
else
// если нет - приравниваем его к дате начисления счетчика посещений
$last_update = $stats_array['timestamp'];

if (
// смотрим, есть ли посещения вообще, а то мало ли
$stats_array['totalcount'] &&
// это 1000-е посещение?
$stats_array['totalcount'] % 1000 == 0 &&
// ***
($stats_array['timestamp'] - $last_update > 60*60*24 ||
// это условие говорит о том, что у пользователя до этого не было очков и нам-таки придется ему начислить
$last_update == $stats_array['timestamp']))
{
// загружаем автора ноды
$user = user_load(array('uid' => $node->uid));
// из модуля Profile берем информацию о том сколько начислять нашему автору
profile_load_profile($user);
// если админ не указал сколько начислять - подставляем дефолтовое значение, которое определяем в начале файла userpoints.module
$points = ($user->profile_points) ? $user->profile_points : USERPOINTS_DEFAULT_1000;
// собственно начисляем
_userpoints_update_points($points, $node->uid, "op=$op type=".$node->type);
}
break;
?>

***: Теперь самое непонятное для меня место в этом коде. Проверяем разницу между моментом последнего начисления очков пользователю и моментом зачисления 1000 посещения. Если больше суток (взял из головы), то пропускаем это условие, если нет, то это говорит о следующем.
1) Какой-то чел зашел на страницу и сделал автору 1000 подключений, автору начислили очки.
2) Если чел будет жать F5 - будет вызываться наш обработчик, в котором без этого условия каждый раз начислялись бы очки автору ноды, а зачем это надо?
3) Если зайдет автор статьи, то понятное дело, его посещение не будет зачтено и будет так же 1000 посещений и опять же без этого условия будут начисляться очки.

До конца не понимаю почему так, с утра разберусь.

Несколько моментов. Модуль Profile и модуль UserPoins имеют такие хуки, как _user(). Это говорит нам о том, что когда юзер зайдет на страницу своего профайла он может увидеть сколько у него очков на текущий момент и сколько очков ему будет начисляться за каждое 1000 посещение, что иногда может составлять коммерческую или иную тайну. Выход прост - ищем функции "profile_user()" и "userpoints_user()", комментируем куски кода которые нам эту информацию подсовывают, все.

Комментарии

Аватар пользователя SadhooKlay SadhooKlay (не проверено) 11 марта 2007 в 7:19

Полный бред

Вернее, пардон, реализация красивая но зачем это?
Я могу зарегистрироваться с другим акаунтом и зайти сам на свою статью 100 000 000 раз.
Или даже проще, написать скрипт который будет через прокси сервера, меняя IP заходить периодически по данной ссылке на вашем сайте, а скрипт положить например к себе на хостинг.
ИМХО, идея не востребованная — рейтинг, не нужен как класс, вобще.
Если интересно, я могу вам много аргументов привести, отнюдь не в пользу рейтинга автора.

Хотя сделано, повторюсь, изящно и лаконично.



----------------------------------------------------------
Локализация некоторых модулей

Аватар пользователя dbzer0 dbzer0 11 марта 2007 в 7:37

Ну тут видишь, от проэкта зависит. Не поспоришь конечно, что накрутить то можно. Знающий человек обойдет все. Мне идея эта пригодилась, попробую сегодня запустить на своем проекте.

Аватар пользователя beliy_snow beliy_snow 12 марта 2007 в 9:34

Замечания:
1) На ресурсе, который использует данную схему юзеры не могут регистрироваться сами, их регает админ.
2) 100 000 000 раз - из которых засчитается сколько?! Смотрим внимательнее пост, должны пройти сутки с момента последнего посещения страницы.
3) Прокси сервера - это уже лучше, но в данном случае "овчинка выделки не стоит", ибо на этом ресурсе получать очки за 1000 просмотров не единственный и не приоритетный способ.
4) Рейтинг, как класс, нужен именно для моего проекта. Применять его на своих - решать каждому в отдельности.

Аватар пользователя dbzer0 dbzer0 11 марта 2007 в 7:35

Уже сделал, я не стал править модуль node, а изменил шаблон коммента. Помимо постинга комментов и статей сделал так же и с просмотром, создал таблицу, в которой хранятся проверенные значения количества просмотров (чтобы не начислять дважды) и проверяю по кратности разницу между текущим количеством и сохраненным. Если же разница есть (сумма просмотров опять набрана), то юзаю функцию из модуля userpoints для начисления дополнительных поинтов:

userpoints_userpointsapi('points', $number_of_points, $uid, $event);

А вывожу в теме коммента, используя опять же его api:

$current_points = userpoints_get_current_points($uid);

Аватар пользователя beliy_snow beliy_snow 12 марта 2007 в 9:37

Я старался сделать функционал, который будет максимально использовать средства, предложенные самим друпалом.
Была идея с отдельной таблицей, но как оказалось - "зачем?" - если можно включить Access log и не париться. Если по проекту нужно будет считать количество посещений с момента первого захода на страницу - тогда да, будем делать по-другому, о чем и напишем непременно.