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

function forum_node($field) {
Dries's avatar
 
Dries committed
5
  $info["name"] = t("forum topic");
Dries's avatar
 
Dries committed
6 7 8 9 10 11 12 13 14
  $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
15
  if ($op == "create") {
Dries's avatar
 
Dries committed
16
    return user_access("create forum topics");
Dries's avatar
 
Dries committed
17
  }
Dries's avatar
 
Dries committed
18 19
}

Dries's avatar
 
Dries committed
20
function forum_perm() {
Dries's avatar
 
Dries committed
21
  return array("create forum topics");
Dries's avatar
 
Dries committed
22
}
Dries's avatar
 
Dries committed
23

24
function forum_settings() {
Dries's avatar
 
Dries committed
25

Dries's avatar
 
Dries committed
26
  if (module_exist("taxonomy")) {
Dries's avatar
 
Dries committed
27
    $vocs[0] = "<". t("none") .">";
Dries's avatar
 
Dries committed
28 29 30 31
    foreach (taxonomy_get_vocabularies("forum") as $vid => $voc) {
      $vocs[$vid] = $voc->name;
    }

Dries's avatar
 
Dries committed
32
    if ($voc) {
33 34
      $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."));
Dries's avatar
 
Dries committed
35
      $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
36
      $output .= form_textfield(t("Forum icon path"), "forum_icon_path", variable_get("forum_icon_path", ""), 30, 255, t("The path to the forum icons.  Leave blank to disable icons.  Don't add a trailing slash.  Default icons are available in the 'misc' directory."));
Dries's avatar
 
Dries committed
37
      $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);
38
      $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
39
      $number = array(10 => 10, 25 => 25, 50 => 50, 75 => 75, 100 => 100);
40 41
      $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"));
Dries's avatar
 
Dries committed
42
      $output .= form_radios(t("Default order"), "forum_order", variable_get("forum_order", 1), $forder, t("The default display order for topics."));
43
      $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
44 45
    }
  }
Dries's avatar
 
Dries committed
46

Dries's avatar
 
Dries committed
47 48 49
  return $output;
}

Dries's avatar
Dries committed
50 51
function forum_taxonomy($op, $type, $object) {
  if ($type == "vocabulary" && ($op == "insert" || $op == "update")) {
Dries's avatar
 
Dries committed
52
    if (variable_get("forum_nav_vocabulary", "") == "" && in_array("forum", $object["nodes"])) {
Dries's avatar
Dries committed
53 54 55 56 57 58
      // 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
59
function forum_load($node) {
Dries's avatar
 
Dries committed
60
  $forum = db_fetch_object(db_query("SELECT * FROM {forum} WHERE nid = %d", $node->nid));
Dries's avatar
 
Dries committed
61 62 63 64

  return $forum;
}

65 66 67 68 69 70
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
71
      $content = node_title_list(db_query_range("SELECT n.nid, n.title, GREATEST(n.created, MAX(c.timestamp)) AS sort FROM {node} n LEFT JOIN {comments} c ON n.nid = c.nid WHERE n.type = 'forum' AND n.status = 1 GROUP BY n.nid, n.title, n.created ORDER BY sort DESC", 0, variable_get("forum_block_num", "5")), t("Active forum topics:"));
Dries's avatar
 
Dries committed
72

Dries's avatar
 
Dries committed
73
      $content .= node_title_list(db_query_range("SELECT nid, title FROM {node} WHERE type = 'forum' ORDER BY nid DESC", 0, variable_get("forum_block_num", "5")), t("New forum topics:"));
Dries's avatar
 
Dries committed
74

Dries's avatar
 
Dries committed
75
      if ($content) {
Dries's avatar
 
Dries committed
76
        $content .= "<div class=\"more-link\">". l(t("more"), "forum", array("title" => t("Read the latest forum topics."))) ."</div>";
Dries's avatar
 
Dries committed
77
      }
Dries's avatar
 
Dries committed
78

79
      $blocks["subject"] = t("Forum topics");
Dries's avatar
 
Dries committed
80
      $blocks["content"] = $content;
Dries's avatar
 
Dries committed
81 82
    }
  }
Dries's avatar
 
Dries committed
83

Dries's avatar
 
Dries committed
84 85 86
  return $blocks;
}

