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
}

?>