Комментирование закрыто.
Улучшение форума Drupal. Часть 2.
Часть 2: Комбинированная задача. Улучшаем представление вида главной страницы Форумы.
Это продолжение. Часть 1 находится по адресу selikoff.ru/webmaster/drupal-forum-1
Задача 1 – указывать в столбце “последнее сообщение” каждого форума не только дату
топика и имя добавившего, но и Заголовок топика (нода) + кол-во
сообщений в топике (комментов нода)
Задача 2 – позволить сворачивать форумы с запоминанием в кукисах.
Для решения этих задач переопределяю функцию theme_forum_list в template.php
(далее по правилам переопределения функций замените MY-THEME-NAME на имя вашей темы)
<?php
function MY-THEME-NAME_forum_list($forums, $parents, $tid) {
global $user;
if ($forums) {
//
// следующий js-скрипт необходим для решения задачи №2 - сворачивание форумов.
// (его содержимое будет ниже)
// недостаток у скрипта в том что он написан мною по подобию бюлетеневского,
// а не на базе встроенного jquery , но работает от этого он не хуже
//
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 =(
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 = '<div style="margin-left: '. ($forum->depth * 30) ."px;\">\n";
$description .= ' <div class="name">'. l($forum->name, "forum/$forum->tid") ."<img
src=\"/misc/menu-expanded.png\" align=right style=\"cursor:pointer\" id=\"img_$cc\"
onClick=\"return collapse(".$cc.")\" /></div>\n";
if ($forum->description) {
$description .= ' <div class="description">'. filter_xss_admin($forum->description) ."</div>\n";
}
$description .= "</div>\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 = '<div style="margin-left: '. ($forum->depth * 30) ."px;\">\n";
$description .= ' <div class="name">'. l($forum->name, "forum/$forum->tid") ."</div>\n";
if ($forum->description) {
$description .= ' <div class="description">'. filter_xss_admin($forum->description) ."</div>\n";
}
$description .= "</div>\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."] <br />\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
(для того чтобы иметь возможность сворачивать форумы)
<?php
function MY-THEME-NAME_table($header, $rows, $attributes = array(), $caption = NULL) {
$output = '<table'. drupal_attributes($attributes) .">\n";
if (isset($caption)) {
$output .= '<caption>'. $caption ."</caption>\n";
}
// Format the table header:
if (count($header)) {
$ts = tablesort_init($header);
$output .= ' <thead><tr>';
foreach ($header as $cell) {
$cell = tablesort_header($cell, $header, $ts);
$output .= _theme_table_cell($cell, TRUE);
}
$output .= " </tr></thead>\n";
}
// Format the table rows:
$output .= "<tbody>\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 .= "</tbody>\n<tbody id=\"container_$number\">";
// Build row
$output .= ' <tr'. drupal_attributes($attributes) .'>';
$i = 0;
foreach ($cells as $cell) {
$cell = tablesort_cell($cell, $header, $ts, $i++);
$output .= _theme_table_cell($cell);
}
$output .= " </tr>\n";
//
// разбиваю таблицу на много частей
//
if ($container) $output .= "</tbody>\n<tbody id=\"collapsitbody_$number\" class='visib'>";
}
}
$output .= "</tbody></table>\n";
return $output;
}
?>
Содержимое файла 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;
}
?>
Рубрики Drupal, Вебмастеру | Comments Off
