Ограничение голосования по IP для easyComm
Хотел разместить в Готовые решения — но не хватает рейтинга. ЛожуОставлю тут — если покажется нужным — прошу перенести куда следует.
У клиента система оценки товаров/услуг построена на компоненте — easyComm.
Из-за частых «неположительных» оценках было поручено мне создать нечто, что ограничит голосование на N-ое количество дней. Предмодерация не подошла (как заявили — «предмодерация — говорит о ложных отзывах».
Я создал «это» на основе нескольких подсмотренных в сети кусков. Самое главное что работает)
Не судите строго — первый опыт написания сниппетов.
Создал сниппет — voting_ban:
&unlock — действие при разрешённом голосовании (я поставил вызов формы для голосования)
&day — Количество дней в течении которого нельзя повторно голосовать
Я использую так:
[[!voting_ban? &unlock=`[[!ecForm?]]` &day=`7`]]
Надеюсь кому нибудь пригодится)
ps. Если профессионалы найдут ошибки, либо просто подскажу как улучшить/сократить код — буду рад)
UPD:
Всё что делает сниппет можно было прочесть по комментариям в коде, но продублирую (по просьбе трудящихся)
1) Определяем IP посетителя,
2) На основании параметра &day (по умолчанию 7 дней) вычисляем период в течении которого запрещено голосовать
3) Получаем список IP которые участвовали в голосовании в данный период времени для данного ресурса
4) Сравниваем текущий IP с выборкой — если не находим — показываем форму для голосования &unlock
У клиента система оценки товаров/услуг построена на компоненте — easyComm.
Из-за частых «неположительных» оценках было поручено мне создать нечто, что ограничит голосование на N-ое количество дней. Предмодерация не подошла (как заявили — «предмодерация — говорит о ложных отзывах».
Я создал «это» на основе нескольких подсмотренных в сети кусков. Самое главное что работает)
Не судите строго — первый опыт написания сниппетов.
Создал сниппет — voting_ban:
<?php
// очищаем кеш
$id = $modx->resource->get('id');
$docObj = $modx->getObject('modResource',$id);// $docObj - объект ресурса, кеш которого надо почистить
$key = $docObj->getCacheKey();
$cache = $modx->cacheManager->getCacheProvider($modx->getOption('cache_resource_key', null, 'resource'));
$cache->delete($key, array('deleteTop' => true));
$cache->delete($key);
//Получаем IP посетителя
$ip = $_SERVER['REMOTE_ADDR'];
//Получаем ID текущего ресурса
$id = $modx->resource->get('id');
//текущая дата
$today = date('Y-m-d');
// сколько дней нельзя голосовать
$day = (isset($day)) ? $day : '7';
//действие при разрешённом голосовании
$unlock = (isset($unlock)) ? $unlock : '';
//вычисляем ПЕРВУЮ дату в периоде в котором нельзя голосовать повторно (вторая дата - текущая дата)
$date = date('Y-m-d',strtotime("-$day day", strtotime(preg_replace('~^(\d+)\.(\d+)\.(\d+)$~', '$3-$2-$1', $today))));
// отбираем записи IP всех голосовавших с датой публикации больше ПЕРВОЙ для текущего ресурса
$sql = "SELECT C.ip AS ip FROM modx_ec_messages C LEFT JOIN modx_ec_threads D ON C.thread=D.id AND C.date>'$date'
WHERE D.resource =".$id ;
$q = $modx->prepare($sql);
$q->execute(array(0));
$arr = $q->fetchAll(PDO::FETCH_ASSOC);
foreach ($arr as $arr_one) {
$tmpip = $arr_one["ip"];
$allip[] = $tmpip;
}
//сравниваем IP посетителя с полученными
if (in_array("$ip", $allip)) {
//Действие если запрещено
}
else{
//Действие если разрешено
print $unlock;
}
Параметры:&unlock — действие при разрешённом голосовании (я поставил вызов формы для голосования)
&day — Количество дней в течении которого нельзя повторно голосовать
Я использую так:
[[!voting_ban? &unlock=`[[!ecForm?]]` &day=`7`]]
Надеюсь кому нибудь пригодится)
ps. Если профессионалы найдут ошибки, либо просто подскажу как улучшить/сократить код — буду рад)
UPD:
Всё что делает сниппет можно было прочесть по комментариям в коде, но продублирую (по просьбе трудящихся)
1) Определяем IP посетителя,
2) На основании параметра &day (по умолчанию 7 дней) вычисляем период в течении которого запрещено голосовать
3) Получаем список IP которые участвовали в голосовании в данный период времени для данного ресурса
4) Сравниваем текущий IP с выборкой — если не находим — показываем форму для голосования &unlock
Комментарии: 8
Зачем это нужно понятно из названия. А что делает данный сниппет? Потенциальный пользователь данного решения должен копаться в коде, чтобы понять?
И ещё вопрос.
П.С. Данное решение никак не тянет на готовое.
И ещё вопрос.
Ложу тут — если покажется нужным — прошу перенести куда следует.В данном предложении как правильно читать — лОжу или ложУ?
П.С. Данное решение никак не тянет на готовое.
Ок, пусть лежит тут — думаю всё же кому нибудь пригодится
оффтоп
В данном предложении как правильно читать — лОжу или ложУ?Как удобно так и читайте.
Если вам интересно, могу объяснить почему данное решение вряд ли кто будет использовать.
Если Вас не затруднит
Смотрите, Сергей, если задача — разрешить добавлять комментарий 1 раз в n дней, то решается она несколькими строчками.
Вариант 1. Через сниппет как у вас.
Если у этого компонента есть событие добавления комментария по аналогии с Tickets, то форма показывается, но при добавлении комментария плагин проверяет возможность добавления.
Вот как минимум 2 варианта.
П.С. Ещё было бы логично проверять почту. У пользователя ip может быть динамическим. А лучше разрешать оставлять отзыв только авторизованным пользователям. Тогда ещё проще.
Вариант 1. Через сниппет как у вас.
$sql = "SELECT 1 FROM modx_ec_messages C LEFT JOIN modx_ec_threads D ON C.thread=D.id
WHERE D.resource = {$modx->resource->id} AND C.date>DATE_SUB(NOW(),INTERVAL {$day} DAY) AND ip = ?" ;
$stmt = $modx->prepare($sql);
$stmt ->execute($_SERVER['REMOTE_ADDR']);
if ($stmt->rowCount() ) {
// Запрещено
return '';
}
// Выполняем указанные сниппет
return $modx->runSnippet($snippet, $scriptProperties);
Ну и вызывать так// Вместо unlock указываем snippet и любые другие параметры указанного сниппета
[[!voting_ban? &snippet=`ecForm` &day=`7`]]
Вариант 2. Через плагин.Если у этого компонента есть событие добавления комментария по аналогии с Tickets, то форма показывается, но при добавлении комментария плагин проверяет возможность добавления.
Вот как минимум 2 варианта.
П.С. Ещё было бы логично проверять почту. У пользователя ip может быть динамическим. А лучше разрешать оставлять отзыв только авторизованным пользователям. Тогда ещё проще.
Спасибо за объяснение. Повторюсь — писал впервые из нескольких кусков.
писал впервые из нескольких кусковЭто очень заметно. Чисто для понимания давайте пробежимся по коду.
// очищаем кешЗачем?
П.С. Вообще это можно сделать непрограммно — просто создавать некэшированные страницы. Но в данном случае не понятно, зачем это нужно.
//Получаем ID текущего ресурсаЗачем? В первой строчке уже получали.
$id = $modx->resource->get('id');
//текущая датаЗачем? В strtotime и так по умолчанию берется текущая дата.
$today = date('Y-m-d');
$date = date('Y-m-d',strtotime("-$day day", strtotime(preg_replace('~^(\d+)\.(\d+)\.(\d+)$~', '$3-$2-$1', $today))));Это вообще что за конструкция? Явно откуда-то скопирована без понимания. Хватило бы
$date = date('Y-m-d',strtotime("-$day day"));
Но и это лишнее, так как в mySql есть готовые функции для работы с датами.$tmpip = $arr_one[«ip»];А почему нельзя было написать так $allip[] = $arr_one[«ip»]?
$allip[] = $tmpip;
if (in_array("$ip", $allip)) {$ip нужно указывать без кавычек.
print $unlock;Возврат значений из сниппета должен быть через return.
Явно есть над чем поработать.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.