forum.module 29.9 KB
Newer Older
Dries's avatar
 
Dries committed
1 2 3
<?php
// $Id$

4
function forum_system($field){
Dries's avatar
 
Dries committed
5 6 7 8 9 10
  $output = "";

  if ($field == "description") { $output = forum_help("admin/system/modules"); }
  else if ($field == "admin_help") { $output = forum_help("admin/system/modules/forum"); };

  return $output;
11 12
}

Dries's avatar
 
Dries committed
13
function forum_node($field) {
Dries's avatar
 
Dries committed
14
  $info["name"] = t("forum topic");
Dries's avatar
 
Dries committed
15 16 17 18 19 20 21 22 23
  $info["description"] = t("A forum is a threaded discussion, enabling users to communicate about a particular topic.");

  return $info[$field];
}

function forum_access($op, $node) {
  if ($op == "view") {
    return $node->status;
  }
Dries's avatar
 
Dries committed
24
  if ($op == "create") {
Dries's avatar
 
Dries committed
25
    return user_access("create forum topics");
Dries's avatar
 
Dries committed
26
  }
Dries's avatar
 
Dries committed
27 28
}

Dries's avatar
 
Dries committed
29
function forum_perm() {
Dries's avatar
 
Dries committed
30
  return array("create forum topics");
Dries's avatar
 
Dries committed
31
}
Dries's avatar
 
Dries committed
32

33
function forum_settings() {
Dries's avatar
 
Dries committed
34

Dries's avatar
 
Dries committed
35
  if (module_exist("taxonomy")) {
Dries's avatar
 
Dries committed
36
    $vocs[0] = "<". t("none") .">";
Dries's avatar
 
Dries committed
37 38 39 40
    foreach (taxonomy_get_vocabularies("forum") as $vid => $voc) {
      $vocs[$vid] = $voc->name;
    }

Dries's avatar
 
Dries committed
41
    if ($voc) {
42 43 44
      $output .= form_textarea(t("Explanation or submission guidelines"), "forum_help", variable_get("forum_help", ""), 70, 5, t("This text will be displayed at the top of the forum submission form.  Useful for helping or instructing your users."));
      $output .= form_select(t("Forum vocabulary"), "forum_nav_vocabulary", variable_get("forum_nav_vocabulary", ""), $vocs, t("The taxonomy vocabulary that will be used as the navigation tree."));
      $output .= _taxonomy_term_select(t("Containers"), "forum_containers", variable_get("forum_containers", array()), variable_get("forum_nav_vocabulary", ""), t("You can choose forums which will not have topics, but will be just containers for other forums."), 1, t("<none>"));
Dries's avatar
 
Dries committed
45

46 47
      $output .= form_textfield(t("Topic icons path"), "forum_topic_icon_path", variable_get("forum_topic_icon_path", ""), 30, 255, t("The path to the topic icons.  Leave blank to disable icons."));
      $output .= form_textfield(t("Folder icons path"), "forum_folder_icon_path", variable_get("forum_folder_icon_path", ""), 30, 255,t( "The path to the <b>default</b>, <b>hot</b>, <b>new</b>, <b>hot & new</b>, and <b>closed</b> folder icons.  Leave blank to disable icons."));
Dries's avatar
 
Dries committed
48
      $number = array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 30 => 30, 35 => 35, 40 => 40, 50 => 50, 60 => 60, 80 => 80, 100 => 100, 10000=>10000);
49
      $output .= form_select(t("Hot topic threshold"), "forum_hot_topic", variable_get("forum_hot_topic", 15), $number, t("The number of posts a topic must have to be considered <b>hot</b>."));
Dries's avatar
 
Dries committed
50
      $number = array(10 => 10, 25 => 25, 50 => 50, 75 => 75, 100 => 100);
51 52 53 54
      $output .= form_select(t("Topics per page"), "forum_per_page", variable_get("forum_per_page", 25), $number, t("The default number of topics displayed per page; links to browse older messages are automatically being displayed."));
      $forder = array(1 => t("Date - newest first"), 2 => t("Date - oldest first"), 3 => t("Posts - most active first"), 4=> t("Posts - least active first"));
      $output .= form_select(t("Default order"), "forum_order", variable_get("forum_order", 1), $forder, t("The default display order for topics."));
      $output .= form_textfield(t("Number of topics in block"), "forum_block_num", variable_get("forum_block_num", "5"), 5, 5, t("The number of topics in the <b>Forum topics</b>-block.  To enable the block, click ". l("here", "admin/block") ."."));
Dries's avatar
 
Dries committed
55 56 57 58 59 60 61 62
    }
    else {
      $output .= _forum_message_taxonomy();
    }
  }
  else {
    $output .= _forum_message_taxonomy();
  }
Dries's avatar
 
Dries committed
63

Dries's avatar
 
Dries committed
64 65 66
  return $output;
}

Dries's avatar
Dries committed
67 68
function forum_taxonomy($op, $type, $object) {
  if ($type == "vocabulary" && ($op == "insert" || $op == "update")) {
Dries's avatar
 
Dries committed
69
    if (variable_get("forum_nav_vocabulary", "") == "" && in_array("forum", $object["nodes"])) {
Dries's avatar
Dries committed
70 71 72 73 74 75
      // since none is already set, silently set this vocabulary as the navigation vocabulary
      variable_set("forum_nav_vocabulary", $object["vid"]);
    }
  }
}

Dries's avatar
 
Dries committed
76
function forum_load($node) {
Dries's avatar
 
Dries committed
77
  $forum = db_fetch_object(db_query("SELECT * FROM {forum} WHERE nid = %d", $node->nid));
Dries's avatar
 
Dries committed
78 79 80 81

  return $forum;
}