87
function forum_link($type, $node = 0, $main = 0) {
Dries's avatar
Dries committed
88
  global $user;
Dries's avatar
 
Dries committed
89

Dries's avatar
 
Dries committed
90 91
  $links = array();

Dries's avatar
 
Dries committed
92
  if ($type == "page" && user_access("access content")) {
Dries's avatar
 
Dries committed
93
    $links[] = l(t("forums"), "forum");
Dries's avatar
 
Dries committed
94 95
  }

Dries's avatar
 
Dries committed
96
  if ($type == "system" && user_access("create forum topics")) {
Dries's avatar
 
Dries committed
97
      menu("node/add/forum",t("forum topic"), "page");
Dries's avatar
 
Dries committed
98 99
  }

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

Dries's avatar
Dries committed
103
    $result = db_query("SELECT n.nid, n.title, 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.created ORDER BY ". _forum_get_topic_order(isset($user->sortby) ? $user->sortby : variable_get("forum_order", 1)), $node->tid);
Dries's avatar
 
Dries committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120

    while ($topic = db_fetch_object($result)) {
      if ($stop == 1) {
        $next->nid = $topic->nid;
        $next->title = $topic->title;
        break;
      }
      if ($topic->nid == $node->nid) {
        $stop = 1;
      }
      else {
        $prev->nid = $topic->nid;
        $prev->title = $topic->title;
      }
    }

    if ($prev) {
Dries's avatar
Dries committed
121
      $links[] = l(t("previous forum topic"), "node/view/$prev->nid", array("title" => $prev->title));
Dries's avatar
 
Dries committed
122 123 124
    }

    if ($next) {
Dries's avatar
Dries committed
125
      $links[] = l(t("next forum topic"), "node/view/$next->nid", array("title" => $next->title));
Dries's avatar
 
Dries committed
126
    }
Dries's avatar
 
Dries committed
127 128
  }

Dries's avatar
 
Dries committed
129
  return $links;
Dries's avatar
 
Dries committed
130 131
}

Dries's avatar
 
Dries committed
132 133 134 135 136 137
function forum_content($node) {
  $node->teaser = check_output($node->teaser);
  $node->body = check_output($node->body);
  return $node;
}

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

Dries's avatar
 
Dries committed
140 141 142 143 144 145 146
  if ($main == 0) {
    $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);
Dries's avatar
 
Dries committed
147 148 149 150 151
    // Breadcrumb navigation
    $breadcrumb[] = l(t("Home"), NULL);
    $breadcrumb[] = l(t("Forums"), "forum");
    $breadcrumb[] = l($term_data->name, "forum/$term_data->tid");
    // print the breadcrumb
Dries's avatar
 
Dries committed
152
    print theme("breadcrumb", $breadcrumb);
153
  }
Dries's avatar
 
Dries committed
154 155 156
  // prepair the node content
  $node = forum_content($node);
  // print the node
Dries's avatar
 
Dries committed
157
  print theme("node", $node, $main);
Dries's avatar
 
Dries committed
158 159
}

160 161 162 163
function forum_validate(&$node) {
  // Make sure all fields are set properly:
  $node->icon = $node->icon ? $node->icon : "";
  $node->shadow = $node->shadow ? $node->shadow : 0;
164
  $node->tid = $node->tid ? $node->tid : 0;
165 166 167 168 169 170
  // 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
171 172 173
  }
}

Dries's avatar
 
