Улучшаем форум. Часть 2

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

Аватар пользователя selff selff 27 декабря 2007 в 11:17

Часть 2: Комбинированная задача. Улучшаем представление вида главной страницы Форумы.
это продолжение, часть 1 находится по адресу www.drupal.ru/node/10510

    Задачи:
  1. № 1 - указывать в столбце "последнее сообщение" каждого форума не только дату
    топика и имя добавившего, но и Заголовок топика (нода) + кол-во
    сообщений в топике (комментов нода)
  2. № 2 - позволить сворачивать форумы с запоминанием в кукисах.



скриншот форума


Для решения этих задач переопределяю функцию theme_forum_list в template.php
(далее по правилам переопределения функций замените MY-THEME-NAME на имя вашей темы):

function MY-THEME-NAME_forum_list($forums, $parents, $tid) {
global $user;

if ($forums) {
//
// следующий js-скрипт необходим для решения задачи №2 - сворачивание форумов.
// (его содержимое будет ниже)
// недостаток у скрипта в том что он написан мною по подобию бюлетеневского,
// а не на базе встроенного jquery Sad , но работает от этого он не хуже Smile
//
drupal_add_js('misc/myforum.js');
$header = array(t('Forum'), t('Topics'), t('Posts'), t('Last post'));
//
// Данный запрос не является идеальным, над ним еще прийдется поколдавать, это быстрое
// решение которое пришло мне в голову, но оно начнет неправильно выдавать результат,
// когда у нас появяться более одного сообщения созданного в одну и ту же секунду.
// Этот запрос требуется для решения первой задачи - вывод заголовка нового нода
// или нода который прокомментировали последним
//
$sql = "
SELECT f.tid, n.nid,n.title,nc.last_comment_timestamp,nc.comment_count,nc.last_comment_uid as uid,
CASE WHEN nc.last_comment_name THEN nc.last_comment_name ELSE u.name END as name
FROM {forum} AS f, {node} AS n,{node_comment_statistics} AS nc
INNER JOIN {users} u ON nc.last_comment_uid = u.uid
WHERE n.nid = f.nid AND nc.nid=n.nid AND nc.last_comment_timestamp Sad
SELECT max(ncs.last_comment_timestamp)
FROM {node_comment_statistics} AS ncs,{node} nd,{forum} fr
WHERE ncs.nid=nd.nid AND nd.nid=fr.nid AND nd.type='forum' AND fr.tid=f.tid
GROUP BY fr.tid
)
GROUP BY f.tid
";
$result = db_query(db_rewrite_sql($sql));
$nodetopic = array();
while ($nt = db_fetch_object($result)){
$nodetopic[$nt->tid]->topic = drupal_strlen($nt->title)>40?drupal_substr($nt->title,0,40)."...":$nt->title;
$nodetopic[$nt->tid]->node = $nt->nid; // id нода
$nodetopic[$nt->tid]->alt = $nt->title; // заголовок нода
$nodetopic[$nt->tid]->count = $nt->comment_count; // кол-во комментов
$nodetopic[$nt->tid]->user->uid = $nt->uid; // id пользователя
$nodetopic[$nt->tid]->user->name = $nt->name; // имя пользователя
$nodetopic[$nt->tid]->user->timestamp = $nt->last_comment_timestamp; // время последнего сообщения
}
$cc=0;
foreach ($forums as $forum) {
//
// Этот блок кода решает вторую задачу - отделяет контейнеры каждого форума,
// чтобы их потом можно было сворачивать
// Сворачивать форумы мы будем с помощью стрелочек
// /misc/menu-expanded.png - стрелка указывает вниз (форум развернут)
// /misc/menu-expanded_collapsed.png - стрелка указывает влево (форум свернут)
//
if ($forum->container) {
$description = 'depth * 30) ."px;\">\n";
$description .= ' '. l($forum->name, "forum/$forum->tid") ."\n";
if ($forum->description) {
$description .= ' '. filter_xss_admin($forum->description) ."\n";
}
$description .= "\n";
$rows[] = array(array('data' => $description, 'class' => 'container', 'colspan' => '4'));
$cc++;
}
else {
$new_topics = _forum_topics_unread($forum->tid, $user->uid);
$forum->old_topics = $forum->num_topics - $new_topics;
if (!$user->uid) {
$new_topics = 0;
}

$description = 'depth * 30) ."px;\">\n";
$description .= ' '. l($forum->name, "forum/$forum->tid") ."\n";

if ($forum->description) {
$description .= ' '. filter_xss_admin($forum->description) ."\n";
}
$description .= "\n";
$nt = $nodetopic[$forum->tid];
//
// В следующем массиве я меняю последний элемент (это вывод в столбец Последнее сообщение)
//
$rows[] = array(
array('data' => $description, 'class' => 'forum'),
array('data' => $forum->num_topics . ($new_topics ? ' '. l('[+'.$new_topics.']', "forum/$forum->tid", NULL, NULL, 'new') : ''), 'class' => 'topics'),
array('data' => $forum->num_posts, 'class' => 'posts'),
array('data' => ($nt ? ( l ( $nt->topic, "node/$nt->node", array('title'=>$nt->alt, 'class'=>'replay-topic' ) , NULL , 'new')) . " [".$nt->count."]
\n"
: '' ) . theme('forum_format', $nt->user), 'class' => 'last-reply')
);//array('data' => _forum_format($forum->last_post), 'class' => 'last-reply')

$cc++;
}
}

return theme('table', $header, $rows);

}

}
?>

