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

4
function forum_system($field){
Dries Buytaert's avatar
   
Dries Buytaert 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 Buytaert's avatar
   
Dries Buytaert committed
13
function forum_node($field) {
Dries Buytaert's avatar
   
Dries Buytaert committed
14
  $info["name"] = t("forum topic");
Dries Buytaert's avatar
   
Dries Buytaert 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 Buytaert's avatar
   
Dries Buytaert committed
24
  if ($op == "create") {
Dries Buytaert's avatar
   
Dries Buytaert committed
25
    return user_access("create forum topics");
Dries Buytaert's avatar
   
Dries Buytaert committed
26
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
27
28
}

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

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

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

Dries Buytaert's avatar
   
Dries Buytaert committed
41
    if ($voc) {
42
43
      $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 Buytaert's avatar
   
Dries Buytaert committed
44
      $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 Buytaert's avatar
   
Dries Buytaert committed
45
      $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);
46
      $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 Buytaert's avatar
   
Dries Buytaert committed
47
      $number = array(10 => 10, 25 => 25, 50 => 50, 75 => 75, 100 => 100);
48
49
50
51
      $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 Buytaert's avatar
   
Dries Buytaert committed
52
53
54
55
56
57
58
59
    }
    else {
      $output .= _forum_message_taxonomy();
    }
  }
  else {
    $output .= _forum_message_taxonomy();
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
60

Dries Buytaert's avatar
   
Dries Buytaert committed
61
62
63
  return $output;
}

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

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

  return $forum;
}