Dries committed
174
function forum_form(&$node, &$help, &$error) {
Dries's avatar
Dries committed
175 176 177
  if ($node->tid) {
    // editing
    $tid = $node->tid;
178 179
  }
  else {
Dries's avatar
Dries committed
180 181
    // new topic
    $tid = arg(3);
182 183
  }

Dries's avatar
 
Dries committed
184 185 186
  // outputs the compose guidelines
  $help = variable_get("forum_help", "");

Dries's avatar
 
Dries committed
187
  $output .= _taxonomy_term_select(t("Forum"), "tid", $tid, variable_get("forum_nav_vocabulary", ""), "", 0, "", variable_get("forum_containers", array()));
Dries's avatar
Dries committed
188 189 190 191 192

  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
193

Dries's avatar
Dries committed
194
  $output .= form_textarea(t("Body"), "body", $node->body, 60, 10);
Dries's avatar
 
Dries committed
195 196 197 198

  return $output;
}

Dries's avatar
 
Dries committed
199
function forum_insert($node) {
Dries's avatar
 
Dries committed
200
  db_query("INSERT INTO {forum} (nid, shadow, tid) VALUES (%d, %d, %d)", $node->nid, $node->shadow, $node->tid[0]);
Dries's avatar
 
Dries committed
201 202 203
}

function forum_update($node) {
Dries's avatar
 
Dries committed
204
  db_query("UPDATE {forum} SET shadow = %d, tid = %d WHERE nid = %d", $node->shadow, $node->tid[0], $node->nid);
Dries's avatar
 
Dries committed
205 206 207
}

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

Dries's avatar
 
Dries committed
211
function _forum_num_comments($nid) {
Dries's avatar
 
Dries committed
212
  $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
213 214 215
  return ($value) ? $value->count : 0;
}

Dries's avatar
 
Dries committed
216
function _forum_last_comment($nid) {
Dries's avatar
 
Dries committed
217
  $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
218 219 220
  return ($value) ? format_date($value->timestamp, "small") : "&nbsp;";
}

Dries's avatar
 
Dries committed
221
function _forum_last_reply($nid) {
Dries's avatar
 
Dries committed
222
  $value = db_fetch_object(db_query_range("SELECT c.timestamp, u.name, u.uid FROM {comments} c INNER 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
223 224 225 226 227
  return $value;
}

function _forum_format($topic) {
  if ($topic) {
Dries's avatar
 
Dries committed
228
    return t("%date<br />by %author", array("%date" => format_date($topic->timestamp, "small"), "%author" => format_name($topic)));
Dries's avatar
 
Dries committed
229 230 231 232 233 234 235 236 237 238 239 240 241
  }
  else {
    return message_na();
  }
}

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

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

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

Dries's avatar
 
Dries committed
244
  if (empty($cache)) {
245
    $forums = array();
Dries's avatar
 
Dries committed
246
    $_forums = taxonomy_get_tree(variable_get("forum_nav_vocabulary", ""), $tid);
Dries's avatar
 
Dries committed
247 248
    $n = 0;
    foreach ($_forums as $forum) {
Dries's avatar
 
Dries committed
249 250 251
      if (in_array($forum->tid, variable_get("forum_containers", array()))) {
        $forum->container = 1;
      }
Dries's avatar
 
Dries committed
252 253 254
      $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);
Dries's avatar
 
Dries committed
255 256 257 258
      $forums[$forum->tid] = $forum;
      $n++;
    }

Dries's avatar
 
Dries committed
259
    cache_set("forum:$tid", serialize($forums), 1);
Dries's avatar
 
Dries committed
260
  }
Dries's avatar
 
Dries committed
261 262 263
  else {
    $forums = unserialize($cache->data);
  }
Dries's avatar
 
Dries committed
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

  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
284

Dries's avatar
 
Dries committed
285 286 287 288
  return $parents;
}

function _forum_num_topics($term) {
Dries's avatar
 
Dries committed
289
  $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
290 291 292 293
  return ($value) ? $value->count : 0;
}

function _forum_num_replies($term) {
Dries's avatar
 
Dries committed
294
  $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
295 296 297 298
  return ($value) ? $value->count : 0;
}