Кроме того, там же в template.php переопределяю функцию theme_table
(для того чтобы иметь возможность сворачивать форумы):

function MY-THEME-NAME_table($header, $rows, $attributes = array(), $caption = NULL) {
$output = '

\n";
if (isset($caption)) {
$output .= ''. $caption ."\n";
}
// Format the table header:
if (count($header)) {
$ts = tablesort_init($header);
$output .= '
';
foreach ($header as $cell) {
$cell = tablesort_header($cell, $header, $ts);
$output .= _theme_table_cell($cell, TRUE);
}
$output .= "

\n";
}
// Format the table rows:
$output .= "\n";
if (count($rows)) {
$flip = array('even' => 'odd', 'odd' => 'even');
$class = 'even';
foreach ($rows as $number => $row) {
$attributes = array();
$container = false;
if ($row[0]['class']=='container') $container = true;
if ($container) $attributes['class'] = 'collapsitbody';
if (isset($row['data'])) {
foreach ($row as $key => $value) {
if ($key == 'data') {
$cells = $value;
}
else {
$attributes[$key] = $value;
}
}
}
else {
$cells = $row;
}
// Add odd/even class
$class = $flip[$class];
if (isset($attributes['class'])) {
$attributes['class'] .= ' '. $class;
}
else {
$attributes['class'] = $class;
}
//
// разбиваю таблицу на части
//
if ($container) $output .= "\n";
// Build row
$output .= '

';
$i = 0;
foreach ($cells as $cell) {
$cell = tablesort_cell($cell, $header, $ts, $i++);
$output .= _theme_table_cell($cell);
}
$output .= "

\n";
//
// разбиваю таблицу на много частей
//
if ($container) $output .= "\n";
}
}

$output .= "

\n";
return $output;
}
?>

UPD:
И кроме того я ввел новую функцию для отображения время/даты и пользователя:
(вместо функции _forum_format )
function MY-THEME-NAME_forum_format($topic) {
if ($topic && $topic->timestamp) {
$str = t('time от !author', array('time' => format_date($topic->timestamp, 'custom', 'H:i d.m.Y', NULL), '!author' => theme('username', $topic)));
return $str;
}
else {
return t('n/a');
}
}
?>

Содержимое файла myforum.js

