Улучшаем механизм оценки статей в Joomla 1.0

  • Среда, 08 августа 2007

Стандартный компонент публикаций материалов Joomla поддерживает возможность оценки материалов посетителями сайта. Однако встроенный механизм оценки материала имеет существенный недостаток: он позволяет пользователям повторно оценивать материал. Ограничение конечно есть: нельзя подряд оценивать один и тот же материал с одного IP адреса, а вот поочередно два пользователя могут сколь угодно «накручивать» оценку. В этой статье я хочу рассказать о том, как можно немного улучшить механизм оценки и затруднить возможность «накрутки» рейтинга материала.

Для того, чтобы затруднить процесс накрутки рейтинга вполне достаточно будет запоминать IP-адрес не последнего оценившего материал пользователя, а всех, кто принял участие в оценке.

Для хранения данных о материалах и IP-адресах пользователей добавим дополнительную таблицу jos_content_rating_ext. Ее можно легко создать в phpMyAdmin.

CREATE TABLE `jos_content_rating_ext` (
  `content_id` int(11) NOT NULL default '0',
  `user_id` int(11) NOT NULL default '0',
  `rating` int(11) unsigned NOT NULL default '0',
  `ip` varchar(50) NOT NULL default '',
   KEY `idx_content` (`content_id`, `ip`, `user_id`)
) TYPE=MyISAM;

Теперь модифицируем функцию сохранения результатов оценки статьи. Для этого необходимо открыть файл /components/com_content/content.php. Перед началом модификации рекомендую сделать резервную копию этого файла. Чтобы при желании можно было легко отменить внесенные изменения.

Итак, приступим. Находим в этом файле строчки:

function recordVote() {
     global $database;

и заменяем их на:

function recordVote() {
     global $database, $my;

Затем чуть ниже находим кусок кода:

 $query = "INSERT INTO #__content_rating ( content_id, lastip, rating_sum, rating_count )"
               . "\n VALUES ( " . (int) $cid . ", " . $database->Quote( $currip ) . ", " . (int) $user_rating . ", 1 )";
               $database->setQuery( $query );
               $database->query() or die( $database->stderr() );;

и после него добавляем:

               $query = "INSERT INTO #__content_rating_ext ( content_id, user_id, rating, ip )"
               . "\n VALUES ( " . (int) $cid . ", " . $my->id . ", " . (int) $user_rating . ", " . $database->Quote( $currip ) . " )";
               $database->setQuery( $query );
               $database->query() or die( $database->stderr() );

Затем еще чуть ниже находим код:

		} else {

			if ($currip != ($votesdb->lastip)) {
				$query = "UPDATE #__content_rating"
				. "\n SET rating_count = rating_count + 1, rating_sum = rating_sum + " . (int) $user_rating . ", lastip = " . $database->Quote( $currip )
				. "\n WHERE content_id = " . (int) $cid
				;
				$database->setQuery( $query );
				$database->query() or die( $database->stderr() );

и заменяем его на:

		} else {
			$currip = ( phpversion() <= '4.2.1' ? @getenv( 'REMOTE_ADDR' ) : $_SERVER['REMOTE_ADDR'] );
			$query = "SELECT *"
			. "\n FROM #__content_rating_ext"
			. "\n WHERE content_id = " . (int) $cid
			. (($my->id) ? "\n AND user_id = " . $my->id : "\n AND ip = " . $database->Quote( $currip ) )
			;
			$database->setQuery( $query );
			$cnt = $database->loadResult();

			if ($cnt == 0 ) {
				$query = "UPDATE #__content_rating"
				. "\n SET rating_count = rating_count + 1, rating_sum = rating_sum + " . (int) $user_rating . ", lastip = " . $database->Quote( $currip )
				. "\n WHERE content_id = " . (int) $cid
				;
				$database->setQuery( $query );
				$database->query() or die( $database->stderr() );

				$query = "INSERT INTO #__content_rating_ext ( content_id, user_id, rating, ip )"
				. "\n VALUES ( " . (int) $cid . ", " . $my->id . ", " . (int) $user_rating . ", " . $database->Quote( $currip ) . " )";
				$database->setQuery( $query );
				$database->query() or die( $database->stderr() );

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

Следует заметить, что эта защита достаточно простенькая, и конечно не спасет от злоумышленников твердо задавшихся целью накрутить рейтинг. К примеру ее легко можно обойти посредством использования анонимных прокси-серверов. Однако в любом случае, это лучше, чем стандартный механизм.

Однако, помимо положительных эффектов, есть и небольшая ложка дегтя. В наше время достаточно частое явление когда несколько пользователей выходят в интернет под одним внешним IP. И данная модификация позволит проголосовать только первому из группы пользователей этого адреса.

Частично эту проблему можно решить, предложив пользователям сначала авторизоваться на сайте. Потому как для авторизованных пользователей проверка производится не по IP, а по их идентификатору.

Желаю успешных экспериментов, жду отзывов и вопросов на форуме!

Joomla!® CMS — пожалуй, лучшая система управления контентом с открытым исходным кодом

Логотип Joomla

Joomla! — это больше, чем просто программное обеспечение, это люди, включающие разработчиков, дизайнеров, системных администраторов, переводчиков, копирайтеров, и, что самое главное — простых пользователей.

Мы рады пригласить вас в ряды нашего сообщества!

Свернуть

Коротко о главном в Joomla

Новости портала

Новое в блогах

Видео

Форум о Joomla