function _forum_topics_read($uid) {
Dries's avatar
 
Dries committed
299
  $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
300 301 302 303 304 305 306 307 308

  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
309
  $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 INNER 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
310

Dries's avatar
 
Dries committed
311
  $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 INNER 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
312 313 314 315 316 317

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

  return $value;
}

Dries's avatar
Dries committed
318
function forum_get_topics($tid, $sortby, $forum_per_page) {
Dries's avatar
 
Dries committed
319
  global $user, $forum_topic_list_header;
Dries's avatar
 
Dries committed
320

Dries's avatar
 
Dries committed
321
  $forum_topic_list_header = array(
Dries's avatar
Dries committed
322 323
      array("data" => "&nbsp;"),
      array("data" => t("Topic"), "field" => "n.title"),
Dries's avatar
 
Dries committed
324
      array("data" => t("Replies"), "field" => "num_comments"),
Dries's avatar
 
Dries committed
325 326 327
      array("data" => t("Created"), "field" => "n.created"),
      array("data" => t("Last reply"), "field" => "date_sort", "sort" => "desc"),
  );
Dries's avatar
 
Dries committed
328 329

  $sql_sortby = _forum_get_topic_order($sortby);
Dries's avatar
 
Dries committed
330
  for ($i = 0; $i < count($forum_topic_list_header); $i++) {
Dries's avatar
 
Dries committed
331 332 333 334 335 336 337
    if ($forum_topic_list_header[$i]["field"] == $sql_sortby) {
      $forum_topic_list_header[$i]["order"] = $sql_sortby;
    }
  }

  $term = taxonomy_get_term($tid);
  $voc = taxonomy_get_vocabulary($term->vid);
Dries's avatar
Dries committed
338
  $check_tid = $tid ? "'". check_query($tid). "'" : "NULL";
Dries's avatar
 
Dries committed
339

Dries's avatar
Dries committed
340
  // show topics with the correct tid, or in the forum but with shadow = 1
Dries's avatar
 
Dries committed
341 342
  // @TODO: this is not ANSI SQL! ("user error: 'n.created' isn't in GROUP BY")
  // @TODO: timestamp is a sql reserved word. are there more?
Dries's avatar
Dries committed
343
  $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, n.comment AS comment_mode, f.tid FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid LEFT 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_tid AND f.shadow = 1) OR f.tid = $check_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";
Dries's avatar
 
Dries committed
344
  $sql .= tablesort_sql($forum_topic_list_header);
Dries's avatar
Dries committed
345

Dries's avatar
Dries committed
346
  $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_tid AND f.shadow = 1) OR f.tid = $check_tid) AND n.status = 1 AND n.type = 'forum'";
Dries's avatar
 
Dries committed
347

Dries's avatar
Dries committed
348
  $result = pager_query($sql, $forum_per_page, 0, $sql_count);
Dries's avatar
 
Dries committed
349 350 351 352
  $topic_num = db_num_rows($result);

  $n = 0;
  while ($topic = db_fetch_object($result)) {
Dries's avatar
Dries committed
353 354 355 356 357
    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
358 359
      }
      else {
Dries's avatar
Dries committed
360 361
        if (!$history && $user->uid) {
          $topic->new_replies = 0;
Dries's avatar
 
Dries committed
362 363 364
          $topic->new = 1;
        }
        else {
Dries's avatar
 
Dries committed
365
          $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
366 367 368 369 370 371 372 373

          $topic->new_replies = $comments ? $comments : 0;
          if ($topic->new_replies) {
            $topic->new = 1;
          }
          else {
            $topic->new = 0;
          }
Dries's avatar
 
Dries committed
374 375
        }
      }
Dries's avatar
Dries committed
376 377 378 379 380 381
     }
     else {
      // you're not logged in eh?
      $topic->new_replies = 0;
      $topic->new = 0;
     }
Dries's avatar
 
Dries committed
382 383 384 385 386

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

Dries's avatar
Dries committed
387
  return $topics;
Dries's avatar
 
Dries committed
388 389
}