82 83 84 85 86 87
function forum_block($op = "list", $delta = 0) {
  if ($op == "list") {
    $blocks[0]["info"] = t("Forum topics");
  }
  else {
    if (user_access("access content")) {
Dries's avatar
 
Dries committed
88
      $content = node_title_list(db_query_range("SELECT n.nid, n.title, u.uid, u.name, GREATEST(n.created, MAX(c.timestamp)) AS sort FROM {node} n INNER JOIN {forum} f ON n.nid = f.nid INNER JOIN {comments} c ON n.nid = c.nid LEFT JOIN {users} u ON n.uid = u.uid WHERE n.type = 'forum' AND n.nid = f.nid AND n.status = 1 GROUP BY n.nid, n.title, n.created, u.uid, u.name ORDER BY sort DESC", 0, variable_get("forum_block_num", "5")), t("Active forum topics:"));
Dries's avatar
 
Dries committed
89

Dries's avatar
 
Dries committed
90
      $content .= node_title_list(db_query_range("SELECT n.nid, n.title, u.uid, u.name FROM {node} n INNER JOIN {forum} f ON n.nid = f.nid LEFT JOIN {users} u ON n.uid = u.uid WHERE n.type = 'forum' ORDER BY n.nid DESC", 0, variable_get("forum_block_num", "5")), t("New forum topics:"));
Dries's avatar
 
Dries committed
91

Dries's avatar
 
Dries committed
92 93
      if ($content) {
        $content .= "<div id=\"forum_more\" style=\"text-align: right;\">". l(t("more"), "forum", array("title" => t("Read the latest forum topics."))) ."</div>";
Dries's avatar
 
Dries committed
94
      }
Dries's avatar
 
Dries committed
95

96
      $blocks["subject"] = t("Forum topics");
Dries's avatar
 
Dries committed
97
      $blocks["content"] = $content;
Dries's avatar
 
Dries committed
98 99
    }
  }
Dries's avatar
 
Dries committed
100

Dries's avatar
 
Dries committed
101 102 103
  return $blocks;
}

104
function forum_link($type, $node = 0, $main = 0) {
Dries's avatar
Dries committed
105
  global $user;
Dries's avatar
 
Dries committed
106

Dries's avatar
 
Dries committed
107 108
  $links = array();

Dries's avatar
 
Dries committed
109
  if ($type == "page" && user_access("access content")) {
Dries's avatar
 
Dries committed
110
    $links[] = l(t("forum"), "forum");
Dries's avatar
 
Dries committed
111 112
  }

113
  if (!$main && $type == "node" && $node->type == "forum") {
Dries's avatar
 
Dries committed
114 115
    // get previous and next topic

Dries's avatar
 
Dries committed
116
    $result = db_query("SELECT n.nid, n.title, n.body, n.path, GREATEST(n.created, MAX(c.timestamp)) AS date_sort, COUNT(c.nid) AS num_comments FROM {node} n INNER JOIN {forum} f ON n.nid = f.nid INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = f.nid AND f.tid = %d AND n.status = 1 GROUP BY n.nid, n.title, n.body, n.created ORDER BY ". _forum_get_topic_order(isset($user->sortby) ? $user->sortby : variable_get("forum_order",1)), $node->tid);
Dries's avatar
 
Dries committed
117 118 119 120 121 122

    while ($topic = db_fetch_object($result)) {
      if ($stop == 1) {
        $next->nid = $topic->nid;
        $next->title = $topic->title;
        $next->body = $topic->body;
Dries's avatar
 
Dries committed
123
        $next->path = $topic->path;
Dries's avatar
 
Dries committed
124 125 126 127 128 129 130 131 132
        break;
      }
      if ($topic->nid == $node->nid) {
        $stop = 1;
      }
      else {
        $prev->nid = $topic->nid;
        $prev->title = $topic->title;
        $prev->body = $topic->body;
Dries's avatar
 
Dries committed
133
        $prev->path = $topic->path;
Dries's avatar
 
Dries committed
134 135 136 137
      }
    }

    if ($prev) {
Dries's avatar
 
Dries committed
138
      $links[] = l(t("previous forum topic"), node_url($prev), array("title" => $prev->title .": ". substr(strip_tags($prev->body), 0, 100)."..."));
Dries's avatar
 
Dries committed
139 140 141
    }

    if ($next) {
Dries's avatar
 
Dries committed
142
      $links[] = l(t("next forum topic"), node_url($next), array("title" => $next->title .": ". substr(strip_tags($next->body), 0, 100)."..."));
Dries's avatar
 
Dries committed
143
    }
Dries's avatar
 
Dries committed
144 145
  }

Dries's avatar
 
Dries committed
146
  return $links;
Dries's avatar
 
Dries committed
147 148
}

Dries's avatar
 
Dries committed
149
function forum_view($node, $main = 0) {
Dries's avatar
 
Dries committed
150

Dries's avatar
 
Dries committed
151 152 153 154 155 156 157 158

  $term_data = array_shift(taxonomy_node_get_terms($node->nid));
  if (!$term_data) {
    // we are previewing
    $term_data = taxonomy_get_term($node->taxonomy[0]);
  }
  $voc = taxonomy_get_vocabulary($term_data->vid);

159
  if (!$main) {
Dries's avatar
 
Dries committed
160
    $node->title = _forum_get_icon($node) ." ". l($voc->name, "forum") ." : ". l($term_data->name, "forum/$term_data->tid") ." / <b>$node->title</b>";
161
  }
Dries's avatar
 
Dries committed
162

Dries's avatar
 
Dries committed
163 164 165
  $node->teaser = check_output($node->teaser);
  $node->body = check_output($node->body);

Dries's avatar
 
Dries committed
166
  theme("node", $node, $main);
Dries's avatar
 
Dries committed
167 168
}

