Главное меню
все форумы все темы форума добавить тему
Класс комментариев
Начал проектировать класс для работы с комментариями. Пришлось немного поломать голову, чтобы он сравнительно легко интегрировался с модулями
Но, в общем, постепенно начинает вырисовываться.
Для хранения комментариев принято решение использовать структуру nested sets. Она позволяет избежать рекурсии и вообще построить дерево одним запросом. Правда, у нее есть и свои ограничения. Например, она не позволяет строить лес (то есть несколько деревьев сразу). Чтобы обойти это ограничение, пришлось ввести суррогатный пустой комментарий. Но в общем-то это даже не плохо - теперь комментарии почти не имеют жесткой связи с модулями.
 
Попробую немного описать как это работает. Вопросы и комментарии приветствуются.
 
При запросе комментариев модуль передает суррогатный ключ, уникальный в пределах модуля, и url страницы.
ключ может быть как просто числовым (например, в модуле новостей можно просто передать id новости), так и составным (например, страница с альбомом 'album_1', а страница с фотографией альбома - 'image_1').
url нужен для того, чтобы можно было узнать на какой странице размещен комментарий (например, при модерации).
 
Метод LabComments::getComments($key, $url) возвращает массив вида
 
Text

array
  'add_id' => 2 //id скрытого комментария. Будет использоваться
  ля ссылки "добавить комментарий"
  'comments' => //непосредственно массив пользовательских комментариев
    array
      0 =>
        array
          'comment_id' => 3
          'text' => '[b]test[/b]'
          'text_html' => '<b>test</b>' //не уверен до конца надо ли хранить
                  распарсенные комментарии или рассчитывать на кэширование выборки
          'putdate' => '0000-00-00 00:00:00'
          'user_id' => 1
          'login' => 'user' //пока рассматриваю вариант хранения логинов
                  и для зарегистрированных пользователей тоже, так как логины
                  в системе не меняются, а таблицу пользователей не придется дергать
                  при каждой выборке
          'email' => 'email@domain.com'
          'status' => 1 //статус комментария. Пока что придумал следующие статусы:
                  ожидает модерации, опубликован, удален автором, удален модератором, скрыт.
          'level' => 1 //уровень вложенности дерева. Начинается с 1,
                  так как уровень вложенности 0 имеет скрытый комментарий
          'leaf' => true //ключ, показывающий что данный элемент не имеет наследников.
                  Это для удобства построения дерева.
          'moderate' => array //массив пользователей (или массив id пользователей),
                  пожаловавшихся на этот комментарий
 

 
Что радует, удалось избежать передачи ключа материала практически везде, кроме запроса списка комментариев и удаления всех комментариев. Так что серьезных переделок в модулях, вроде бы, не потребуется.
 
Если есть вопросы (а они наверняка есть ) - милости прошу.
Каким образом Вы планируете организовать структуру таблицы mysql? Я так понял что ключи в массивах и будут основными полями таблицы в бд?
Пока что таблицы выглядят так:
 