Dries's avatar
Dries committed
390
function _forum_new($tid) {
Dries's avatar
 
Dries committed
391
  global $user;
Dries's avatar
 
Dries committed
392
  $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
393 394 395 396
  while ($r = db_fetch_object($result)) {
    $read[] = $r->nid;
  }

Dries's avatar
 
Dries committed
397
  $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
398 399 400 401

  return $nid ? $nid : 0;
}

Dries's avatar
 
Dries committed
402
function _forum_message_taxonomy() {
Dries's avatar
 
Dries committed
403
  return t("Forums are threaded discussions based on the taxonomy system.  For the forums to work, the taxonomy module has to be installed and enabled.  When activated, a taxonomy vocabulary (eg. \"forums\") needs to be %created and bound to the node type \"forum topic\".  The vocabulary's %terms define the forums.  If you define a term as a \"Container\", the term is not a forum itself, but rather holds forums.  This lets you group your forums.", array('%created' => l(t('created'), 'admin/taxonomy/add/vocabulary'), '%terms' => l(t('terms'), 'admin/taxonomy', array('title' => t('add terms')))));
Dries's avatar
 
Dries committed
404 405
}

Dries's avatar
 
Dries committed
406
function forum_page() {
Dries's avatar
 
Dries committed
407
  global $sortby, $forum_per_page, $from, $user;
Dries's avatar
 
Dries committed
408

Dries's avatar
 
Dries committed
409
  $op = $_POST["op"];
Dries's avatar
 
Dries committed
410

Dries's avatar
 
Dries committed
411
  if (user_access("access content")) {
Dries's avatar
 
Dries committed
412
    if (module_exist("taxonomy")) {
Dries's avatar
 
Dries committed
413
      $tid = arg(1);
Dries's avatar
 
Dries committed
414

Dries's avatar
Dries committed
415 416 417 418 419
      if (arg(2) == "new") {
        if ($nid = _forum_new($tid)) {
          drupal_goto(url("node/view/$nid"));
        }
      }
Dries's avatar
 
Dries committed
420

Dries's avatar
 
Dries committed
421
      if (empty($sortby)) {
Dries's avatar
 
Dries committed
422
        $sortby = isset($user->sortby) ? $user->sortby : variable_get("forum_order", 1);
Dries's avatar
 
Dries committed
423
      }
Dries's avatar
 
Dries committed
424

Dries's avatar
 
Dries committed
425 426 427
      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
428

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

Dries's avatar
 
Dries committed
431 432
      $forums = forum_get_forums($tid);
      $parents = forum_get_parents($tid);
Dries's avatar
 
Dries committed
433 434 435
      if ($tid && !in_array($tid, variable_get("forum_containers", array()))) {
        $topics = forum_get_topics($tid, $sortby, $forum_per_page);
      }
Dries's avatar
 
Dries committed
436

Dries's avatar
 
Dries committed
437
      print theme("forum_display", $forums, $topics, $parents, $tid, $sortby, $forum_per_page, $offset);
Dries's avatar
 
Dries committed
438 439
    }
    else {
Dries's avatar
 
Dries committed
440
      $message = t("Warning");
Dries's avatar
 
Dries committed
441 442 443
      print theme("header", $message);
      print theme("box", $message, _forum_message_taxonomy());
      print theme("footer");
Dries's avatar
 
Dries committed
444
    }
Dries's avatar
 
Dries committed
445 446
  }
  else {
Dries's avatar
 
Dries committed
447
    $message = t("Access denied");
Dries's avatar
 
Dries committed
448 449 450
    print theme("header", $message);
    print theme("box", $message, message_access());
    print theme("footer");
Dries's avatar
 
Dries committed
451 452 453
  }
}

Dries's avatar
 
Dries committed
454 455
/**
  @addtogroup theme_system
Dries's avatar
 
Dries committed
456

Dries's avatar
 
Dries committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
  Forum module specific theme functions.
  @{
**/