169 170 171 172
function forum_validate(&$node) {
  // Make sure all fields are set properly:
  $node->icon = $node->icon ? $node->icon : "";
  $node->shadow = $node->shadow ? $node->shadow : 0;
173
  $node->tid = $node->tid ? $node->tid : 0;
174 175 176 177 178 179
  // We use the validate hook to remember the old taxonomy terms:
  if ($node->tid) {
    $node->taxonomy = array_keys(taxonomy_node_get_terms($node->nid));
    if (!in_array($node->tid[0], $node->taxonomy)) {
      $node->taxonomy[] = $node->tid[0];
    }
Dries's avatar
Dries committed
180 181 182
  }
}

Dries's avatar
 
Dries committed
183
function forum_form(&$node, &$help, &$error) {
Dries's avatar
Dries committed
184 185 186
  if ($node->tid) {
    // editing
    $tid = $node->tid;
187 188
  }
  else {
Dries's avatar
Dries committed
189 190
    // new topic
    $tid = arg(3);
191 192
  }

Dries's avatar
 
Dries committed
193 194 195
  // outputs the compose guidelines
  $help = variable_get("forum_help", "");

196
  $output .= _taxonomy_term_select(t("Forum"), "tid", $tid, variable_get("forum_nav_vocabulary", ""), "", 0, "", variable_get("forum_containers", array()));
Dries's avatar
Dries committed
197 198 199 200 201

  if ($node->nid) {
    // if editing, give option to leave shadows
    $output .= form_checkbox(t("Leave shadow copy"), "shadow", 1, $node->shadow, t("If you move this topic, you can leave a link in the old forum to the new forum."));
  }
Dries's avatar
 
Dries committed
202

Dries's avatar
 
Dries committed
203
  if ($icon_path = variable_get("forum_topic_icon_path", "")) {
Dries's avatar
 
Dries committed
204 205 206 207 208 209 210
    if ($node->icon) {
      // we are editing post
      if ($dir = @opendir($icon_path)) {
        $icon_num = 0;
        while($icon = readdir($dir)) {
          if ($icon == '.' || $icon == '..') {continue;}
          if ($node->icon == $icon) {$checked = "checked";} else {$checked = "";}
Dries's avatar
 
Dries committed
211
          $radio .= "<input type=\"radio\" name=\"edit[icon_num]\" value=\"$icon_num\" $checked /><img src=\"$icon_path$icon\" alt=\"\" title=\"\" /> \n";
Dries's avatar
 
Dries committed
212 213 214 215 216 217 218 219 220 221 222
          $icon_num++;
        }
        closedir($dir);
      }
    }
    else {
      if ($dir = @opendir($icon_path)) {
        $icon_num = 0;
        while($icon = readdir($dir)) {
          if ($icon == '.' || $icon == '..') {continue;}
          if ($node->icon_num == $icon_num) {$checked = "checked";} else {$checked = "";}
Dries's avatar
 
Dries committed
223
          $radio .= "<input type=\"radio\" name=\"edit[icon_num]\" value=\"$icon_num\" $checked /><img src=\"$icon_path$icon\" alt=\"\" title=\"\" /> \n";
Dries's avatar
 
Dries committed
224 225 226 227 228 229 230
          $icon_num++;
        }
        closedir($dir);
      }
    }
    $output .= form_item(t("Topic icon"), $radio);
  }
Dries's avatar
Dries committed
231
  $output .= form_textarea(t("Body"), "body", $node->body, 60, 10);
Dries's avatar
 
Dries committed
232 233 234 235

  return $output;
}

Dries's avatar
 
Dries committed
236 237
function forum_insert($node) {
  $node->icon = _forum_decode_icon($node);
Dries's avatar
 
Dries committed
238
  db_query("INSERT INTO {forum} (nid, icon, shadow, tid) VALUES (%d, '%s', %d, %d)", $node->nid, $node->icon, $node->shadow, $node->tid[0]);
Dries's avatar
 
Dries committed
239 240 241 242
}

function forum_update($node) {
  $node->icon = _forum_decode_icon($node);
Dries's avatar
 
Dries committed
243
  db_query("UPDATE {forum} SET icon = '%s', shadow = %d, tid = %d WHERE nid = %d", $node->icon, $node->shadow, $node->tid[0], $node->nid);
Dries's avatar
 
Dries committed
244 245 246 247
}

function _forum_decode_icon($node) {
  // to prevent malicious users
Dries's avatar
 
Dries committed
248
  if ($icon_path = variable_get("forum_topic_icon_path", "")) {
Dries's avatar
 
Dries committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262
    if ($dir = @opendir($icon_path)) {
      $icon_num = 0;
      while($icon = readdir($dir)) {
        if ($icon == '.' || $icon == '..') {continue;}
        if ($icon_num == $node->icon_num) {$myicon = $icon;}
        $icon_num++;
      }
      closedir($dir);
    }
  }
  return $myicon;
}

function forum_delete(&$node) {
Dries's avatar
 
Dries committed
263
  db_query("DELETE FROM {forum} WHERE nid = %d", $node->nid);
Dries's avatar
 
Dries committed
264
}
Dries's avatar
 
Dries committed
265

Dries's avatar
 
Dries committed
266
function _forum_num_comments($nid) {
Dries's avatar
 
Dries committed
267
  $value = db_fetch_object(db_query("SELECT COUNT(cid) AS count FROM {comments} WHERE nid = %d AND status = 0", $nid));
Dries's avatar
 
Dries committed
268 269 270
  return ($value) ? $value->count : 0;
}

Dries's avatar
 
Dries committed
271
function _forum_last_comment($nid) {
Dries's avatar
 
Dries committed
272
  $value = db_fetch_object(db_query_range("SELECT timestamp FROM {comments} WHERE nid = %d AND status = 0 ORDER BY timestamp DESC", $nid, 0, 1));
Dries's avatar
 
Dries committed
273 274 275
  return ($value) ? format_date($value->timestamp, "small") : "&nbsp;";
}

Dries's avatar
 
