Переходим с phpbb2 на Drupal. Улучшение (исправление) встроенного форума.
Прислано: apple_rom
вт, 21/08/2007 - 12:02
Возможно нижеизложенная информация профессионалам покажется пустой, водянистой и неправильной, но для новичков, которые перешли на друпал, думаю, окажется полезной. В том числе и сам буду признателен получить рекомендации и ответы на ещё не решённые вопросы.
После установки обработать напильником
Первое, что испытывают пользователи (после перехода сайта на друпаловский движок, соответственно и друпаловский форум), привыкшие к интерфейсу а-ля phpbb - написать чего обидно-злобного или просительного по поводу "верните, как было". :)
Но назад дороги нет, потому попытаемся сделать то, чего нет самостоятельно. Нижеизложенное рассчитано на не искушённых в PHP-программировании людей (как я), хотя и знающих, где-что лежит, кроме того знакомых с другими языками программирования (как минимум С/С++).
Не пытаясь придумать каких-то "искусственных" примеров, просто перечислю всё, с чем пришлось столкнуться самому при переходе форум PHPBB2 - CMS Drupal
Установка Drupal
Проблем с самой установкой быть не должно. Все технические мелочи в виде правильно установленных логинов-паролей и т.п. не в счёт. На момент написания был установлен Drupal 5.2 в корневую директорию сайта.
Нужные модули для переноса старого форума
Самая главная проблема и боль. Совет на будущее, если Вы недавно "сели за Друпал" и при этом обязательно нужно перенести старый phpbb-форум - не тратьте время на "баловство" с настройками всевозможных модулей самого друпала, сначала отработайте процесс переноса и лишь потом "балуйтесь" всякими другими модулями.
Для переноса phpbb-форума используется модуль phpbb2Drupal. О нём не раз писалось, потому лишь скажу про "подводные камни".
Всё "за раз"
Нужно добиться того, чтобы сделать всё "за один раз". Т.е. импортировать юзеров-форумы-топики-посты - без "перескакиваний", иначе возможны различные глюки - обычно это то, что импортированные посты не появятся в форумах, в то время, как в самой БД будут присутствовать (но они "не привязываются" к форумам).
Только зелёное
Придётся отказаться от различных "продвинутостей" (в частности, почему и пишется эта статья), в виде использования модулей, расширяющих возможности друпала, как здесь принято говорить, "красными" методами.
Это и весьма интересный модуль (точней целый набор модулей) category, который представляет собой "разогнанный" модуль таксономии, встроенный в друпал. Если Вы уже успели им побаловаться - учтите, что он заменяет стандартные модули book и taxonomy, в результате чего, после его деинсталяции нужно обязательно проверить, что в системе используются "родные" модули, иначе работа всего связанного с подшивкой и форумом превращается в один сплошной глюк. Именно из-за этого - использования нестандартных модулей вместо родных - импортировать (корректно) данные из phpbb не получится. Один из "подмодулей" Legacy ситуацию не спасает - попытка поставить category после импорта данных также обречена на провал. Итого, модуль category вычёркиваем, не пускайте слюни, нам он больше не пригодится, а если ещё только собирались его попробовать (и при этом, повторюсь, процедура переноса phpbb2-drupal есть обязательна) - не тратьте зря время.
Другой весьма интересный модуль, который заменяет стандартный форум - UIE Forum. В нём, в принципе, есть "всё что нужно" - и скрытые форумы и возможности по назначению модераторов в каждый из подфорумов и т.п. Однако в нём нет одного - автор оного наотрез отказался от того, чтобы добавить возможность импорт в него данных, при чём не только из phpbb, но и из "обычного", встроенного в друпал. Итого, несмотря на "крутость", это есть "вещь в себе", которая подходит лишь для тех, кто работает "с чистого листа" и в будущем не планирует обновляться. Вычёркиваем.
Возможно, есть и другие, не опробованные мною модули, однако осмелюсь высказать предположение, что из-за вынужденного использования модуля phpbb2Drupal вряд ли что-то ещё подойдёт.
Импорт форума
Перед настройкой модуля phpbb2Drupal нужно поставить модуль BBcode, иначе будучи установленным после возможны глюки - bb-тэги будут корректно обрабатываться лишь у вновь созданных сообщений, в то время, как импортированные обрабатываться не будут (лишь после "пересохранения").
У кого на форуме использовался тэг offtop - можно добавить его самостоятельно. Ищем в файле "bbcode-filter.inc" строчку
<?php
// Font, text and alignment
?>и после неё добавляем
<?php
'#\[(off|offtop)(?::\w+)?\](.*?)\[/(off|offtop)(?::\w+)?\]#si' => '<span style="font-style:italic; font-size:9px; color:#777777">\\2</span>',
?>(размер-цвет можно поменять на другой).
Касаемо выбора ставить ли галочку "Преобразовывать BBcode в HTML" - решать вам. Но нужно учесть, что в случае большой БД преобразования увеличит время обработки. Потому, в частности, рекомендуется ставить pathauto после импорта форума. Я их (BBcode) оставлял "as is".
По умолчанию модуль копирует в заглавие каждого комментария название темы - смотрится достаточно печально. Для исправления этого недостатка ищем в файле "phpbb2drupal.module" обработку заголовка комментария
<?php
// if the title field is empty, use the node title as default.
?>и заменяем на принудительную "пустоту":
<?php
$comment['subject'] = <u>''</u>; // "пусто" вместо $node->title;
?>То с чем придётся смириться - все топики форума, в которых не было ответов "всплывут" наверх, превратив таким образом форум в не самое приятное зрелище. Это происходит от того, что в phpbb при создании темы один и тот же комментарий автора дублируется - он записывается и в таблицу posts и в posts_text. В результате при импорте приходится пропускать первый комментарий таблицы posts_text , таким образом дата последнего ответа теряется и тема с пометкой "нет ответов" выползает наверх.
Теоретически, это можно побороть, более существенно изменив алгоритм работы модуля, но для этого у меня не хватило опыта и знаний и пришлось мириться с появившейся "тиной" из старых тем во всех ветках. Хотя, при активном участии пользователей подобная тина быстро разгоняется. :)
Скрытые форумы, модераторство подфорумов сотоварищи
Реализовать подобные вещи окромя уже перечисленных и вычеркнутых нами модулей позволяют:
У каждого из них есть свои преимущества. Taxonomy Access Control (полная версия) позволяет чётко управлять доступом к терминам категорий в зависимости от роли, что равнозначно "полной версии" управления доступа к форумам в админке phpbb. Taxonomy Access Control Lite есть упрощённа версия и позволяет аналогичное с поправкой на более простые права доступа - равнозначно "Простому режиму" управления доступом в админке phpbb. Forum Access есть некий баланс между "монстровидностью" полного "таксесса" и упрощённого "таклайта", мне он (Forum Access) понравился больше всего.
Однако во всех этих "эмуляциях" возможностей phpbb (имеется в виду - различный доступ к подфорумам, зависимый от роли) есть два недостатка. Первый - модули, средствами которых делаются такие функции - "незелёные". Конечно, кому-то это "не довод", но учесть надо. :) Второй недостаток в моём случае оказался решающим - в случае большого размера форума (с большим количеством пользователей и подразделов) из-за, как я предполагаю, неоптимальной работы данных модулей с БД, где они запрашивают права юзера на просмотр каждой из ссылок - скорость форума резко падает (в разы). И это никак (существенно) исправить не удаётся. Потому, если для вас наличие скрытых форумов принципиально - позаботьтесь о ресурсах производительности в случае объёмного форума. Иначе же (как поступил я) - проще отказаться от таких форумов (у меня они уехали на зеркальные серверы, оставшись на старом движке phpbb).
Если же, всё-таки, вы решитесь использовать подобные модули (для скрытия подфорумов и т.п.), учтите одну важную особенность, чтобы не повторять детские ошибки (как по началу делал это я :) ) - при установке каждого из модулей (после применения установленных галочек в admin/build/modules) обязательно дождитесь окончания отработки процесса. Иначе, прервав его, вы увидете, что галочка применена, однако из-за обрыва процесса создания нужных таблиц - получите непредсказуемое поведение модуля в будущем. Тоже самое (дождаться) нужно при деинсталяции таких модулей.
Правим форум
Отойдя после перого "психологического шока", закоренелые phpbb-сты выдвигают примерно следующий список недостатков.
- Формат даты/времени - "43 недели 6 часа назад" некоторых приводит в тихое бешенство. В случае просмотра последних сообщений (tracker) - можно настроить с помощью переопределения посредством модуля views
- Древовидный формат постов - можно (нужно?) отключить в управлении комментариями ("admin/content/comment/settings -> Режим показа по умолчанию -> Плоский список - развёрнутый", а также "Управление комментариями -> Не показывать"). Кроме того, чтобы полностью исключить древовидность потребуется убить кнопку "Комментировать" у каждого из постов (иначе сделанный комментарий выстроится в "ветку дерева"). Это можно сделать изменив во "встроенном" (в друпал) модуле комментариев (файл "comment.module") функцию comment_links, у которой нужно затереть (закомментировать)
<?php
$links['comment_reply'] = array(
'title' => t('reply'),
'href' => "comment/reply/$comment->nid/$comment->cid"
);
?>(две штуки).
- Отсутствие аватар - включается в каждой из тем ("admin/build/themes/settings/нужная_тема -> Включить/выключить отображение -> Пользовательские изображения в сообщениях / Пользовательские изображения в комментариях") после разрешения "Изображения -> Поддержка изображений" в admin/user/settings
- Возможность "Быстрого ответа" - решается (в каком-то смысле) расположением ответа не на отдельной странице, а внизу топика ("admin/content/comment/settings -> Настройки отправки -> Расположение формы отправки комментария -> Показывать ниже сообщения или комментариев")
- Отсутствие цитирования
- Нет возможности "Отметить все темы прочитанными" - беда, пока не решил.
- "Пропавшие" недавно созданные темы. Реально они есть - просто "глубоко", на энной странице каждого из подфорумов, в зависимости от количества имеющихся раньше тем без ответов (подумайте, может, их, вообще - стоит убить перед импортом?)
- Непривычно большой отступ после Enter - объяснить про Shift+Enter
- При получении нового ЛС не всплывает отдельное окно
- Нет поиска (в расширенном) по автору
- При выборе "многостраничного" топика переход происходит на первую страницу. Туда же выбрасывает при добавлении комментария в таких темах. Самая больная тема, увеличение количества комментариев на странице - не выход. Решено - ниже.
- Нет поиска (в расширенном) по автору
- Переход к следующей странице комментариев лишь внизу страницы. Решено - ниже.
- После удаления комментария выкидывает на главную страницу. Решено - ниже.
- При добавлении комментария в "многостраничную" тему - выкидывает на её первую страницу. Решено - ниже.
- На многостраничных топиках неудобная навигация - переход к нужной странице ("pager") лишь снизу. Для исправления в модуле комментариев "comment.module" ищем
- Непривычно (неудобно?) - новую тему можно начать прямо с главной страницы форума (и/или контейнеров), но нельзя из "подфорумов". Чтобы убрать кнопку нового обсуждения с главной страницы форума и контенеров в модуле "forum.module" ищем функцию theme_forum_display и вырезаем из неё
<?php
$output = '<ul>';
if (user_access('create forum topics')) {
$output .= '<li>'. l(t('Post new forum topic.'), "node/add/forum/$tid") .'</li>';
}
else if ($user->uid) {
$output .= '<li>'. t('You are not allowed to post a new forum topic.') .'</li>';
}
else {
$output .= '<li>'. t('<a href="@login">Login</a> to post a new forum topic.', array('@login' => url('user/login', drupal_get_destination()))) .'</li>';
}
$output .= '</ul>';
?>
. Использовать модуль Quote, который частично решает данную проблему, позволяя цитировать весь комментарий не рекомендуется в случае, если вы отказались от использования древовидного вида, т.к. данный модуль автоматически "прикрепляет" сделанный с помощью его цитирования ответ к тому, где была нажата кнопка "Quote" и после, при модерировании, удалив этот комментарий - удалится и вся цепочка ответов на него.
<?php
// Start a form, for use with comment control.
$result = pager_query($query, $comments_per_page, 0, $query_count, $query_args);
?>и добавляем после
<?php
$output .= theme('pager', NULL, $comments_per_page, 0);
?>А для того, чтобы сделать кнопку в подфорумах ищем функцию theme_forum_topic_list и в самое начало (после global $user;) вставляем вырезанный текст.
Если после этого сверху "полирнуть" установкой модуля Formfilter, с помощью которого можно запретить отображение выбора форума, в который нужно посылать сообщение. Правда, чтобы оно было видно для модераторов, придётся в нём (модуле Formfilter) в самое начало функции _formfilter_filter_element добавить
<?php
global $user;
if (is_array($user->roles) && array_key_exists(3, $user->roles)) {
return;
}
?>(где 3 = rid модератора)
- Некоторые советы по ходу, чтобы самому не забыть:
- Даже если совсем не нравятся имеющиеся в стандартной поставке темы - можете удалять все, но оставьте Garland/Minelli - иначе в различных "критических" ситуациях придётся лицезрить "текстовый" режим, а не привычный интерфейс.
- Если предполагается много тем и блоков - лучше сначала всё сделать для одной (той же "Garland") темы (удалив оставшиеся) и после установить нужные темы - правила расположения блоков "применятся" ко всем свежеустановленным темам. Иначе, начав "расставление" блоков для каждой из тем отдельно - расположение их (блоков) для всех имеющихся на данный момент в друпале тем запомнится и останется таковым даже после удаление и установки заново таковых тем. Т.е. последовательность такая - убиваем все темы, кроме Garland, настраиваем на ней все блоки и лишь после этого ставим нужные темы.
- При настройке тем (особенно блоков для них) не забудьте про настройку "Оформление админки", чтобы не пугаться "внезапному" смену темы при сохранении настроек.
- При подборе тем не забывайте проверять вид сайта:
- В разных броузерах, как минимум в IE / Opera, ибо отличия иногда принципиальны.
- В разных разрешениях, как минимум в 1024х768 (не расситывайте, что у всех 20" монитор ;) )
- В разных "местах" сайта - вид форума, топиков, отдельных страниц и т.п. Часто в целом понравившаяся тема даёт какой-то "принципиальный" глюк в "принципиальном" месте сделанного сайта.
- При "подкручивании" какой-то темы путём изменения её style.css - не забывайте выключить "Объединение и сжатие файлов CSS" в admin/settings/performance, иначе внесённые изменения могут "удивительным образом" игнорироваться, а наутро проснувшись узрите свой сайт в крамольном виде - последстсвия попыток "хоть что-то изменить в проклятом CSS". ;)
- При изменении параметров в "Управление сайтом » Настройка » Производительность" (admin/settings/performance) принципиально контролировать изменения именно на незалогененном пользователе, ведь основная оптимизация рассчитана именно для них, а потому и основные глюки у них же. :) Кроме того, важно проверять действия оптимизации на разных по "весу" страницах (мало текста, средне, много), в разных броузерах, а ещё лучше и просить "сторонних" людей проконтролировать корректность отображения. Иначе, обрадовавшись, что "всё залетало" можете с прискорбием обнаружить, что "никто не приходит" из-за того, что незалогенным пользователям не удаётся что-то увидеть на сайте, чтобы, собственно, зайти в систему. Или же они зайдут, но будет "почему-то" недоступен форум - маленькие страницы отдаются нормально, а наполнененые ветками форума - нет. Во всех таких случаях - "понижаем" (отключаем) кэширование, манипуляции с "Минимальное время жизни кеша" - не помогут. При этом, даже в случае проблем и отключения кэширования, возможность включить (и получить от это пользу) "Объединение и сжатие файлов CSS" - остаётся.
- Даже отключив кэширование (как наивно кажется) - нельзя забывать, что друпал, всё равно, пользуется оным для различных критичных по производительности функций, а потому таблицы типа cache_filter сотоварищи могут со временем существенно увеличить объём БД.
- Таблицы, связанные с кэшем можно чистить "вручную", однако после такой операции работа сайта становится непредсказуемой, (например, для залогиненных пользователей будет нормально, в то время, как незалогиненные увидят лишь половину материала), потому после этого обязательно нужно переиндексировать в "Управление сайтом » Content management » Публикация" (в admin/content/node-settings - только не путать с переиндексацией сайта в admin/settings/search!).
- Для того, чтобы заработал поиск на сайте - нужно сперва проиндексировать контент. В друпале это нельзя сделать "за раз", этот процесс привязан к "cron.php". Потому для ускорения процедуры можно поработать ручками - запуская файл cron.php в строке броузера (предварительно поставив обрабоку максимума записей за один раз). Только не слишком часто, иначе не доделав предыдущее он начнёт переиндексироавать этот "кусочек" заново.
in progress...
- apple_rom's blog
- Для комментирования войдите или зарегистрируйтесь
Может труд разбить на части?
- Для комментирования войдите или зарегистрируйтесь
Спасибо, очень актуально! Как раз занимаюсь вопросом переноса форума из phpbb на drupal. Пока имеет место проблема некорректной перекодировки данных. Ежели решится - пойду дальше.
Автор абсолютно прав насчет того, что для начала следует натренироваться на пустом друпале. Процесс весьма нетривиален...
- Для комментирования войдите или зарегистрируйтесь
очень интересно
- Для комментирования войдите или зарегистрируйтесь
- Для комментирования войдите или зарегистрируйтесь
Мне удалось победить самую противную проблему - когда при переходе на тему, где много страниц - всегда попадаешь на первую из них
Может быть все же - "код в студию!"?
поддержку кириллических ссылок
И это тоже можно :) Я так понимаю - отредактированный файлик соответствий?
- Для комментирования войдите или зарегистрируйтесь
Ещё один "глюк" друпаловского форума - я обновил свой комментарий и он по очерёдности перескочил за сделанное после него сообщение от "On вт, 28/08/2007 - 04:40 vadbars@drupal.org says:"). Видимо, надо будет убрать обновление даты при апдэйте статистики, если уже были комментарии после первой версии комментария.
- Для комментирования войдите или зарегистрируйтесь
пугает только количество запросов из-за Pathauto
- Для комментирования войдите или зарегистрируйтесь
Удалось достаточно просто решить путём использования "кэшируемой" функции comment_num_all. Добавляем в модуль комментариев (comment.module) функцию вычисления последней страцицы:
<?php
function _pages_count($nid)
{
$pages = 0;
$count = comment_num_all( $nid );
$per_page = _comment_get_display_setting( 'comments_per_page' );
if( $count > $per_page )
{
while( $count > $per_page )
{
$pages++;
$count -= $per_page;
}
return 'page='.$pages;
}
else
{
return NULL;
}
}
?>- После чего изменяем все участки, где проявляется ошибка при работе с многостраничными топиками.
- Чиним функцию, которая выбрасывала на первую страницу при редактировании комментария
- В блоке Последних комментарии тоже будет ошибка для таких топиков - исправляем.
- Кроме комментариев делаем аналогичное в forum.module с функцией отображения списка топиков
- Если используется "родной" (не переопределённый) трэкер ("Последние сообщения") - исправляем и его.
<?php
function comment_form_submit($form_id, $form_values) {
$form_values = _comment_form_submit($form_values);
if ($cid = comment_save($form_values)) {
return array('node/'. $form_values['nid'], _pages_count($form_values['nid']), "comment-$cid"); // замеменено NULL
}
}
?><?php
function theme_comment_block() {
$items = array();
foreach (comment_get_recent() as $comment) {
// Заменяем второй NULL ранее написанной функцией
$items[] = l(substr($comment->comment, 0, strrpos((substr($comment->comment, 0, 160)), " ")) . ' ...', 'node/'. $comment->nid, NULL, _pages_count($comment->nid), 'comment-'. $comment->cid) .'<br />'. t('@time ago', array('@time' => format_interval(time() - $comment->timestamp)));
// "Родная" $items[] видоизменён - по способу http://drupal.ru/node/7262
}
if ($items) {
return theme('item_list', $items);
}
}
?><?php
function theme_forum_topic_list($tid, $topics, $sortby, $forum_per_page) {
global $user;
// set "New topic"-link on sub-forum page (move from main and subcontainers) *romby*
$output = '<ul>';
if (user_access('create forum topics')) {
$output .= '<li>'. l(t('Post new forum topic.'), "node/add/forum/$tid") .'</li>';
}
else if ($user->uid) {
$output .= '<li>'. t('You are not allowed to post a new forum topic.') .'</li>';
}
else {
$output .= '<li>'. t('<a href="@login">Login</a> to post a new forum topic.', array('@login' => url('user/login', drupal_get_destination()))) .'</li>';
}
$output .= '</ul>';
// end changes
$output .= theme('pager', NULL, $forum_per_page, 0);
global $forum_topic_list_header;
$rows = array();
if ($topics) {
foreach ($topics as $topic) {
// folder is new if topic is new or there are new comments since last visit
// *romby* - add '$topic->tid != 0' for deleted topic with checked "move-flag"
if ( ( $topic->tid != 0 ) && ( $topic->tid != $tid ) )
// end of changes
{
$rows[] = array(
array('data' => theme('forum_icon', $topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky), 'class' => 'icon'),
array('data' => check_plain($topic->title), 'class' => 'title'),
array('data' => l(t('This topic has been moved'), "forum/$topic->tid"), 'colspan' => '3')
);
}
else {
// *romby* - add _pages_count function
$pages = _pages_count($topic->nid);
$rows[] = array(
array('data' => theme('forum_icon', $topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky), 'class' => 'icon'),
array('data' => l($topic->title, "node/$topic->nid", NULL, $pages), 'class' => 'topic'), // <- $pages here
array('data' => $topic->num_comments . ($topic->new_replies ? '<br />'. l(format_plural($topic->new_replies, '1 new', '@count new'), "node/$topic->nid", NULL, $pages, 'new') : ''), 'class' => 'replies'), // <- $pages here
array('data' => _forum_format($topic), 'class' => 'created'),
array('data' => _forum_format(isset($topic->last_reply) ? $topic->last_reply : NULL), 'class' => 'last-reply')
);
// end of changes
}
}
}
// change '=' to '.=' for output previos "New topic"-link *romby*
$output .= theme('table', $forum_topic_list_header, $rows);
// end changes
$output .= theme('pager', NULL, $forum_per_page, 0);
// set once "New topic"-link on sub-forum page *romby*
$output .= '<ul>';
if (user_access('create forum topics')) {
$output .= '<li>'. l(t('Post new forum topic.'), "node/add/forum/$tid") .'</li>';
}
else if ($user->uid) {
$output .= '<li>'. t('You are not allowed to post a new forum topic.') .'</li>';
}
else {
$output .= '<li>'. t('<a href="@login">Login</a> to post a new forum topic.', array('@login' => url('user/login', drupal_get_destination()))) .'</li>';
}
$output .= '</ul>';
// end changes
return $output;
}
?><?php while ($node = db_fetch_object($result)) {
// Determine the number of comments:
$comments = 0;
if ($node->comment_count) {
$comments = $node->comment_count;
if ($new = comment_num_new($node->nid)) {
$comments .= '<br />';
// *romby* remove NULL with _pages_count
$comments .= l(format_plural($new, '1 new', '@count new'), "node/$node->nid", NULL, _pages_count($node->nid), 'new');
// end of changes
}
}
$rows[] = array(
check_plain(node_get_types('name', $node->type)),
// *romby* remove NULL with _pages_count
l($node->title, "node/$node->nid", NULL, _pages_count($node->nid)) .' '. theme('mark', node_mark($node->nid, $node->changed)),
// end of changes
theme('username', $node),
array('class' => 'replies', 'data' => $comments),
t('!time ago', array('!time' => format_interval(time() - $node->last_updated)))
);
}
?>- Для комментирования войдите или зарегистрируйтесь
Для "русифицирования" ссылок в Pathauto заменяем главное условие, по которому фильтруются все "небуквы"-"нецифры", под которое в том числе попадает и кириллица.
<?php
// Preserve alphanumerics, everything else becomes a separator
$pattern = '/[^a-zA-Z0-9]+/ ';
$output = preg_replace($pattern, $separator, $output);
?>Вместо этого ставим более "мягкое" выражение:
<?php
$output = preg_replace("/[_'`!@#$%^&*()|\s\.,?\[\]{}><:;\/\"]+/", "_", $output);
?>А чтобы при таком условии не получалось "двойных" подчёркиваний на знаках препинания (и пр.) - подрезаем их аналогично вырезанию апострофов:
<?php
// Replace or drop apostrophes based on user settings
$separator = variable_get('pathauto_separator', '-');
$quotes = variable_get('pathauto_quotes', 0);
$output = str_replace("'", ($quotes ? $separator : ''), $string);
// Добавляем ещё и ...
$vowels = array("(", ")", "[", "]", "{", "}", "*", "%", "#", "@", "`", "~", );
$output = str_replace('"', ($quotes ? $separator : ''), $output);
?>Чтобы полностью навести красоту - запрещаем перевод больших букв в маленькие:
<?php
//$alias = drupal_strtolower($alias);
?>Конечно, кроме всего прочего нужно подставить файлик (прилагается) "преобразований", где для кириллицы этих преобразований и нет.
- Для комментирования войдите или зарегистрируйтесь
Отключив ранее кнопки комментариев к отдельным постам мы сейчас не можем изменить "быстроответный" вид расположения формы ввода ответа (внизу топика), т.к. кнопка посылки комментраия на тему в этом случае будет отсутствовать. Исправляем эту проблему:
<?php
// If enabled, show new comment form.
if (user_access('post comments') && node_comment_mode($nid) == COMMENT_NODE_READ_WRITE && (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_BELOW)) {
$output .= comment_form_box(array('nid' => $nid), t('Post new comment'));
}
?>Заменяем на:
<?php
// If enabled, show new comment form.
if( user_access( 'post comments' ) && node_comment_mode( $nid ) == COMMENT_NODE_READ_WRITE )
{
$output .= '<ul><li>';
$output .= l( t( 'Post new comment' ), 'comment/reply/'.$nid, NULL, NULL, 'comment-form' );
$output .= '</li><ul>';
}
?>В результате внизу топика появится кнопка
- Для комментирования войдите или зарегистрируйтесь
Спасибо! Будем посмотреть.
На drupal.org не хотите отписаться? Если проблема с некорректной ссылкой на последний комментарий действительно решена, то это порадует очень многих. Эта багофича тянется с самых ранних версий.
- Для комментирования войдите или зарегистрируйтесь
На drupal.org не хотите отписаться?
Таки это тоже не слишком "культурное" решение - изначально было желание исправить это на уровне ядра, чтобы не патчить все модули подряд. Просто пока торопят возмущённые пользователи форума (привыкшие к функционалу phpbb), потому решил сделать сначала хоть какое-то приличное и работающее решение. Позже попробую сделать "правильно" и уже по (любому) результату отпишусь.
Ещё один момент - при варианте с формой отправки комментария на отдельной странице (в целом для друпала и к которой мы пришли по этой пишущейся "методичке" в частности) - можно видеть лишь "заглавное" сообщение (пост нода). Такая принудительная тренировка памяти очень быстро начинает раздражать, особенно счастливых обладателей IE, где возврат на предыдущую страницу - для просмотра последних комментраев (а не только нода) весьма не быстр. Потому исправим это, отобразив кроме поста нода ещё и $comments_per_page последних комментариев на странице с формой отпавки сообщения. Для этого придётся вставить достаточно крупный кусок, хотя вообще он достаточно прост, ибо банально выдран из функции comment_render . Итак, ищем в уже не раз упомянутой функции comment_reply место сразу после вывод содержимого поста нода:
<?php
// This is the case where the comment is in response to a node. Display the node.
else if (user_access('access content')) {
$output .= node_view($node);
?>и после него вставляем:
<?php
// ----------------------------------------------------
$output .= '<BR>...<BR><BR>';
$mode = _comment_get_display_setting('mode');
$order = _comment_get_display_setting('sort');
$comments_per_page = _comment_get_display_setting('comments_per_page');
// Multiple comment view
$query_count = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d';
$query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, u.data, c.score, c.users, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d';
$query_args = array($nid);
if (!user_access('administer comments')) {
$query .= ' AND c.status = %d';
$query_count .= ' AND status = %d';
$query_args[] = COMMENT_PUBLISHED;
}
if ($order == COMMENT_ORDER_NEWEST_FIRST) {
if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
$query .= ' ORDER BY c.timestamp DESC';
}
else {
$query .= ' ORDER BY c.thread DESC';
}
}
else if ($order == COMMENT_ORDER_OLDEST_FIRST) {
if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
$query .= ' ORDER BY c.timestamp';
}
else {
/*
** See comment above. Analysis learns that this doesn't cost
** too much. It scales much much better than having the whole
** comment structure.
*/
$query .= ' ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))';
}
}
// Start a form, for use with comment control.
//$result = pager_query($query, $comments_per_page, 0, $query_count, $query_args);
// db_query_range($query, $args, $pager_page_array[$element] * $limit, $limit)
$com_num_all = comment_num_all($nid);
if( $com_num_all < $comments_per_page )
{
$com_num_all = $comments_per_page;
}
$result = db_query_range( $query, $query_args, $com_num_all - $comments_per_page, $comments_per_page );
//$output .= theme('pager', NULL, $comments_per_page, 0);
$divs = 0;
$last_depth = 0;
drupal_add_css(drupal_get_path('module', 'comment') .'/comment.css');
while ($comment = db_fetch_object($result)) {
$comment = drupal_unpack($comment);
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
$comment->depth = count(explode('.', $comment->thread)) - 1;
if ($mode == COMMENT_MODE_THREADED_COLLAPSED || $mode == COMMENT_MODE_THREADED_EXPANDED) {
if ($comment->depth > $last_depth) {
$divs++;
$output .= '<div class="indented">';
$last_depth++;
}
else {
while ($comment->depth < $last_depth) {
$divs--;
$output .= '</div>';
$last_depth--;
}
}
}
if ($mode == COMMENT_MODE_FLAT_COLLAPSED) {
$output .= theme('comment_flat_collapsed', $comment);
}
else if ($mode == COMMENT_MODE_FLAT_EXPANDED) {
$output .= theme('comment_flat_expanded', $comment);
}
else if ($mode == COMMENT_MODE_THREADED_COLLAPSED) {
$output .= theme('comment_thread_collapsed', $comment);
}
else if ($mode == COMMENT_MODE_THREADED_EXPANDED) {
$output .= theme('comment_thread_expanded', $comment);
}
}
for ($i = 0; $i < $divs; $i++) {
$output .= '</div>';
}
// $output .= theme('pager', NULL, $comments_per_page, 0);
$output = theme('comment_wrapper', $output);
// ===============================================
?>Если захочется выводить лишь "постоянные" Х последних комментариев - заменяем на него $comments_per_page.
- Для комментирования войдите или зарегистрируйтесь
Тут найдено решение гадской проблемы Пометить все как прочитанные. Позже нужно будет "встроить" в форум, ибо патчить каждую тему сайта для вывода кнопки ни разу не кошерно.
- Для комментирования войдите или зарегистрируйтесь
Кстати, замечено некоторое дополнительное притормаживание форума, вероятно вызванное решением с переходами на многостраничные темы.
... 0.19 1 drupal_lookup_path SELECT dst FROM url_alias WHERE src = 'user/2410' 0.2 1 drupal_lookup_path SELECT dst FROM url_alias WHERE src = 'user/2783' 0.14 1 comment_num_all SELECT comment_count FROM node_comment_statistics WHERE nid = 14077 0.17 1 drupal_lookup_path SELECT dst FROM url_alias WHERE src = 'node/14077' 0.19 1 drupal_lookup_path SELECT dst FROM url_alias WHERE src = 'user/378' 0.14 1 comment_num_all SELECT comment_count FROM node_comment_statistics WHERE nid = 13962 0.17 1 drupal_lookup_path SELECT dst FROM url_alias WHERE src = 'node/13962' 0.2 1 drupal_lookup_path SELECT dst FROM url_alias WHERE src = 'user/1934' 0.16 1 comment_num_all SELECT comment_count FROM node_comment_statistics WHERE nid = 14038 0.17 1 drupal_lookup_path SELECT dst FROM url_alias WHERE src = 'node/14038' ...
Хотя, возможно, если будет включено кэширование (в моём случае, к сожалению, включение даже на нормале даёт глюки), то никаких дополнительных задержек и не последует...
- Для комментирования войдите или зарегистрируйтесь
Один из вариантов решения проблемы перехода на многостраничные темы форумов "на уровне ядра" - видится исправления функции отдачи адреса url. В её фрагменте:
<?php
// The special path '<front>' links to the default front page.
if (!empty($path) && $path != '<front>') {
$path = drupal_get_path_alias($path);
$path = drupal_urlencode($path);
if (!$clean_url) {
if (isset($query)) {
return $base . $script .'?q='. $path .'&'. $query . $fragment;
}
else {
// тут для "грязных"...
return $base . $script .'?q='. $path . $fragment;
}
}
else {
if (isset($query)) {
return $base . $path .'?'. $query . $fragment;
}
else {
// тут для "чистых" ссылок - добавляем проверку и вычисление страницы...
return $base . $path . $fragment;
}
}
}
?>... в случае $query == NULL (иначе - это запрос от пэйджера или др. функции, что уже "посчитала" страницу) делаем проверку полученного алиаса, чтобы он начинался с "/forum/" (или другое - позже можно добавить в настраиваемое значение) - значит это форумная ссылка (иначе будем зря дёргать запросами БД по каждой ссылке). И ежели так - получаем nid и определяем кол-во комментариев с последующим установлением нужного значения в $query. Вот только вопрос - не слишком ли "коряво" выдирать номер нода из строки $path?
- Для комментирования войдите или зарегистрируйтесь
Чтобы не забыть, продолжаю отчитываться сам себе же.
Модуль FormFilter при всей очевидной полезности заставил помучаться в тонком моменте - если с помощью него скрыть отображение выбора категорий форума, то в поле forum->tid для создаваемой темы будет занесён 0. В результате получается совсем неочевидный глюк - с одной стороны, создаваемая тема получит в node принадлежность к форуму, но в нём появится как перенесённая неизвестно куда (tid = 0). Я по глупости сначала добавил условие, чтобы форумы с tid = 0 не считались перенесёнными, в результате всё как бы работали, но - новые сообщения считались неверно и при удалении такой темы не получилось бы отметить её как перенесённую. В общем, короче - будьте осторожны и не злоупотребляйте модулем FormFilter, иначе придётся как мне :) (обновлять все созданные темы с tid=0 при включенном поле выбора подфорума - после обновления tid получили требуемое значение и всё образовалось).
По-прежнему не удаётся включить кэширование форума из-за вылезающией ошибки
Warning: gzinflate() [function.gzinflate]: data error in /home/rombyportal/public_html/includes/bootstrap.inc on line 575
Ошибка вылазит у некоторых незалогиненных пользователей, использующих IE. Все найденные подобные ошибки на drupal.org остались без чёткого решения, к сожалению. Максимально конкретный вариант решения был здесь, но и он не помог. :/
В общем, в результате пришлось хорошенько подумать над оптимизацией. После исследования загрузки страниц с помощью модуля Devel были убиты модули, которые не представляли "принципиальной" ценности, но при этом напрягали БД многочисленными запросами, отражающие явно плохо написанный код. Если кто зачем-то поставит себе модуль User Activity - гляньте подробности его работы, они могут очень не понравится. :)
Кроме удаления ещё других "непринципиальных" и нагружающих "лишними" запросами модулей, стоит задуматься над оптимизацией кэша.
При использовании модуля Pathauto на каждую ссылку ищется алиас. В результате получаем, пусть мелкие, но самые многочисленные запросы. При чём важно, что они делаются "без разбора" - в том числе на те ссылки, которые не имеют синонимов. А ведь наиболее частые ссылки у каждого из комментариев - ответить, удалить, редактировать, отправить сообщение и тп. - обычно не использую синонимы. Зачем же зря напрягать и делать запросы для таких путей? В общем, в таком случае есть смысл подредактировать функцию url, заменив вызов $path = drupal_get_path_alias( $path ); на:
<?php
if (!empty($path) && $path != '<front>')
{
if( ! ( substr( $path, 0, 7 ) == 'comment'
|| substr( $path, 0, 8 ) == 'node/add'
|| substr( $path, 0, 5 ) == 'admin'
|| substr( $path, 0, 6 ) == 'logout'
|| substr( $path, 0, 6 ) == 'search'
|| substr( $path, 0, 10 ) == 'userpoints'
|| substr( $path, 0, 15 ) == 'user2userpoints'
|| substr( $path, 0, 10 ) == 'privatemsg' ) )
{
if( substr( $path, 0, 6 ) == 'NoPath' ) // для "ручного" отключения вычисления синонима
{
$path = substr( $path, 6, strlen( $path ) );
}
else
{
$path = drupal_get_path_alias( $path );
}
}
?>Сделано не слишком оптимально, однако результат на лицо - количество обращений drupal_lookup_path уменьшилось в три-четрыре раза.
Кроме того, всякие выборки, что были дописаны в ходе улучшения юзабельности (например, банальное количество сообщений пользователя в его comment.tpl.php) - правильней сделать "кэшируемыми", например, так:
function user_comments_count( $uid )
<?php
{
static $cache;
if (!isset($cache[$uid]))
{
$cache[$uid] = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE uid = %d', $uid)); // AND status = %d , COMMENT_PUBLISHED
}
return $cache[$uid];
}
?>После всех таких действий, даже без установки альтернативных алгоритмов кэширования количество запросов к БД уменьшилось местами почти на половину, что на глаз ускорило работу (примерно в полтора раза).
Кстати, как помните, мы реализовали "русские" ссылки, однако полностью их "русскими" назвать не получалось из-за того, что автопреобразование из "процентиков" в кириллицу умеет лишь Опера и FF с дополнительным плагином. Так вот, если в вышеупомянутой функции url закомментировать строчку $path = drupal_urlencode($path);, то получим "честные" русские ссылки уже в любом броузеры. Местами такой не совсем "честный" подход даёт глюки (обычно при частом нажатии кнопки назад в IE русские буквы заменяются на коряболки), однако, во-первых, при этом чаще нормально срабатывает, во-вторых, это правильней отнести к "нестандартным" ситуациям - во всём остальном получается красота.
Хотя нет, не во всём. :) Модуль "альтернативного" кэширования Boost использующий сохранение сгенерированных страниц на диске - сохраняет русские названия некорректно, потому от него пришлось отказаться.
- Для комментирования войдите или зарегистрируйтесь
Очень интересные исследования и работа над Друпалом...
Мои поздравления, очень нужная тема... насчёт кэша, могу посоветовать вновь оживший fastpath_fscache... он, по моему, работает получше, чем Буст, во всяком случае проблем с зарегистрированными пользователями и анонимными - не имеет...
- Для комментирования войдите или зарегистрируйтесь
Кстати, упомянутая проблема с тем, что перейдя на строго плоский развёрнутый вид форума, получается весьма гадская неприятность, когда при правке какого-то поста он "улетает" в самый конец, меняя видимую хронологию (последовательность) сообщений - из-за того, что ему ставится более свежая дата, а отображение комментариев в comment_render как раз сортируется по timestamp - решается убийством обновления даты при редатировании поста в comment_save:
<?php
db_query("UPDATE {comments} SET status = %d, subject = '%s', comment = '%s', format = %d, uid = %d, name = '%s', mail = '%s', homepage = '%s' WHERE cid = %d", $edit['status'], $edit['subject'], $edit['comment'], $edit['format'], $edit['uid'], $edit['name'], $edit['mail'], $edit['homepage'], $edit['cid']);
?>Как вариант, чтобы таки был виден факт редактирования поста после его размещения можно добавить перед вышеописанной записью нечто типа:
<?php
$edit['comment'] .= '<BR><div class="comment_was_changed">'.t('Comment was changed by ').theme('username', $user).' at '.format_date( time(), 'small' ).'</div><BR>';
?>Такая версия не слишком удобна из-за того, что она добавляется в том числе и в самый последний пост (который обычно очень часто редактируется автором при размещении), потому нужно бы добавить условие. Однако как просто решить проблему определения "последнего поста" пока не знаю - как узнаю отпишусь. :)
п.с. кстати, на мой взгляд, это (обновление даты редактируемого поста) - есть именно баг, ибо сложно увидеть, где по "философии" всей структуры друпала оправдана данная операция, изменяющая цепочку сообщений.
- Для комментирования войдите или зарегистрируйтесь
Если проблема с некорректной ссылкой на последний комментарий действительно решена, то это порадует очень многих. Эта багофича тянется с самых ранних версий.
Вадим, на ДО уже давно видел патч для этого, правда ссылку не дам - не добавил в закладки(((
- Для комментирования войдите или зарегистрируйтесь
Первая часть сообщения - хорошая, вторая - не очень. :) "Что ж, будем искать с перламутровыми пуговицами" (с) Бриллиантовая рука.
- Для комментирования войдите или зарегистрируйтесь
Может и не в тему чуть, но я увидел, что об uie не очень хорошего мнения, лично я считаю его единственным форумом, для которого не надо дополнительные модули для реализации моста между друпой и движком форума. Он взят за основу и будет развиваться, проблемы в нем конечно есть и функционала маловато, но мне например нравится вобла и функции воблы будут потиху переносится в этот форум. Все остальные форумы это костыли увы, сделаны не как дополнение к движку а как отдельный нормально функционирующий сайт-форум.
- Для комментирования войдите или зарегистрируйтесь
Есть такой баг (правда кажется создатель модуля считает его фичей): у всех анонимных постеров при переносе пропадают имена (все становятся Anonymous).
Решается так:
находим:
//construct the node $comment = array( 'pid' => $pid, 'nid' => $nid, 'uid' => $uid, 'subject' => $post->post_subject, 'comment' => $post->post_text, 'hostname' => $hostname, 'timestamp' => $post->post_time );
заменяем на:
//construct the node $comment = array( 'name' => $post->post_username, 'pid' => $pid, 'nid' => $nid, 'uid' => $uid, 'subject' => $post->post_subject, 'comment' => $post->post_text, 'hostname' => $hostname, 'timestamp' => $post->post_time );
- Для комментирования войдите или зарегистрируйтесь
ещё исправление для phpbb2drupal - как сделать чтоб пустые темы не всплывали после импорта вверх, а оставались на положенных местах:
находим:
<?php
$query = db_query('SELECT *
FROM %stopics t
INNER JOIN %sposts p ON t.topic_id = p.topic_id
INNER JOIN %sposts_text pt ON p.post_id = pt.post_id
WHERE p.post_id = t.topic_first_post_id
AND t.topic_id = %d',$pre, $pre, $pre, $result->topic_id);
?>заменяем на:
<?php
$query = db_query('SELECT p.*,t.*,pt.*, plast.post_time AS last_comment_timestamp
FROM %stopics t
INNER JOIN %sposts plast ON t.topic_last_post_id = plast.post_id
INNER JOIN %sposts p ON t.topic_id = p.topic_id
INNER JOIN %sposts_text pt ON p.post_id = pt.post_id
WHERE p.post_id = t.topic_first_post_id
AND t.topic_id = %d',$pre, $pre, $pre, $pre, $result->topic_id);
?>находим:
<?php
db_set_active('default');
node_save($node);
taxonomy_node_save($node->nid, array($tid));
?>вставляем после этого:
<?php
db_query("UPDATE {node_comment_statistics} SET last_comment_timestamp=%d WHERE nid=%d ",$topic->last_comment_timestamp,$node->nid);
?>- Для комментирования войдите или зарегистрируйтесь
apple_rom, возникла проблема с применением кода, который отвечает за нормальные ссылки на последние комментарии.
Функцию в comment.module добавил, кроме того изменил код в блоке последних комментариев, который ты привел.
Посмотрел - в блоке у всех комментариев значится "..." вместо сабжа, а также ссылки в блоке на комментарии глючат - везде указывается page=1, даже у комментариев, которые на первой странице, хотя у них должно стоять page=0.
Как решить проблему?
- Для комментирования войдите или зарегистрируйтесь
Может и не в тему чуть, но я увидел, что об uie не очень хорошего мнения, лично я считаю его единственным форумом, для которого не надо дополнительные модули для реализации моста между друпой и движком форума.
Мнение уместно в случае создания (нового) сайта/форума, а не переноса уже имеющегося phpbb2-форума. Чего не поддерживает и, по заверению автора, не будет поддерживать, uie.
brooho
Большое спасибо за добавления - вмести с Вашими (и изложенным выше мною) поправками модуль phpbb2drupal станет, наконец, относительно полноценным.
- Для комментирования войдите или зарегистрируйтесь
К сожалению, возниклим проблемы при исправлении просмотра последней страницы вместо первой... Друпал 5 версии. Модулей comment.module и forum.module в папке с модулями аж две штуки - в самой папке и в подпапках comment и module. Какие из них нужно править и в какую часть текста размещать участки кода?
Я сделал все, как в инструкции, но сайт стал отображаться пустым HTMLом, чистым листом. Видимо, что-то все-таки ушло от моего внимания и хотелось бы спросить подробностей - как поставить код, чтобы исключить ошибки?
- Для комментирования войдите или зарегистрируйтесь
Возможно, кому-то понадобится
Длинный пост на друпал.орге о многостраничных комментариях. http://drupal.org/node/6162
Нда, видно что это проблема уже долго тянется...
К сожалению, из-за огромного количества патчей, решений, я так и не смогла выбрать себе наиболее нормальное. Если кто-нибудь разбирающийся посмотрит, напишите, пж-ста, какой там наиболее нормальный!
- Для комментирования войдите или зарегистрируйтесь
интересно, как в 6 все эти хаки и хуки
- Для комментирования войдите или зарегистрируйтесь
Да, очень даже полезная статья. Под шестерку вроде тоже есть модуль. Вообще очень интересный опыт!
- Для комментирования войдите или зарегистрируйтесь
Замечательная статья, но почему ни слова об advanced forum?
Он сразу решает половину перечисленных и неперечисленных проблем :) Во время написания статьи его наверное еще не было?
Нет возможности "Отметить все темы прочитанными" - беда, пока не решил.
- есть в AF
Непривычно (неудобно?) - новую тему можно начать прямо с главной страницы форума (и/или контейнеров), но нельзя из "подфорумов".
- решено в AF
плюс более симпатичный вид главной страницы форумов и возможность менять темы оформления.
А вот проблемы с многостраничными комментариями до сих пор актуальны, автору спасибо, всё работает на 5.8.
Может быть кто подскажет как аналогично доработать comment_notify.module ? В каком месте там надо заменить NULL на функцию вычисления последней страницы, чтобы уведомление приходило с правильной ссылкой? Моих собственных способностей хватает только на copy-paste :(
- Для комментирования войдите или зарегистрируйтесь
адвансед говорят сильно нагружает систему
проверить не могу.
а вообще, щас актуально решения под 6-ю версию
- Для комментирования войдите или зарегистрируйтесь













Комментарии