/**
 Controls the output of the forum body.

 @param forums
 @param topics
 @param parents
 @param tid
 @param sortby
 @param forum_per_page
 @param offset

 @return string the output for the forum body.
**/
function theme_forum_display($forums, $topics, $parents, $tid, $sortby, $forum_per_page, $offset) {
Dries's avatar
 
Dries committed
475
  // forum list, topics list, topic browser and "add new topic" link
Dries's avatar
 
Dries committed
476

Dries's avatar
 
Dries committed
477
  $title = t("Forums");
Dries's avatar
 
Dries committed
478

Dries's avatar
 
Dries committed
479 480 481
  /*
  ** Breadcrumb navigation:
  */
Dries's avatar
 
Dries committed
482
  $breadcrumb[] = l(t("Home"), "");
Dries's avatar
 
Dries committed
483
  $breadcrumb[] = l($title, "forum");
Dries's avatar
 
Dries committed
484 485

  if ($parents) {
Dries's avatar
 
Dries committed
486 487
    $parents = array_reverse($parents);
    foreach ($parents as $p) {
488 489
      if ($p->tid == $tid) {
        $title = $p->name;
Dries's avatar
 
Dries committed
490 491
      }
      else {
Dries's avatar
 
Dries committed
492
        $breadcrumb[] = l($p->name, "forum/$p->tid");
Dries's avatar
 
Dries committed
493 494 495 496
      }
    }
  }

Dries's avatar
 
Dries committed
497 498
  if (count($forums) || count($parents)) {
    $output  = "<div id=\"forum\">";
Dries's avatar
 
Dries committed
499
    $output .= theme("forum_list", $forums, $parents, $tid);
Dries's avatar
 
Dries committed
500

Dries's avatar
 
Dries committed
501
    if ($tid && !in_array($tid, variable_get("forum_containers", array()))) {
Dries's avatar
 
Dries committed
502
      $output .= theme("forum_topic_list", $tid, $topics, $sortby, $forum_per_page, $offset);
Dries's avatar
 
Dries committed
503 504 505 506 507 508
    }
    $output .= "</div>";
  }
  else {
    $title = t("No forums defined");
    $output = '';
Dries's avatar
 
Dries committed
509 510
  }

Dries's avatar
 
Dries committed
511 512 513 514
  print theme("header", $title);
  print theme("breadcrumb", $breadcrumb);
  print theme("box", $title, $output);
  print theme("footer");
Dries's avatar
 
Dries committed
515 516
}

Dries's avatar
 
Dries committed
517 518 519 520 521 522 523 524 525 526
/**
 Outputs the forum listing.

 @param forums
 @param parents
 @param tid

 @return string the output for the forum listing.
**/
function theme_forum_list($forums, $parents, $tid) {
Dries's avatar
 
Dries committed
527 528
  global $user;

Dries's avatar
 
Dries committed
529 530
  if ($forums) {

Dries's avatar
 
Dries committed
531
    $header = array(t("Forum"), t("Topics"), t("Posts"), t("Last post"));
Dries's avatar
 
Dries committed
532 533

    foreach ($forums as $forum) {
Dries's avatar
 
Dries committed
534 535 536 537
      if ($forum->container) {
        $forum->num_topics = "";
        $forum->num_posts = "";
        $forum->last_post = "";
538
      }
Dries's avatar
 
Dries committed
539 540 541 542
      else {
        if ($user->uid) {
          $new_topics = $forum->num_topics - $forum->old_topics;
        }
Dries's avatar
 
Dries committed
543

Dries's avatar
 
Dries committed
544
        $links = array();
Dries's avatar
 
Dries committed
545

Dries's avatar
 
Dries committed
546 547 548
        if ($forum->last_post) {
          $links[] = l(t("the most recent topic"), "node/view/". $forum->last_post->nid);
        }
Dries's avatar
 
Dries committed
549

Dries's avatar
 
Dries committed
550 551 552
        if ($new_topics) {
          $links[] = l(t("the first new topic"), "forum/$forum->tid/new");
        }
Dries's avatar
 
Dries committed
553
      }
Dries's avatar
 
Dries committed
554 555 556 557 558 559 560 561 562 563

      $description  = "<div class=\"forum\" 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\">$forum->description</div>\n";
      }
      if ($links) {
        $description .= " <div class=\"navigation\">". t("Jump to: %links", array("%links" => implode(", ", $links))) .".</div>\n";
      }
Dries's avatar
 
Dries committed
564
      $description .= "</div>\n";
Dries's avatar
 
Dries committed
565 566 567 568 569

      $rows[] = array(
        array("data" => $description, "class" => "description"),
        array("data" => $forum->num_topics . ($new_topics ? "<br />(".t("%a new", array("%a" => $new_topics)).")" : ""), "class" => "topics"),
        array("data" => $forum->num_posts, "class" => "posts"),
Dries's avatar
 
Dries committed
570 571
        array("data" => ($forum->container ? "" : _forum_format($forum->last_post)), "class" => "last-reply")

Dries's avatar
 
Dries committed
572 573
       );

Dries's avatar
 
Dries committed
574 575 576
    }
  }