window.onload = function () {
    //alert ( fetch_cookie('myforum_collapse') );
    arrayofcont = fetch_cookie('myforum_collapse');
    if (arrayofcont!= null){
        arrayofcont = arrayofcont.split('\n');
        for (var i in arrayofcont) {
            collapse(arrayofcont[i]);
        }
    }
}
var is_regexp = (window.RegExp) ? true : false;
function fetch_object(idname) {
        if (document.getElementById){ return document.getElementById(idname); }
        else if (document.all){ return document.all[idname]; }
        else if (document.layers){ return document.layers[idname]; }
        else { return null; }
}
function collapse(id) {
        if (!is_regexp)return false;
        obj = fetch_object('collapsitbody_' + id);
        row = fetch_object('container_' + id);
        img = fetch_object('img_' + id);
        if (!obj)
        {
                if (img)img.style.display = 'none';
                return false;
        }
        if (obj.style.display == 'none')
        {
                obj.style.display = '';
                save_collapsed(id, false);
                if (img)
                {
                        img_re = new RegExp("_collapsed\\.png$");
                        img.src = img.src.replace(img_re, '.png');
                }
        }else{
                obj.style.display = 'none';
                save_collapsed(id, true);
                if (img)
                {
                        img_re = new RegExp("\\.png$");
                        img.src = img.src.replace(img_re, '_collapsed.png');
                }
        }
        return false;
}
function save_collapsed(id, addcollapsed)
{
        var collapsed = fetch_cookie('myforum_collapse');
        var tmp = new Array();
        if (collapsed != null)
        {
                collapsed = collapsed.split('\n');
                for (var i in collapsed)
                    if (collapsed[i] != id && collapsed[i] != '') tmp[tmp.length] = collapsed[i];
        }
        if (addcollapsed) tmp[tmp.length] = id;
        expires = new Date();
        expires.setTime(expires.getTime() + (1000 * 86400 * 365));
        set_cookie('myforum_collapse', tmp.join('\n'), expires);
}
function set_cookie(name, value, expires)
{
        document.cookie = name + '=' + escape(value) + '; path=/' + (typeof expires != 'undefined' ? '; expires=' + expires.toGMTString() : '');
}
function delete_cookie(name)
{
        document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT' +  '; path=/';
}
function fetch_cookie(name)
{
        cookie_name = name + '=';
        cookie_length = document.cookie.length;
        cookie_begin = 0;
        while (cookie_begin < cookie_length)
        {
                value_begin = cookie_begin + cookie_name.length;
                if (document.cookie.substring(cookie_begin, value_begin) == cookie_name)
                {
                        var value_end = document.cookie.indexOf (';', value_begin);
                        if (value_end == -1)value_end = cookie_length;
                        return unescape(document.cookie.substring(value_begin, value_end));
                }
                cookie_begin = document.cookie.indexOf(' ', cookie_begin) + 1;
                if (cookie_begin == 0)break;
        }
        return null;
}

продолжение следует...

Комментарии

Аватар пользователя selff selff 27 декабря 2007 в 14:27

либо у вас конфликтует js с другими (хотя это мало вероятно), либо css свойства table,tbody,thead .. перекрываются
надо смотреть, ничего определённее сказать не могу

Аватар пользователя Separator@drupal.org Separator@drupal.org 27 декабря 2007 в 14:27

Это заработало. просто не было картинки с названием menu-expanded_collapsed.png
теперь другая проблема, последнее сообщение и количество коментариеа отображаются, а вот автор и время нет

Аватар пользователя selff selff 27 декабря 2007 в 14:59

ой, да. забыл написать: я использую свою функцию для отображения время/даты и пользователя
function MY-THEME-NAME_forum_format($topic)
см. UPD перед js файлом

Аватар пользователя AQUADES AQUADES 12 января 2008 в 20:45

Немного подправил пути к файлам...
А какие именно подправляли пути, уважаемый.
После того, как внес поправки описанные выше при создании и редактировании поста попадаю в пустую страницу.