Dries committed
276
function _forum_last_reply($nid) {
Dries's avatar
 
Dries committed
277
  $value = db_fetch_object(db_query_range("SELECT c.timestamp, u.name, u.uid FROM {comments} c LEFT JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d AND c.status = 0 ORDER BY c.timestamp DESC", $nid, 0, 1));
Dries's avatar
 
Dries committed
278 279 280 281 282
  return $value;
}

function _forum_format($topic) {
  if ($topic) {
283
    return "<small>". t("%date<br />by %author", array("%date" => format_date($topic->timestamp, "small"), "%author" => format_name($topic))) ."</small>";
Dries's avatar
 
Dries committed
284 285 286 287 288 289 290 291 292 293 294 295 296
  }
  else {
    return message_na();
  }
}

function forum_get_forums($tid = 0) {
  global $user;

  if (!$tid) {
    $tid = 0;
  }

Dries's avatar
 
Dries committed
297
  $cache = cache_get("forum:$tid");
Dries's avatar
 
Dries committed
298

Dries's avatar
 
Dries committed
299
  if (empty($cache)) {
300
    $forums = array();
Dries's avatar
 
Dries committed
301
    $_forums = taxonomy_get_tree(variable_get("forum_nav_vocabulary", ""), $tid);
Dries's avatar
 
Dries committed
302 303 304 305 306 307 308 309 310 311 312 313 314 315
    $n = 0;
    foreach ($_forums as $forum) {
      if (in_array($forum->tid, variable_get("forum_containers", array()))) {
        $forum->container = 1;
      }
      else {
        $forum->num_topics = _forum_num_topics($forum->tid);
        $forum->num_posts = _forum_num_replies($forum->tid) + $forum->num_topics;
        $forum->last_post = _forum_last_post($forum->tid);
      }
      $forums[$forum->tid] = $forum;
      $n++;
    }

Dries's avatar
 
Dries committed
316
    cache_set("forum:$tid", serialize($forums), 1);
Dries's avatar
 
Dries committed
317
  }
Dries's avatar
 
Dries committed
318 319 320
  else {
    $forums = unserialize($cache->data);
  }
Dries's avatar
 
Dries committed
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340

  if ($user->uid && $forums) {
    foreach (_forum_topics_read($user->uid) as $tid => $old) {
      if ($forums[$tid]) {
        $forums[$tid]->old_topics = $old;
      }
    }
  }
  return $forums;
}

function forum_get_parents($tid) {
  if ($tid) {
    $parents[] = taxonomy_get_term($tid);
  }
  $n = 0;
  while ($parent = taxonomy_get_parents($parents[$n]->tid)) {
    $parents = array_merge($parents, $parent);
    $n++;
  }
Dries's avatar
 
Dries committed
341

Dries's avatar
 
Dries committed
342 343 344 345
  return $parents;
}

function _forum_num_topics($term) {
Dries's avatar
 
Dries committed
346
  $value = db_fetch_object(db_query("SELECT COUNT(n.nid) AS count FROM {node} n INNER JOIN {forum} f ON n.nid = f.nid WHERE f.tid = %d AND n.nid = f.nid AND n.status = 1 AND n.type = 'forum'", $term));
Dries's avatar
 
Dries committed
347 348 349 350
  return ($value) ? $value->count : 0;
}

function _forum_num_replies($term) {
Dries's avatar
 
Dries committed
351
  $value = db_fetch_object(db_query("SELECT COUNT(*) AS count FROM {comments} c INNER JOIN {node} n ON n.nid = c.nid INNER JOIN {forum} f ON n.nid = f.nid WHERE f.tid = %d AND n.nid = f.nid AND n.nid = c.nid AND n.status = 1 AND c.status = 0 AND n.type = 'forum'", $term));
Dries's avatar
 
Dries committed
352 353 354 355
  return ($value) ? $value->count : 0;
}

function _forum_topics_read($uid) {
Dries's avatar
 
Dries committed
356
  $result = db_query("SELECT tid, count(*) AS c FROM {history} h INNER JOIN {node} n ON n.nid = h.nid INNER JOIN {forum} f ON n.nid = f.nid WHERE f.nid = n.nid AND n.nid = h.nid AND n.type = 'forum' AND n.status = 1 AND h.uid = %d GROUP BY tid", $uid);
Dries's avatar
 
Dries committed
357 358 359 360 361 362 363 364 365

  while ($obj = db_fetch_object($result)) {
    $topics_read[$obj->tid] = $obj->c;
  }

  return $topics_read ? $topics_read : array();
}

function _forum_last_post($term) {
Dries's avatar
 
Dries committed
366
  $topic = db_fetch_object(db_query_range("SELECT n.nid, n.created AS timestamp, u.name AS name, u.uid AS uid FROM {forum} f INNER JOIN {node} n ON n.nid = f.nid LEFT JOIN {users} u ON n.uid = u.uid WHERE f.tid = %d AND n.nid = f.nid AND n.type = 'forum' AND n.status = 1 ORDER BY timestamp DESC", $term, 0, 1));
Dries's avatar
 
Dries committed
367

Dries's avatar
 
Dries committed
368
  $reply = db_fetch_object(db_query_range("SELECT n.nid, c.timestamp, u.name AS name, u.uid AS uid FROM {forum} f INNER JOIN {node} n ON n.nid = f.nid INNER JOIN {comments} c ON n.nid = c.nid LEFT JOIN {users} u ON c.uid = u.uid WHERE f.tid = %d AND n.nid = f.nid AND n.type = 'forum' AND n.status = 1 AND c.status = 0 ORDER BY c.timestamp DESC", $term, 0, 1));
Dries's avatar
 
Dries committed
369 370 371 372 373 374

  $value = ($topic->timestamp > $reply->timestamp) ? $topic : $reply;

  return $value;
}