Dries's avatar
 
Dries committed
577
  return theme("table", $header, $rows);
Dries's avatar
 
Dries committed
578 579
}

Dries's avatar
 
Dries committed
580 581 582 583 584 585 586 587
/**
 Outputs the topic listing.

 @param tid
 @param topics
 @param sortby
 @param forum_per_page
 @param offset
Dries's avatar
 
Dries committed
588

Dries's avatar
 
Dries committed
589 590 591
 @return string the output for the topic list.
**/
function theme_forum_topic_list($tid, $topics, $sortby, $forum_per_page, $offset) {
Dries's avatar
 
Dries committed
592
  global $id, $status, $user, $pager_total, $forum_topic_list_header;
Dries's avatar
 
Dries committed
593 594

  if ($topics) {
Dries's avatar
 
Dries committed
595

Dries's avatar
 
Dries committed
596 597
    foreach ($topics as $topic) {
      // folder is new if topic is new or there are new comments since last visit
Dries's avatar
Dries committed
598
      if ($topic->tid != $tid) {
Dries's avatar
 
Dries committed
599
        $rows[] = array(
Dries's avatar
 
Dries committed
600
          array("data" => _forum_icon($topic->new, $topic->num_comments, $topic->comment_mode), "class" => "icon"),
Dries's avatar
 
Dries committed
601
          array("data" => $topic->title, "class" => "title"),
Dries's avatar
 
Dries committed
602
          array("data" => l(t("This topic has been moved"), "forum/$topic->tid"), "colspan" => "3")
Dries's avatar
 
Dries committed
603
        );
Dries's avatar
 
Dries committed
604 605
      }
      else {
Dries's avatar
 
Dries committed
606
        $rows[] = array(
Dries's avatar
 
Dries committed
607
          array("data" => _forum_icon($topic->new, $topic->num_comments, $topic->comment_mode), "class" => "icon"),
Dries's avatar
 
Dries committed
608 609
          array("data" => l($topic->title, "node/view/$topic->nid"), "class" => "topic"),
          array("data" => $topic->num_comments . ($topic->new_replies ? "<br />(".t("%a new", array("%a" => $topic->new_replies)).")" : ""), "class" => "replies"),
Dries's avatar
 
Dries committed
610 611
          array("data" => _forum_format($topic), "class" => "created"),
          array("data" => _forum_format($topic->last_reply), "class" => "last-reply")
Dries's avatar
 
Dries committed
612
        );
Dries's avatar
 
Dries committed
613 614 615
      }
    }

Dries's avatar
 
Dries committed
616
    if ($pager = pager_display(NULL, $forum_per_page, 0, "default", tablesort_pager())) {
Dries's avatar
 
Dries committed
617
      $rows[] = array(array("data" => $pager, "colspan" => "5", "class" => "pager"));
Dries's avatar
 
Dries committed
618 619
    }
  }
Dries's avatar
 
Dries committed
620 621


Dries's avatar
Dries committed
622
  if (user_access("create forum topics")) {
Dries's avatar
 
Dries committed
623
    $output = l(t("create new forum topic"), "node/add/forum/$tid") ."<br /><br />";
Dries's avatar
 
Dries committed
624 625
  }

Dries's avatar
 
Dries committed
626
  $output .= theme("table", $forum_topic_list_header, $rows);
Dries's avatar
 
Dries committed
627

Dries's avatar
 
Dries committed
628 629 630
  return $output;
}