Аватар пользователя AQUADES AQUADES 12 января 2008 в 21:25

enkosynthesys1 wrote:
добавил указанные функции в файл template.php находящийся в папке с темой, но форум не изменился Sad
в чем я не прав?

<?php ... ?> убрали?
название вашей темы в названиях функций вместо MY-THEME-NAME исправили?

Аватар пользователя AQUADES AQUADES 12 января 2008 в 22:38

enkosynthesys1 wrote:
да "<?php" убрал.
и название исправил...
может тело в том что у меня в названии темы подчеркивание?
получается theme_new_forum_list

Применительно стандартной темы у меня получается garland_forum_list - при этом все работает, правда почему то когда в форуме создаю/изменяю пост или комментарий после нажатия кнопки "отправить" попадаю черт знает куда, причем изменения вносятся, а визуально в этот момент у меня белое окно. Т.е. при стандартных установках после нажатия я попадаю, например ...node/4#comment-4, а с этими изменениями/улучшениями я попадаю в ...comment/edit/4
У кого такая же беда, подскажите, как исправить, я в пхп не сильно шарю, поэтому испытываю определенные сложности с этим делом.

Аватар пользователя AQUADES AQUADES 12 января 2008 в 22:50

Заново приклеил все функции в DW к исходному файлу, перезалил - всё работает. Странно. Так и не разобрался в чем была проблема. Smile Пока работает и ладно.
Автору ещё раз спасибо. Ждем новых введений.

Аватар пользователя studmedia_red studmedia_red (не проверено) 2 февраля 2008 в 14:06

Не побоюсь этого слова, здорово! Но один из админов установил FlatForum и количество просмотров после установки этого кода не просматривается. Они конфликтуют?

И еще наивный вопрос - куда класть myforum.js и нужно ли его специально вызывать из кода (дописывать шаблон), или достаточно просто закачать файл?

Аватар пользователя SlavviR SlavviR 20 февраля 2008 в 12:41

!!! заметил, что после вышеописанных процедур, информация о последних сообщениях показывается только для тех у кого в правах доступа разрешено управлять материалами (модуль node)
а кому запрещено, показывает, что последних сообщений нет.
что за зверь то такой и как с ним бороться?

Аватар пользователя SlavviR SlavviR 19 января 2009 в 12:12

всему причина – модуль Forum Access
удалил, обновил в «Публикациях» правила доступа

всё! теперь всем доступен этот чудный фейс форума
ох как я доволен!

Аватар пользователя selff selff 1 марта 2008 в 19:53

studmedia_red ,
1. По поводу FlatForum не знаю, но догадываюсь что конфликтуют,
если кол-во просмотров не видно значит флат форум переопределил ту же функцию что и я переопределял.
2. myforum.js клади куда хочешь, я положил в /misc
и в функции:
> function MY-THEME-NAME_forum_list($forums, $parents, $tid) {
.. я указал откуда его брать
drupal_add_js('misc/myforum.js');

SlavviR , у меня таких проблем нет, смотрите права доступа к форумам и нодам для анонимов,
у меня все и незарегистрированный пользователь тоже видят число сообщений.

Аватар пользователя leramulina leramulina 16 марта 2008 в 0:51

Я - начинающий друпаловод Smile Объясните, пожалуйста, что значит: "Для решения этих задач переопределяю функцию theme_forum_list". Это мне надо в template.php добавить этот код??? И если да, то в какой участок?

Аватар пользователя cosmos cosmos 30 мая 2008 в 11:57

неперекрывается функция
ставлю в template.php
function mytheme_forum_list($forums, $parents, $tid) {
echo "gfmgfmhghmhj";
}

и не ничего не выводится

Аватар пользователя listai listai 6 августа 2009 в 12:24

"SlavviR" wrote:
всё! теперь всем доступен этот чудный фейс форума
ох как я доволен!

а к 6 весии Drupal такого кода нет?