Dries's avatar
Dries committed
375
function forum_get_topics($tid, $sortby, $forum_per_page) {
Dries's avatar
 
Dries committed
376 377 378 379 380 381 382
  global $user;

  $term = taxonomy_get_term($tid);
  $voc = taxonomy_get_vocabulary($term->vid);

  $sql_sortby = _forum_get_topic_order($sortby);

Dries's avatar
Dries committed
383
  // show topics with the correct tid, or in the forum but with shadow = 1
Dries's avatar
 
Dries committed
384
  $sql = "SELECT n.nid, n.title, u.name AS name, u.uid AS uid, n.created AS timestamp, GREATEST(n.created, MAX(c.timestamp)) AS date_sort, COUNT(c.nid) AS num_comments, f.icon, n.comment AS comment_mode, f.tid FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid LEFT JOIN {users} u ON n.uid = u.uid INNER JOIN {comments} c ON n.nid = c.nid INNER JOIN {forum} f ON n.nid = f.nid WHERE n.nid = r.nid AND ((r.tid = '".check_query($tid)."' AND f.shadow = 1) OR f.tid = '".check_query($tid)."') AND n.status = 1 AND n.type = 'forum' GROUP BY n.nid, n.title, u.name, u.uid, n.created, n.comment, f.tid, f.icon ORDER BY $sql_sortby";
Dries's avatar
Dries committed
385

Dries's avatar
 
Dries committed
386
  $sql_count = "SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {forum} f ON n.nid = f.nid INNER JOIN {term_node} r ON n.nid = r.nid WHERE n.nid = r.nid AND ( (r.tid = '".check_query($tid)."' AND f.shadow = 1) OR f.tid = '".check_query($tid)."') AND n.status = 1 AND n.type = 'forum'";
Dries's avatar
 
Dries committed
387

Dries's avatar
Dries committed
388
  $result = pager_query($sql, $forum_per_page, 0, $sql_count);
Dries's avatar
 
Dries committed
389 390 391 392
  $topic_num = db_num_rows($result);

  $n = 0;
  while ($topic = db_fetch_object($result)) {
Dries's avatar
Dries committed
393 394 395 396 397
    if ($user->uid) {
      $history = _forum_user_last_visit($topic->nid);
      // folder is new if topic is new or there are new comments since last visit
      if ($topic->shadow > 0) {
        $topic->new = 0;
Dries's avatar
 
Dries committed
398 399
      }
      else {
Dries's avatar
Dries committed
400 401
        if (!$history && $user->uid) {
          $topic->new_replies = 0;
Dries's avatar
 
Dries committed
402 403 404
          $topic->new = 1;
        }
        else {
Dries's avatar
 
Dries committed
405
          $comments = db_result(db_query("SELECT COUNT(c.nid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = '$topic->nid' AND n.status = 1 AND c.status = 0 AND timestamp > '$history' GROUP BY n.nid"));
Dries's avatar
Dries committed
406 407 408 409 410 411 412 413

          $topic->new_replies = $comments ? $comments : 0;
          if ($topic->new_replies) {
            $topic->new = 1;
          }
          else {
            $topic->new = 0;
          }
Dries's avatar
 
Dries committed
414 415
        }
      }
Dries's avatar
Dries committed
416 417 418 419 420 421
     }
     else {
      // you're not logged in eh?
      $topic->new_replies = 0;
      $topic->new = 0;
     }
Dries's avatar
 
Dries committed
422 423 424 425 426

    $topic->last_reply = _forum_last_reply($topic->nid);
    $topics[] = $topic;
  }

Dries's avatar
Dries committed
427
  return $topics;
Dries's avatar
 
Dries committed
428 429
}

Dries's avatar
Dries committed
430
function _forum_new($tid) {
Dries's avatar
 
Dries committed
431
  global $user;
Dries's avatar
 
Dries committed
432
  $result = db_query("SELECT n.nid FROM {node} n, {history} h, {forum} f WHERE n.type = 'forum' AND n.status = 1 AND h.nid = n.nid AND f.nid = h.nid AND f.tid = %d AND h.uid = %d", $tid, $user->uid);
Dries's avatar
 
Dries committed
433 434 435 436
  while ($r = db_fetch_object($result)) {
    $read[] = $r->nid;
  }

Dries's avatar
 
Dries committed
437
  $nid = db_result(db_query_range("SELECT n.nid FROM {node} n INNER JOIN {forum} f ON n.nid = f.nid WHERE n.type = 'forum' AND f.nid = n.nid AND n.status = 1 AND f.tid = %d ".($read ? "AND NOT (n.nid IN (".implode(",", $read).")) " : "") ."ORDER BY created", $tid, 0, 1));
Dries's avatar
 
Dries committed
438 439 440 441

  return $nid ? $nid : 0;
}

Dries's avatar
 
Dries committed
442 443 444 445
function _forum_message_taxonomy() {
  return t("For the forums to work, the taxonomy module has to be installed and enabled.  When activated, a taxonomy vocubulary needs to be created, bound to the forum module.  The vocabulary's terms define the forums.");
}

Dries's avatar
 