Dries's avatar
 
Dries committed
631 632
/**  @} End of addtogroup theme_system **/

Dries's avatar
 
Dries committed
633
function _forum_icon($new_posts, $num_posts = 0, $comment_mode = 0) {
Dries's avatar
 
Dries committed
634

Dries's avatar
 
Dries committed
635
  $base_path = variable_get("forum_icon_path", "");
Dries's avatar
 
Dries committed
636 637
  if ($base_path) {
    if ($num_posts > variable_get("forum_hot_topic", 15)) {
Dries's avatar
 
Dries committed
638
      $icon = $new_posts ? "hot-new" : "hot";
Dries's avatar
 
Dries committed
639 640 641 642 643 644 645 646 647
    }
    else {
      $icon = $new_posts ? "new" : "default";
    }

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

Dries's avatar
 
Dries committed
648
    // default
Dries's avatar
 
Dries committed
649
    $file = $base_path ."/forum-$icon.gif";
Dries's avatar
 
Dries committed
650

Dries's avatar
 
Dries committed
651
    return "<img src=\"$file\" alt=\"\" title=\"\" />";
Dries's avatar
 
Dries committed
652 653 654 655 656 657 658 659 660 661
  }
  else {
    return "&nbsp;";
  }
}

function _forum_user_last_visit($nid) {
  global $user;
  static $history;
  if (!$history) {
Dries's avatar
 
Dries committed
662
    $result = db_query("SELECT nid, timestamp FROM {history} WHERE uid = %d", $user->uid);
Dries's avatar
 
Dries committed
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
    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
687
function forum_help($section = "admin/help#forum") {
Dries's avatar
 
Dries committed
688 689 690
  $output = "";

  switch ($section) {
Dries's avatar
 
Dries committed
691
    case 'admin/help#forum':
Dries's avatar
 
Dries committed
692
      $output .= "<h3>Creating a forum</h3>";
Dries's avatar
 
Dries committed
693
      $output .= "<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>";
Dries's avatar
 
Dries committed
694
      $output .= "<p>When you are happy with your vocabulary, go to %forums 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>";
Dries's avatar
 
Dries committed
695
      $output .= "<h4>Icons</h4>";
Dries's avatar
 
Dries committed
696
      $output .= "<p>To disable icons, set the icon path as blank in %forums.</p>";
Dries's avatar
 
Dries committed
697
      $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 recommended to use 15x15 or 16x16.</p>";
Dries's avatar
 
Dries committed
698
      $output = t($output, array("%taxonomy" => l(t("taxonomy vocabulary"), "admin/taxonomy/add/vocabulary"), "%taxo-terms" => l(t("add some terms"), "admin/taxonomy"), "%forums" => l(t("administer") ." &raquo; ". t("configutation") ." &raquo; ". t("modules") ." &raquo; ". t("forum"), "admin/system/modules/forum"), "%permission" => l(t("permission"), "admin/user/permission")));
Dries's avatar
 
Dries committed
699
      break;
Dries's avatar
 
Dries committed
700
    case 'admin/system/modules#description':
Dries's avatar
 
Dries committed
701
      $output = t("Enable threaded discussions about general topics.");
Dries's avatar
 
Dries committed
702 703
      break;
    case 'admin/system/modules/forum':
Dries's avatar
 
Dries committed
704
      $output = _forum_message_taxonomy();
Dries's avatar
 
Dries committed
705 706
      break;
  }
Dries's avatar
 
Dries committed
707

Dries's avatar
 
Dries committed
708
  return $output;
Dries's avatar
 
Dries committed
709 710 711
}

?>