79
80
81
82
83
84
function forum_block($op = "list", $delta = 0) {
  if ($op == "list") {
    $blocks[0]["info"] = t("Forum topics");
  }
  else {
    if (user_access("access content")) {
Dries Buytaert's avatar
   
Dries Buytaert committed
85
      $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 Buytaert's avatar
   
Dries Buytaert committed
86

Dries Buytaert's avatar
   
Dries Buytaert committed
87
      $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 Buytaert's avatar
   
Dries Buytaert committed
88

Dries Buytaert's avatar
   
Dries Buytaert committed
89
      if ($content) {
Dries Buytaert's avatar
   
Dries Buytaert committed
90
        $content .= "<div class=\"more-link\">". l(t("more"), "forum", array("title" => t("Read the latest forum topics."))) ."</div>";
Dries Buytaert's avatar
   
Dries Buytaert committed
91
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
92

93
      $blocks["subject"] = t("Forum topics");
Dries Buytaert's avatar
   
Dries Buytaert committed
94
      $blocks["content"] = $content;
Dries Buytaert's avatar
   
Dries Buytaert committed
95
96
    }
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
97

Dries Buytaert's avatar
   
Dries Buytaert committed
98
99
100
  return $blocks;
}

101
function forum_link($type, $node = 0, $main = 0) {
Dries Buytaert's avatar
Dries Buytaert committed
102
  global $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
103

Dries Buytaert's avatar
   
Dries Buytaert committed
104
105
  $links = array();

Dries Buytaert's avatar
   
Dries Buytaert committed
106
  if ($type == "page" && user_access("access content")) {
Dries Buytaert's avatar
   
Dries Buytaert committed
107
    $links[] = l(t("forums"), "forum");
Dries Buytaert's avatar
   
Dries Buytaert committed
108
109
  }

110
  if (!$main && $type == "node" && $node->type == "forum") {
Dries Buytaert's avatar
   
Dries Buytaert committed
111
112
    // get previous and next topic

Dries Buytaert's avatar
   
Dries Buytaert committed
113
    $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 Buytaert's avatar
   
Dries Buytaert committed
114
115
116
117
118
119

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

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

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

Dries Buytaert's avatar
   
Dries Buytaert committed
143
  return $links;
Dries Buytaert's avatar
   
Dries Buytaert committed
144
145
}

Dries Buytaert's avatar
   
Dries Buytaert committed
146
function forum_view($node, $main = 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
147

Dries Buytaert's avatar
   
Dries Buytaert committed
148
149
150
151
152
153
154
  $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);

155
  if (!$main) {
Dries Buytaert's avatar
   
Dries Buytaert committed
156
    $node->title = l($voc->name, "forum") ." &raquo; ". l($term_data->name, "forum/$term_data->tid") ." &raquo; $node->title";
157
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
158

Dries Buytaert's avatar
   
Dries Buytaert committed
159
160
161
  $node->teaser = check_output($node->teaser);
  $node->body = check_output($node->body);

Dries Buytaert's avatar
   
Dries Buytaert committed
162
  theme("node", $node, $main);
Dries Buytaert's avatar
   
Dries Buytaert committed
163
164
}

165
166
167
168
function forum_validate(&$node) {
  // Make sure all fields are set properly:
  $node->icon = $node->icon ? $node->icon : "";
  $node->shadow = $node->shadow ? $node->shadow : 0;
169
  $node->tid = $node->tid ? $node->tid : 0;
170
171
172
173
174
175
  // 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 Buytaert's avatar
Dries Buytaert committed
176
177
178
  }
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
189
190
191
  // outputs the compose guidelines
  $help = variable_get("forum_help", "");

Dries Buytaert's avatar
   
Dries Buytaert committed
192
  $output .= _taxonomy_term_select(t("Forum"), "tid", $tid, variable_get("forum_nav_vocabulary", ""), "", 0, "");
Dries Buytaert's avatar
Dries Buytaert committed
193
194
195
196
197

  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 Buytaert's avatar
   
Dries Buytaert committed
198

199
  $output .= form_textarea(t("Body"), "body", $node->body, 60, 10);
Dries Buytaert's avatar
   
Dries Buytaert committed
200
201
202
203

  return $output;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
204
function forum_insert($node) {
Dries Buytaert's avatar
   
Dries Buytaert committed
205
  db_query("INSERT INTO {forum} (nid, shadow, tid) VALUES (%d, %d, %d)", $node->nid, $node->shadow, $node->tid[0]);
Dries Buytaert's avatar
   
Dries Buytaert committed
206
207
208
}

function forum_update($node) {
Dries Buytaert's avatar
   
Dries Buytaert committed
209
  db_query("UPDATE {forum} SET shadow = %d, tid = %d WHERE nid = %d", $node->shadow, $node->tid[0], $node->nid);
Dries Buytaert's avatar
   
Dries Buytaert committed
210
211
212
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
216
function _forum_num_comments($nid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
217
  $value = db_fetch_object(db_query("SELECT COUNT(cid) AS count FROM {comments} WHERE nid = %d AND status = 0", $nid));
Dries Buytaert's avatar
   
Dries Buytaert committed
218
219
220
  return ($value) ? $value->count : 0;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
221
function _forum_last_comment($nid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
222
  $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 Buytaert's avatar
   
Dries Buytaert committed
223
224
225
  return ($value) ? format_date($value->timestamp, "small") : "&nbsp;";
}

Dries Buytaert's avatar
   
Dries Buytaert committed
226
function _forum_last_reply($nid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
227
  $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 Buytaert's avatar
   
Dries Buytaert committed
228
229
230
231
232
  return $value;
}

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

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

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

Dries Buytaert's avatar
   
Dries Buytaert committed
247
  $cache = cache_get("forum:$tid");
Dries Buytaert's avatar
   
Dries Buytaert committed
248

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

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

  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 Buytaert's avatar
   
Dries Buytaert committed
286

Dries Buytaert's avatar
   
Dries Buytaert committed
287
288
289
290
  return $parents;
}

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

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

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

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

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

function _forum_last_post($term) {
Dries Buytaert's avatar
   
Dries Buytaert committed
311
  $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 Buytaert's avatar
   
Dries Buytaert committed
312

Dries Buytaert's avatar
   
Dries Buytaert committed
313
  $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 Buytaert's avatar
   
Dries Buytaert committed
314
315
316
317
318
319

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

  return $value;
}

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

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

  $sql_sortby = _forum_get_topic_order($sortby);
Dries Buytaert's avatar
   
Dries Buytaert committed
331
332
333
334
335
336
337
338
  for ($i=0; $i < count($forum_topic_list_header); $i++) {
    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 Buytaert's avatar
   
Dries Buytaert committed
339

Dries Buytaert's avatar
Dries Buytaert committed
340
  // show topics with the correct tid, or in the forum but with shadow = 1
Dries Buytaert's avatar
   
Dries Buytaert committed
341
342
  $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 LEFT 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_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";
  $sql .= tablesort_sql($forum_topic_list_header);
Dries Buytaert's avatar
Dries Buytaert committed
343

Dries Buytaert's avatar
   
Dries Buytaert committed
344
  $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 Buytaert's avatar
   
Dries Buytaert committed
345

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

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

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

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

Dries Buytaert's avatar
Dries Buytaert committed
385
  return $topics;
Dries Buytaert's avatar
   
Dries Buytaert committed
386
387
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
395
  $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 Buytaert's avatar
   
Dries Buytaert committed
396
397
398
399

  return $nid ? $nid : 0;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
400
401
402
403
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 Buytaert's avatar
   
Dries Buytaert committed
404
function forum_page() {
Dries Buytaert's avatar
   
Dries Buytaert committed
405
  global $sortby, $forum_per_page, $from, $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
406

Dries Buytaert's avatar
   
Dries Buytaert committed
407
  $op = $_POST["op"];
Dries Buytaert's avatar
   
Dries Buytaert committed
408

Dries Buytaert's avatar
   
Dries Buytaert committed
409
  if (user_access("access content")) {
Dries Buytaert's avatar
   
Dries Buytaert committed
410
    if (module_exist("taxonomy")) {
Dries Buytaert's avatar
   
Dries Buytaert committed
411
      $tid = arg(1);
412
      if ($op == t("Update settings") && $user->uid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
413
414
        $user = user_save($user, array("sortby" => $sortby, "forum_per_page" => $forum_per_page));
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
415

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

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

Dries Buytaert's avatar
   
Dries Buytaert committed
426
427
428
      if (empty($forum_per_page)) {
        $forum_per_page = isset($user->forum_per_page) ? $user->forum_per_page : variable_get("forum_per_page", 25);
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
429

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

Dries Buytaert's avatar
   
Dries Buytaert committed
432
433
      $forums = forum_get_forums($tid);
      $parents = forum_get_parents($tid);
Dries Buytaert's avatar
   
Dries Buytaert committed
434
      $topics = forum_get_topics($tid, $sortby, $forum_per_page);
Dries Buytaert's avatar
   
Dries Buytaert committed
435

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

Dries Buytaert's avatar
   
Dries Buytaert committed
451
/*
Dries Buytaert's avatar
   
Dries Buytaert committed
452
** Theme functions
Dries Buytaert's avatar
   
Dries Buytaert committed
453
*/
Dries Buytaert's avatar
   
Dries Buytaert committed
454

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

Dries Buytaert's avatar
   
Dries Buytaert committed
458
  theme("header");
Dries Buytaert's avatar
   
Dries Buytaert committed
459

Dries Buytaert's avatar
   
Dries Buytaert committed
460
461
462
  /*
  ** Breadcrumb navigation:
  */
Dries Buytaert's avatar
   
Dries Buytaert committed
463

Dries Buytaert's avatar
   
Dries Buytaert committed
464
465
466
467
468
  if ($tid) {
    $trail[] = l(t("Forums"), "forum");
  }
  else {
    $trail[] = t("Forums");
Dries Buytaert's avatar
   
Dries Buytaert committed
469
470
471
  }

  if ($parents) {
Dries Buytaert's avatar
   
Dries Buytaert committed
472
473
    $parents = array_reverse($parents);
    foreach ($parents as $p) {
Dries Buytaert's avatar
   
Dries Buytaert committed
474
      if ($tid != $p->tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
475
        $trail[] = l($p->name, "forum/$p->tid");
Dries Buytaert's avatar
   
Dries Buytaert committed
476
477
      }
      else {
Dries Buytaert's avatar
   
Dries Buytaert committed
478
        $trail[] = $p->name;
Dries Buytaert's avatar
   
Dries Buytaert committed
479
480
481
482
      }
    }
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  $output  = "<div id=\"forum\">";
  $output .= theme("forum_theme_list", $forums, $parents, $tid);

  if ($tid) {
    $output .= theme("forum_theme_topic_list", $tid, $topics, $sortby, $forum_per_page, $offset);
  }

  $output .= "</div>";

  theme("box", implode($trail, " &raquo; "), $output);
  theme("footer");
}

function forum_theme_list($forums, $parents, $tid) {
  global $user;

Dries Buytaert's avatar
   
Dries Buytaert committed
499
500
  if ($forums) {

Dries Buytaert's avatar
   
Dries Buytaert committed
501
    $header = array(t("Forum"), t("Topics"), t("Posts"), t("Last post"));
Dries Buytaert's avatar
   
Dries Buytaert committed
502
503

    foreach ($forums as $forum) {
Dries Buytaert's avatar
   
Dries Buytaert committed
504
505
      if ($user->uid) {
        $new_topics = $forum->num_topics - $forum->old_topics;
506
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
507

Dries Buytaert's avatar
   
Dries Buytaert committed
508
509
510
511
512
      $links = array();

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

Dries Buytaert's avatar
   
Dries Buytaert committed
514
515
      if ($new_topics) {
        $links[] = l(t("the first new topic"), "forum/$forum->tid/new");
Dries Buytaert's avatar
   
Dries Buytaert committed
516
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532

      $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";
      }
      $description .="</div>\n";

      $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 Buytaert's avatar
   
Dries Buytaert committed
533
        array("data" => _forum_format($forum->last_post), "class" => "last-reply")
Dries Buytaert's avatar
   
Dries Buytaert committed
534
535
       );

Dries Buytaert's avatar
   
Dries Buytaert committed
536
537
538
    }
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
539
  return table($header, $rows);
Dries Buytaert's avatar
   
Dries Buytaert committed
540
541
542
}


Dries Buytaert's avatar
   
Dries Buytaert committed
543
function forum_theme_topic_list($tid, $topics, $sortby, $forum_per_page, $offset) {
Dries Buytaert's avatar
   
Dries Buytaert committed
544
  global $id, $status, $user, $pager_total, $forum_topic_list_header;
Dries Buytaert's avatar
   
Dries Buytaert committed
545
546

  if ($topics) {
Dries Buytaert's avatar
   
Dries Buytaert committed
547

Dries Buytaert's avatar
   
Dries Buytaert committed
548
549
    foreach ($topics as $topic) {
      // folder is new if topic is new or there are new comments since last visit
Dries Buytaert's avatar
Dries Buytaert committed
550
      if ($topic->tid != $tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
551
        $rows[] = array(
Dries Buytaert's avatar
   
Dries Buytaert committed
552
          array("data" => _forum_icon($topic->new, $topic->num_comments, $topic->comment_mode), "class" => "icon"),
Dries Buytaert's avatar
   
Dries Buytaert committed
553
          array("data" => $topic->title, "class" => "title"),
Dries Buytaert's avatar
   
Dries Buytaert committed
554
          array("data" => l(t("This topic has been moved"), "forum/$topic->tid"), "colspan" => "3")
Dries Buytaert's avatar
   
Dries Buytaert committed
555
        );
Dries Buytaert's avatar
   
Dries Buytaert committed
556
557
      }
      else {
Dries Buytaert's avatar
   
Dries Buytaert committed
558
        $rows[] = array(
Dries Buytaert's avatar
   
Dries Buytaert committed
559
          array("data" => _forum_icon($topic->new, $topic->num_comments, $topic->comment_mode), "class" => "icon"),
Dries Buytaert's avatar
   
Dries Buytaert committed
560
561
          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 Buytaert's avatar
   
Dries Buytaert committed
562
563
          array("data" => _forum_format($topic), "class" => "created"),
          array("data" => _forum_format($topic->last_reply), "class" => "last-reply")
Dries Buytaert's avatar
   
Dries Buytaert committed
564
        );
Dries Buytaert's avatar
   
Dries Buytaert committed
565
566
567
      }
    }

Dries Buytaert's avatar
   
Dries Buytaert committed
568
    if ($pager = pager_display(NULL, $forum_per_page, 0, "default", tablesort_pager())) {
Dries Buytaert's avatar
   
Dries Buytaert committed
569
      $rows[] = array(array("data" => $pager, "colspan" => "5", "class" => "pager"));
Dries Buytaert's avatar
   
Dries Buytaert committed
570
571
    }
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
572
573


Dries Buytaert's avatar
Dries Buytaert committed
574
  if (user_access("create forum topics")) {
Dries Buytaert's avatar
   
Dries Buytaert committed
575
    $output = l(t("create new forum topic"), "node/add/forum/$tid") ."<br /><br />";
Dries Buytaert's avatar
   
Dries Buytaert committed
576
577
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
578
  $output .= table($forum_topic_list_header, $rows);
Dries Buytaert's avatar
   
Dries Buytaert committed
579

Dries Buytaert's avatar
   
Dries Buytaert committed
580
581
582
  return $output;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
583
function _forum_icon($new_posts, $num_posts = 0, $comment_mode = 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
584

Dries Buytaert's avatar
   
Dries Buytaert committed
585
  $base_path = variable_get("forum_icon_path", "");
Dries Buytaert's avatar
   
Dries Buytaert committed
586
587
  if ($base_path) {
    if ($num_posts > variable_get("forum_hot_topic", 15)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
588
      $icon = $new_posts ? "hot-new" : "hot";
Dries Buytaert's avatar
   
Dries Buytaert committed
589
590
591
592
593
594
595
596
597
    }
    else {
      $icon = $new_posts ? "new" : "default";
    }

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

Dries Buytaert's avatar
   
Dries Buytaert committed
598
    // default
Dries Buytaert's avatar
   
Dries Buytaert committed
599
    $file = $base_path."/forum-$icon.gif";
Dries Buytaert's avatar
   
Dries Buytaert committed
600

Dries Buytaert's avatar
   
Dries Buytaert committed
601
    return "<img src=\"$file\" alt=\"\" title=\"\" />";
Dries Buytaert's avatar
   
Dries Buytaert committed
602
603
604
605
606
607
608
609
610
611
  }
  else {
    return "&nbsp;";
  }
}

function _forum_user_last_visit($nid) {
  global $user;
  static $history;
  if (!$history) {
Dries Buytaert's avatar
   
Dries Buytaert committed
612
    $result = db_query("SELECT nid, timestamp FROM {history} WHERE uid = %d", $user->uid);
Dries Buytaert's avatar
   
Dries Buytaert committed
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
    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 Buytaert's avatar
   
Dries Buytaert committed
637
638
639
640
641
642
643
644
645
646
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 .= "<h4>Icons</h4>";
Dries Buytaert's avatar
   
Dries Buytaert committed
647
648
      $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 recommended to use 15x15 or 16x16.</p>";
Dries Buytaert's avatar
   
Dries Buytaert committed
649
650
651
652
653
654
655
656
      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 Buytaert's avatar
   
Dries Buytaert committed
657

Dries Buytaert's avatar
   
Dries Buytaert committed
658
  return t($output);
Dries Buytaert's avatar
   
Dries Buytaert committed
659
660
661
}

?>