Dries committed
446
function forum_page() {
Dries's avatar
 
Dries committed
447
  global $sortby, $forum_per_page, $from, $user;
Dries's avatar
 
Dries committed
448

Dries's avatar
 
Dries committed
449
  $op = $_POST["op"];
Dries's avatar
 
Dries committed
450

Dries's avatar
 
Dries committed
451
  if (user_access("access content")) {
Dries's avatar
 
Dries committed
452
    if (module_exist("taxonomy")) {
Dries's avatar
 
Dries committed
453
      $tid = arg(1);
454
      if ($op == t("Update settings") && $user->uid) {
Dries's avatar
 
Dries committed
455 456
        $user = user_save($user, array("sortby" => $sortby, "forum_per_page" => $forum_per_page));
      }
Dries's avatar
 
Dries committed
457

Dries's avatar
Dries committed
458 459 460 461 462
      if (arg(2) == "new") {
        if ($nid = _forum_new($tid)) {
          drupal_goto(url("node/view/$nid"));
        }
      }
Dries's avatar
 
Dries committed
463

Dries's avatar
 
Dries committed
464 465 466
      if (empty($sortby)) {
        $sortby = isset($user->sortby) ? $user->sortby : variable_get("forum_order",1);
      }
Dries's avatar
 
Dries committed
467

Dries's avatar
 
Dries committed
468 469 470
      if (empty($forum_per_page)) {
        $forum_per_page = isset($user->forum_per_page) ? $user->forum_per_page : variable_get("forum_per_page", 25);
      }
Dries's avatar
 
Dries committed
471

Dries's avatar
Dries committed
472
      $offset = ($from / $forum_per_page) + 1;
Dries's avatar
 
Dries committed
473

Dries's avatar
 
Dries committed
474
      $forums = forum_get_forums($tid);
Dries's avatar
 
Dries committed
475

Dries's avatar
 
Dries committed
476 477
      $parents = forum_get_parents($tid);
      if ($tid && !in_array($tid, variable_get("forum_containers", array()))) {
Dries's avatar
Dries committed
478
        $topics = forum_get_topics($tid, $sortby, $forum_per_page);
Dries's avatar
 
Dries committed
479
      }
Dries's avatar
 
Dries committed
480

Dries's avatar
 
Dries committed
481
      theme("forum_theme_display", $forums, $topics, $parents, $tid, $sortby, $forum_per_page, $offset);
Dries's avatar
 
Dries committed
482 483
    }
    else {
Dries's avatar
 
Dries committed
484 485 486
      theme("header");
      theme("box", t("Warning"), _forum_message_taxonomy());
      theme("footer");
Dries's avatar
 
Dries committed
487
    }
Dries's avatar
 
Dries committed
488 489
  }
  else {
Dries's avatar
 
Dries committed
490 491 492
    theme("header");
    theme("box", t("Access denied"), message_access());
    theme("footer");
Dries's avatar
 
Dries committed
493 494 495
  }
}

Dries's avatar
 
Dries committed
496
/*
Dries's avatar
 
Dries committed
497
** Theme functions
Dries's avatar
 
Dries committed
498
*/
Dries's avatar
 
Dries committed
499

Dries's avatar
 
Dries committed
500
function forum_theme_display($forums, $topics, $parents, $tid, $sortby, $forum_per_page, $offset) {
Dries's avatar
 
Dries committed
501
  // forum list, topics list, topic browser and "add new topic" link
Dries's avatar
 
Dries committed
502

Dries's avatar
 
Dries committed
503

Dries's avatar
 
Dries committed
504
  $output .= theme("forum_theme_list", $forums, $parents, $tid);
Dries's avatar
 
Dries committed
505
  if ($tid && !in_array($tid, variable_get("forum_containers", array()))) {
Dries's avatar
 
Dries committed
506
    $output .= theme("forum_theme_topic_list", $tid, $topics, $sortby, $forum_per_page, $offset);
Dries's avatar
 
Dries committed
507 508
  }

Dries's avatar
 
Dries committed
509 510
  theme("header");
  theme("box", t("Discussion forum"), $output);
Dries's avatar
 
Dries committed
511
  if ($tid && !in_array($tid, variable_get("forum_containers", array()))) {
Dries's avatar
 
Dries committed
512
    theme("box", t("Control panel"), theme("forum_theme_topic_browser", $sortby, $forum_per_page, $offset));
Dries's avatar
 
Dries committed
513
  }
Dries's avatar
 
Dries committed
514
  theme("footer");
Dries's avatar
 
Dries committed
515 516
}

Dries's avatar
 
Dries committed
517
function forum_theme_list($forums, $parents, $tid) {
Dries's avatar
 
Dries committed
518 519 520 521
  global $user;
  if ($parents) {
    foreach($parents as $p) {
      if ($tid != $p->tid) {
Dries's avatar
 
Dries committed
522
        $t[] = l($p->name, "forum/$p->tid");
Dries's avatar
 
Dries committed
523 524 525 526 527 528
      }
      else {
        $t[] = $p->name;
      }
    }
  }
Dries's avatar
 
Dries committed
529
  $t[] = l(t("Discussion forum"), "forum");
Dries's avatar
 
Dries committed
530

531
  $output .= "<table border=\"0\" cellpadding=\"5\">\n";
Dries's avatar
 
Dries committed
532
  $output .= " <tr><th colspan=\"3\" style=\"text-align: left;\">".implode(" : ", array_reverse($t)) ."</th>";
Dries's avatar
 
Dries committed
533 534 535 536 537 538
  if ($forums) {
    $output .= "<th>". t("topics") ."</th><th>". t("posts") ."</th><th>". t("last post") ."</th></tr>";


    foreach ($forums as $forum) {
      if ($forum->container) {
Dries's avatar
 
Dries committed
539
        $output .= " <tr><td colspan=\"5\">". l($forum->name, "forum/$forum->tid") ."<br /><small>". ($forum->description ? check_output($forum->description) : "") ."</small></td></tr>";
540 541
      }
      else {
Dries's avatar
 
Dries committed
542 543 544
        if ($user->uid) $new_topics = $forum->num_topics - $forum->old_topics;
        $icon = _forum_get_folder_icon($new_topics);
        $output .= " <tr><td>&nbsp;</td><td>$icon</td>";
Dries's avatar
 
Dries committed
545
        $output .= "<td><table border=\"0\"><tr><td style=\"width: ". ($forum->depth * 20) ."px;\">&nbsp;</td><td>". l($forum->name, "forum/$forum->tid") ."<div style=\"padding-top: 5px;\">". check_output($forum->description);
Dries's avatar
 
Dries committed
546 547 548

        $links = array();
        if ($forum->last_post) {
Dries's avatar
 
Dries committed
549
          $links[] = l(t("the most recent topic"), "node/view/". $forum->last_post->nid);
Dries's avatar
 
Dries committed
550 551
        }
        if ($new_topics) {
Dries's avatar
Dries committed
552
          $links[] = l(t("the first new topic"), "forum/$forum->tid/new");
Dries's avatar
 
Dries committed
553 554 555
        }

        if ($links) {
Dries's avatar
 
Dries committed
556
          $output .= "<br />". t("Jump to: %links", array("%links" => implode(", ", $links)));
Dries's avatar
 
Dries committed
557 558
        }

Dries's avatar
 
Dries committed
559
        $output .= "</div></td></tr></table></td>";
Dries's avatar
 
Dries committed
560
        $output .= "<td style=\"text-align: center;\">".$forum->num_topics.($new_topics ? "<br />(".t("%a new", array("%a" => $new_topics)).")" : "")."</td><td style=\"text-align: center;\">".$forum->num_posts."</td><td style=\"text-align: center;\">"._forum_format($forum->last_post)."</td></tr>";
Dries's avatar
 
Dries committed
561 562 563 564 565 566 567 568
      }
    }
  }
  $output .= "</table>\n";

  return $output;
}