MySQL
CREATE TABLE IF NOT EXISTS ?_comments (
  `comment_id` int(11) NOT NULL auto_increment,
  `item_id` int(11) NOT NULL,
  `text` text,
  `text_html` text,
  `putdate` datetime NOT NULL default '0000-00-00 00:00:00',
  `updated` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `user_id` int(11) default NULL,
  `login` varchar(50) default NULL,
  `email` varchar(50) default NULL,
  `status` tinyint(1) NOT NULL,
  `level` tinyint(1) NOT NULL default '0',
  `left_key` int(11) NOT NULL,
  `right_key` int(11) NOT NULL,
  `moderate` varchar(255) default NULL,
  PRIMARY KEY  (`comment_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
CREATE TABLE IF NOT EXISTS ?_comments_items (
  `item_id` int(11) NOT NULL auto_increment,
  `item_key` char(20) NOT NULL,
  `url` char(100) NOT NULL,
  `module_id` int(11) NOT NULL,
  PRIMARY KEY  (`item_id`),
  UNIQUE KEY `module_id` (`module_id`,`item_key`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

 
right_key, right_key и level - ключи необходимые для построения структуры nested sets. Обо всем остальном я написал выше.
Понятно. А как будет выглядеть интеграция этого модуля с самодельными модулями?
На самом деле, полностью обкатанной схемы пока нет (собственно, и класс пока не закончен), но предварительно мне это представляется как-то так:
В начале файла index.php модуля подключается обработчик для работы с комментариями. Он проверяет не относится ли переданная переменная action  к его компетенции, если относится  - берет управление на себя, если нет - снова передает его модулю. Брать на себя управление он будет при любых операциях связанных с комментариями, кроме отображения комментариев - этим должен будет заниматься сам модуль. Вроде бы получается все достаточно просто и логично. Из неочевидного следующее:
 
1. Настройки и права на комментарии. Автор модуля должен будет их добавить в config.xml. Это не проблема, так как он все равно будет править модуль, но если они будут изменяться и дополняться - он должен это отслеживать.
 
2. Непонятно где хранить шаблон для форм (и нужен ли он вообще). В принципе, форму можно генерить прямо в переменную, но тогда из простой кастомизации ее останется только css.
 
3. Нельзя будет сделать внутри модуля закрытых публикаций. То есть если одна публикация видна всем пользователям, а другая - только отдельной группе, то закрытую публикацию смогут комментировать все, так как класс комментариев не имеет ни малейшего представления о разграничении прав внутри модуля. Правда, для того чтобы оставить такой комментарий надо будет знать (или подобрать) id одного из комментариев к закрытой публикации.
Значит через саму админку ничего подключать не придется?
Интересно насчет пункта № 3, потому что в сложных модулях навернека есть распределение прав.
Ну тут больше речь не об возможностях управления через интерфейс, а об удобном инструменте для разработчиков, быстро интегрировать комментарии в свои модули. На месте разработчика модуля я бы все равно сделал настройку для включения/выключения комментариев. Вполне возможно что он захочет реализовать какие-нибудь хитрые правила комментирования, возможность исправления комментариев и т.п.
 
С пунктом 3 я пока не знаю что делать. Теоретически, эта уязвимость позволяет просматривать подзамочные комментарии. Так что либо не выводить текст комментария на который отвечают, либо придумывать какое-то решение.
Loki:
Ну тут больше речь не об возможностях управления через интерфейс, а об удобном инструменте для разработчиков, быстро интегрировать комментарии в свои модули. На месте разработчика модуля я бы все равно сделал настройку для включения/выключения комментариев. Вполне возможно что он захочет реализовать какие-нибудь хитрые правила комментирования, возможность исправления комментариев и т.п.

Полностью с Вами согласен.
Loki:

С пунктом 3 я пока не знаю что делать. Теоретически, эта уязвимость позволяет просматривать подзамочные комментарии. Так что либо не выводить текст комментария на который отвечают, либо придумывать какое-то решение.

Скорее всего этот вопрос можно будет решить в дальнейшем. Пока сложно подкинуть какую либо идею, прежде чем увидеть в действии.
 
Как планируете организовать модерацию?
Defari:
Как планируете организовать модерацию?

Не очень понял вопрос, поэтому просто расскажу что у меня получается сейчас:
будет два класса. Один занимается только работой с комментариями и их структурой (добавление, изменение, выборка и пр). Он ничего не знает ни о политике прав, ни о группах ни о чем другом. Просто проверяет корректность входных данных.
Второй класс отвечает за взаимодействие с пользователем, построение форм, проверка прав и пр. Его можно просто подключить к своему модулю, получив стандартные комментарии. Или можно от него создать наследника с какими-нибудь экзотическими возможностями. В базе планируется что он будет уметь реализовывать взаимодействие со всеми функциями первого класса традиционным образом или через аякс (json).
Какие нужны права?
Сейчас я сделал такие:
1. добавление комментария
2. редактирование собственного комментария
3. удаление собственного комментария
4. возможность пожаловаться на комментарий
5. публикация премодерируемого комментария
6. редактирование чужого комментария
7. удаление чужого комментария (сокрытие)
8. восстановление удаленного комментария
9. удаление ветви комментариев
 
Не слишком ли я размахался? Возможно, просто стоит ввести понятие модератора и администратора. За модератором закрепить права 5 и 7 (6 - под вопросом), а за администратором - все остальное.
Или это будет недостаточно гибко?
Loki:

Или это будет недостаточно гибко?

Скорее всего проще будет, если ввести понятие модератора и администратора, и за ними четко закрепить права.
Согласен, что не так гибко, но зато четкая логика и порядок.
Выложил версию с новой версией смарти и комментариями в отдельную ветку
svn://labcms.ru/repos/flex/branches/smrty_3.1+comments
Пока что комментарии подключены только к модулю новостей... Да и вообще это еще черновик. Номер версии не обновлял, так что обновления БД не произойдет. Необходимо либо установить заново, либо создать недостающие таблицы ?_comments и ?_comments_items (структура в файле kernel/install/kernel.sql).
 
Что сделано:
- древовидные комментарии к каждой новости
- счетчик комментариев для каждой новости (скрытые новости считает как существующие)
- добавление/редактирование/удаление
- модерирование
- администрирование
- жалобы на спам
 
Жалобы на комментарии оставлять можно, но интерфейса модерации еще нет
Так же пока не работает премодерация, ну и какой-никакой антиспам нужен.
Так же нужно будет в дизайне предусмотреть подсветку удаленных сообщений для администратора.
 
В модуле новостей изменения внесены в трех местах: в index.php подключено управление коментариями, в show.php - вывод комментариев к новости, в news.php - к новостям добавлены счетчики комментариев. Естественно присутствуют правки config.xml и шаблонов. В остальном комментарии вполне автономны.
 
Пробуйте, высказывайтесь.
Будем допиливать постепенно.
Почему-то нет ссылки для добавления комментария к новости, зашел админом.
Defari:
Почему-то нет ссылки для добавления комментария к новости, зашел админом.

А в настройках модуля комментарии включили?
Все, разобрался. Не посмотрел в настройках...
Сейчас потестим
 
Update:
Посмотрел. Всё работает славно
Что сейчас замечено:
1. Добавил для зарег. пользователей право пожаловаться на спам, но иконки нет.
2. Удалил ветку комментариев, счетчик показывает старое к-во сообщений.
Сегодня вечером посмотрю подробнее.
Defari:

1. Добавил для зарег. пользователей право пожаловаться на спам, но иконки нет.
2. Удалил ветку комментариев, счетчик показывает старое к-во сообщений.

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

Loki, вроде нужно будет ещё антиспам реализовать? В релизе комментарии будут только у новостей или это с возможностью подключения к иным модулям? (Ведь Вы писали об универсальности).
mushtat:
Loki, вроде нужно будет ещё антиспам реализовать? В релизе комментарии будут только у новостей или это с возможностью подключения к иным модулям? (Ведь Вы писали об универсальности).

Уже сделал. Я и сам собираюсь комментарии использовать, так что засилие роботов на сайте мне совсем не улыбается
 
Под релизом я в данном случае имел ввиду объединение с рабочей веткой. До стабильного релиза еще много что хотелось бы сделать.
 
Из модулей, как мне кажется, стоило бы интегрировать комментарии с модулем новостей, модулем статичных страниц (причем, чтобы еще можно было включать/выключать комментарии для отдельных страниц) и фотоальбомом.
 
Еще бы, наверное, было интересно сделать комментарии к результатам голосования, но Дмитрий куда-то пропал. Наверное, в отпуске.
Ну вот, класс переместился в trunk, так что теперь доступен даже тем, кто совсем не дружен с svn
Здравстуйте! Прошу, пожалуйста, обьяснить, как встроить форму добавления коментариев прямо на страницу комментария, а не на отдельную, как это сделано сейчас. Тыкался всю ночь, но не разобрался.
UPD: Чего-то наделал, после ошибки пишет вот такое - Нарушена структура комментариев. Максимальный ключ равен 8 и не равен 2 Ну тем не менее страница показывается. Что я делал - указал в свойствах дива смарти-условие
<div class="commentsection" {if $comments.counter eq 0} style=\visibility:hidden;\{/if} >. Это, как Вы понимаете, скрывает див с коментами если коментов ноль (поставить условие {if $comments} в шаблоне не позволяет структура). И пишет такую надпись. Но на странице с опубликованным коментарием её нету. При удалении моего условия напись с ошибкой сохраняется. Что мне делать? Сайт тот же, всё видно своими глазами ).
Форма комментариев на странице должна выглядеть примерно так:
Smarty
<form action="{url action="comment_add" var1=$comments.add_id}" method="post">
<input type="hidden" value="{$_user->token}" name="token" />
Комментарий<textarea name="text"></textarea>
<input type="submit" value="Сохранить"/>
</form>

это для авторизованного пользователя.
 
Сообщение выдается только админу и выдается тогда, когда действительно нарушена структура комментариев. Структура nested sets в этом плане более уязвима чем adjacency list. Так что придется Вам либо разобраться с ней и исправить ключи руками, либо почистить таблицы с комментариями, чтобы они создавались заново.
тут же всплывает еще пара вопросов:
-как должна выглядеть форма для незарегистрированного пользователя?
-где и каким образом я могу с ней разобраться, со структурой? что и в какую сторону исправлять? Почистить не вопрос, но нужно ведь разобраться. Так и не понял, почему она нарушилась...
Для незарегистрированных выглядит так:
Smarty
<form action="{url action="comment_add" var1=$comments.add_id}" method="post">
        <input type="hidden" value="{$_user->token}" name="token" />
        Имя
        <input type="text" class="catch" value="" name="login">
        <input type="text" name="{$core_config.catcher}">
        Email
        <input type="text" name="email">
        Комментарий
        <textarea name="text"></textarea>
        <input type="submit"" value="Сохранить">
</form>

тут поле
Smarty
<input type="text" class="catch" value="" name="login">

является скрытым и служит для отлова роботов. Настоящий же логин вводится в поле
Smarty
<input type="text" name="{$core_config.catcher}">

 
Структура нарушилась в результате неудачной попытки добавления комментария.
Про устройство nested sets можно почитать тут.
Если разбираться нет желания и важных комментариев нет, можно просто очистить таблицы _comments и _comments_item
Здравствуйте, Loki! После перерыва вернулся к LabCMS и сразу уперся в проблему: не активировались комментарии. Когда Вы выложили версию с классом комментариев, сразу попробовал и все работало (3.4.733 -> 3.5.750). У меня 2 хоста с LabCMS: рабочий и эталонный. Рабочий я обновляю, а эталонный сношу и устанавливаю заново с каждой версией. Так вот рабочий, с действующими комментами, нормально обновился (3.5.750 -> 3.6.752), а на чистой установке (3.6.752) они не появились.
А в каком, собственно, поле отмечал чекбокс комментариев, забыл по прошествии времени. Короче, на второй день поисков догадался проверить формы с Firebug, и когда отключитл стили, чекбоксы нашлись.
 
Скриншоты здесь
 
То есть, при обновлении функция комментирования сохраняется, а интерфейс меняется.
При чистой установке комменты по умолчанию отключены, а добраться до них нельзя.
 
Или это не ошибка, а такой фильтр для юзеров, пока версия не зарелизена?
 
Пока искал концы, поставил LabCMS под Win 7, там то же самое.
На самом деле тут штука вот в чем:
для суперадмина нет настройки прав, так как в этом нет смысла: в независимости от выставленных прав, ему будет все позволяться. Вы спросите для чего же он тогда вообще присутствует в настройках? А присутствует он потому, что кроме раздачи прав есть еще и раздача настроек. По умолчанию, настройки раздаются только группе незарегистрированных пользователей и от них наследуются всеми остальными. Если же требуется чтобы у каждой группы были свои настройки, то эта опция включается в настройках сайта, после чего появляются дополнительные элементы в настройках групп.
В общем, Вы напрасно искали настройки модулей в настройках групп - они находятся в соседней закладке настроек сайта.
А я постараюсь подумать как спрятать лишнее из групп  
Да-а… Ну я и м***!!!
Что стоило отметить чекбокс, ведь смотрел на него десять раз! А главное, что первоначально у меня все сразу заработало, значит все сделал правильно. А потом провал в сознании
 
Спасибо, Loki!