Dries's avatar
 
Dries committed
569
function forum_theme_topic_browser() {
Dries's avatar
 
Dries committed
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
  global $tid, $sortby, $forum_per_page, $offset;

  if (empty($sortby)) {
    $sortby = variable_get("forum_order",1);
  }
  if (empty($forum_per_page)) {
    $forum_per_page = variable_get("forum_per_page", 25);
  }

  $forum_per_page_options = array(10, 25, 50, 75, 100);
  foreach ($forum_per_page_options as $value) {
    $options .= " <option value=\"$value\"". ($forum_per_page == $value ? " selected=\"selected\"" : "") .">".t("%a topics per page", array("%a" => $value))."</option>\n";
  }

  $output .= "<select name=\"forum_per_page\">$options</select>\n";

  $options = "";
  $sortby_options = array(1 => t("Date - newest first"), 2 => t("Date - oldest first"), 3 => t("Posts - most active first"), 4=> t("Posts - least active first"));
  foreach ($sortby_options as $key => $value) {
    $options .= " <option value=\"$key\"". ($sortby == $key ? " selected=\"selected\"" : "") .">$value</option>\n";
  }

  $output .= "\n<select name=\"sortby\">$options</select>\n";
  $output .= form_hidden("tid", $tid);
  $output .= form_submit(t("Update settings"));
  return form(form_item(t("Topic viewing options"), $output, t("Select your preferred way to display the topics and click 'Update settings'.")));
}

Dries's avatar
 
Dries committed
598
function forum_theme_topic_list($tid, $topics, $sortby, $forum_per_page, $offset) {
Dries's avatar
 
Dries committed
599
  global $id, $status, $user, $pager_total;
Dries's avatar
 
Dries committed
600 601

  if ($topics) {
602
    $output .= "<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n";
Dries's avatar
 
Dries committed
603 604 605 606
    $output .= " <tr><th>&nbsp;</th><th>&nbsp;</th><th>". t("topic") ."</th><th>". t("replies") ."</th><th>". t("posted") ."</th><th>". t("last reply") ."</th></tr>";

    foreach ($topics as $topic) {
      // folder is new if topic is new or there are new comments since last visit
Dries's avatar
Dries committed
607
      if ($topic->tid != $tid) {
Dries's avatar
 
Dries committed
608 609 610 611
        $output .= "
          <tr>
            <td>"._forum_get_folder_icon($topic->new, $topic->num_comments, $topic->comment_mode)."</td>
            <td>"._forum_get_icon($topic)."</td>
Dries's avatar
 
Dries committed
612 613
            <td style=\"vertical-align: top;\">$topic->title</td>
            <td style=\"text-align: center; vertical-align: top;\" colspan=\"3\">". l(t("This topic has been moved"), "forum/$topic->tid")."</td>
Dries's avatar
 
Dries committed
614 615 616 617 618 619 620
          </tr>";
      }
      else {
        $output .= "
          <tr>
            <td>"._forum_get_folder_icon($topic->new, $topic->num_comments, $topic->comment_mode)."</td>
            <td>"._forum_get_icon($topic)."</td>
Dries's avatar
 
Dries committed
621 622 623 624
            <td style=\"vertical-align: top;\">". l($topic->title, "node/view/$topic->nid") ."</td>
            <td style=\"text-align: center; vertical-align: top;\">".$topic->num_comments.($topic->new_replies ? " (".t("%a new", array("%a" => $topic->new_replies)).")" : "")."</td>
            <td style=\"text-align: center;\">"._forum_format($topic)."</td>
            <td style=\"text-align: center;\">"._forum_format($topic->last_reply)."</td>
Dries's avatar
 
Dries committed
625 626 627 628 629 630
          </tr>";
      }
    }

    $output .= "</table></blockquote>\n";
  }
Dries's avatar
 
Dries committed
631
  $output .= "<hr />";
Dries's avatar
 
Dries committed
632

Dries's avatar
 
Dries committed
633
  $output .= "<div style=\"text-align: center;\">" .t("%a topics, %b topics per page, page %c of %d", array("%a" => $pager_total[0], "%b" => $forum_per_page, "%c" => $offset, "%d" => ceil($pager_total[0]/$forum_per_page))) ."</div>";
Dries's avatar
 
Dries committed
634

Dries's avatar
Dries committed
635
  $output .= (($pager = pager_display(NULL, $forum_per_page, 0, "default")) ? "$pager" : "");
Dries's avatar
 
Dries committed
636

Dries's avatar
Dries committed
637
  if (user_access("create forum topics")) {
Dries's avatar
 
Dries committed
638
    $output .= "<div style=\"text-align: center; font-style: bold;\">". l(t("create new forum topic"), "node/add/forum/$tid") ."</div>";
Dries's avatar
 
Dries committed
639 640 641 642 643 644 645
  }

  return $output;
}


function _forum_get_icon($node) {
Dries's avatar
 
Dries committed
646
  if (variable_get("forum_topic_icon_path", "") && $node->icon) {
Dries's avatar
 
Dries committed
647
    return "<img src=\"". variable_get("forum_topic_icon_path", "") ."$node->icon\" />";
Dries's avatar
 
Dries committed
648 649 650 651 652 653 654 655
  }
  else {
    return "&nbsp;";
  }
}

function _forum_get_folder_icon($new_posts, $num_posts = 0, $comment_mode = 0) {
  // "folder" icon because it's generally rendered as a folder
Dries's avatar
 
Dries committed
656

Dries's avatar
 
Dries committed
657

Dries's avatar
 
Dries committed
658
  $base_path = variable_get("forum_folder_icon_path", "");
Dries's avatar
 
Dries committed
659 660 661 662 663 664 665 666 667 668 669 670
  if ($base_path) {
    if ($num_posts > variable_get("forum_hot_topic", 15)) {
      $icon = $new_posts ? "hot_new" : "hot";
    }
    else {
      $icon = $new_posts ? "new" : "default";
    }

    if ($comment_mode == 1) {
      $icon = "closed";
    }

Dries's avatar
 
Dries committed
671 672
    // default
    $file = $base_path."/".$icon.".gif";
Dries's avatar
 
Dries committed
673

Dries's avatar
 
Dries committed
674
    return "<img src=\"$file\" alt=\"\" title=\"\" />";
Dries's avatar
 
Dries committed
675 676 677 678 679 680 681 682 683 684
  }
  else {
    return "&nbsp;";
  }
}

function _forum_user_last_visit($nid) {
  global $user;
  static $history;
  if (!$history) {
Dries's avatar
 
Dries committed
685
    $result = db_query("SELECT nid, timestamp FROM {history} WHERE uid = %d", $user->uid);
Dries's avatar
 
Dries committed
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
    while ($t = db_fetch_object($result)) {
      $history[$t->nid] = $t->timestamp;
    }
  }
  return $history[$nid] ? $history[$nid] : 0;
}

function _forum_get_topic_order($sortby) {
  switch ($sortby) {
    case 1:
      return "date_sort DESC";
      break;
    case 2:
      return "date_sort ASC";
      break;
    case 3:
      return "num_comments DESC";
      break;
    case 4:
      return "num_comments ASC";
      break;
  }
}

Dries's avatar
 
Dries committed
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
function forum_help($section = "admin/forum/help") {
  $output = "";

  switch ($section) {
    case 'admin/help':
    case 'admin/forum/help':
      $output .= "<h3>Creating a forum</h3>";
      $output .= strtr("<p>The forum module uses taxonomy to organize itself. To create a forum you first have to create a %taxonomy. When doing this, choose a sensible name for it (such as \"fora\") and make sure under \"Types\" that \"forum\" is selected. Once you have done this, %taxo-terms to it. Each term will become a forum. If you fill in the description field, users will be given additonal information about the forum on the main forum page. For example: \"troubleshooting\" - \"Please ask your questions here.\"</p>", array("%taxonomy" => l(t("taxonomy vocabulary"), "admin/taxonomy/add/vocabulary"), "%taxo-terms" => l(t("add some terms"), "admin/taxonomy" ) ));
      $output .= strtr("<p>When you are happy with your vocabulary, go to ". l("site configuration &raquo; modules &raquo; forum","admin/system/modules/forum") ." and set <b>Forum vocabulary</b> to the one you have just created. There will now be fora active on the site. For users to access them they must have the \"access content\" %permission and to create a topic they must have the \"create forum topics\" %permission. These permissions can be set in the %permission pages.</p>", array("%forums" => l(t("site configutation &raquo; modules &raquo; forum"), "admin/system/modules/forum"), "%permission" => l(t("permission"), "admin/user/permission") ));
      $output .= "<h3>Containers</h3><p>If you designate a forum as a <i>container</i>, users will not be able to post to it. The forum will be visible on the forum listing page, so it acts as a section delimiter if you will. This is useful if you have a lots of forums which are nested. For example,</p>";
      $output .= "<p>Marketing<br />-- Market research<br />-- Brand management<br /><br />Sales<br />-- Closing the deal<br />-- Avoiding ear and throat pain</p>";
      $output .= "<p>If you don't want people posting into the Marketing or Sales folders, you designate them as Containers.</p>";
      $output .= "<h4>Icons</h4>";
      $output .= strtr("<p>To disable icons, set the icon path as blank in %forums-icon.</p>",array("%forums-icon" => l(t("site configuration &raquo; modules &raquo; forums"), "admin/system/module/forum") ));
      $output .= "<p>All files in the icon directory are assumed to be images. You may use images of whatever size you wish, but it is customary to use 15x15 or 16x16.</p>";
      break;
    case 'admin/system/modules':
      $output = "Enable threaded discussions about general topics.";
      break;
    case 'admin/system/modules/forum':
      $output = strtr("Forums are threaded discussions based on the taxonomy system so you must first %taxonomy-create of type \"forum\" to place the forum tree in. Then %taxonomy-add to this taxonomy. Each term becomes the name of a forum. If you define a term as a \"Container\" (See below) the term is not a forum itself, but rather holds forms. This lets you group your forums.", array("%taxonomy-create" => l(t("create a taxonomy"), "admin/taxonomy/add/vocabulary"), "%taxonomy" => l(t("add terms"), "admin/taxonomy") ));
      break;
  }
Dries's avatar
 
Dries committed
733

Dries's avatar
 
Dries committed
734
  return t($output);
Dries's avatar
 
Dries committed
735 736 737
}

?>