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

Dries Buytaert's avatar
   
Dries Buytaert committed
4
5
6
7
8
/**
 * @file
 * Enable threaded discussions about general topics.
 */

9
10
11
12
/**
 * Implementation of hook_help().
 */
function forum_help($section) {
Dries Buytaert's avatar
   
Dries Buytaert committed
13
  switch ($section) {
14
    case 'admin/forum':
15
      return t('<p>This is a list of existing containers and forums that you can edit. Containers hold forums and, in turn, forums hold threaded discussions. Both containers and forums can be placed inside other containers and forums. By planning the structure of your containers and forums well, you make it easier for users to find a topic area of interest to them.</p>');
16
    case 'admin/forum/add/container':
17
      return t('<p>Containers help you organize your forums. The job of a container is to hold, or contain, other forums that are related. For example, a container named "Food" might hold two forums named "Fruit" and "Vegetables".</p>');
18
    case 'admin/forum/add/forum':
19
      return t('<p>A forum holds discussion topics that are related. For example, a forum named "Fruit" might contain topics titled "Apples" and "Bananas".</p>');
Dries Buytaert's avatar
   
Dries Buytaert committed
20
    case 'admin/modules#description':
21
      return t('Enables threaded discussions about general topics.');
22
23
    case 'admin/forum/configure':
      return t('This is where you can configure system-wide options for how your forums act and display.');
Dries Buytaert's avatar
   
Dries Buytaert committed
24
    case 'node/add#forum':
25
      return t('Create a new topic for discussion in the forums.');
Dries Buytaert's avatar
   
Dries Buytaert committed
26
27
28
  }
}

29
30
31
/**
 * Implementation of hook_node_name().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
32
function forum_node_name($node) {
Dries Buytaert's avatar
   
Dries Buytaert committed
33
  return t('forum topic');
Dries Buytaert's avatar
   
Dries Buytaert committed
34
35
}

36
37
38
/**
 * Implementation of hook_access().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
39
function forum_access($op, $node) {
Dries Buytaert's avatar
   
Dries Buytaert committed
40
41
  global $user;

Dries Buytaert's avatar
   
Dries Buytaert committed
42
43
  if ($op == 'create') {
    return user_access('create forum topics');
Dries Buytaert's avatar
   
Dries Buytaert committed
44
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
45
46
47
48
49
50

  if ($op == 'update' || $op == 'delete') {
    if (user_access('edit own forum topics') && ($user->uid == $node->uid)) {
      return TRUE;
    }
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
51
52
}

53
54
55
/**
 * Implementation of hook_perm().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
56
function forum_perm() {
57
  return array('create forum topics', 'edit own forum topics', 'administer forums');
Dries Buytaert's avatar
   
Dries Buytaert committed
58
}
Dries Buytaert's avatar
   
Dries Buytaert committed
59

60
/**
61
 * Administration page which allows maintaining forums
62
 */
63
64
65
66
67
68
69
function forum_admin() {
  $op = $_POST['op'];
  $edit = $_POST['edit'];

  if (empty($op)) {
    $op = arg(2);
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  switch ($op) {
    case 'add':
      if (arg(3) == 'forum') {
        $output = forum_form_forum();
      }
      else if (arg(3) == 'container') {
        $output = forum_form_container();
      }
      break;
    case 'edit':
      if (arg(3) == 'forum') {
        $output = forum_form_forum(object2array(taxonomy_get_term(arg(4))));
      }
      else if (arg(3) == 'container') {
         $output = forum_form_container(object2array(taxonomy_get_term(arg(4))));
      }
      break;
    case t('Delete'):
      if (!$edit['confirm']) {
90
        $output = _forum_confirm_delete($edit['tid']);
91
92
93
94
95
96
        break;
      }
      else {
        $edit['name'] = 0;
      }
    case t('Submit'):
97
      $status = taxonomy_save_term($edit);
98
99
100
101
      if (arg(3) == 'container') {
        $containers = variable_get('forum_containers', array());
        $containers[] = $edit['tid'];
        variable_set('forum_containers', $containers);
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
        if ($status == SAVED_NEW) {
          drupal_set_message(t('Created new forum container %term.', array('%term' => theme('placeholder', $edit['name']))));
        }
        else {
          drupal_set_message(t('The forum container %term has been updated.', array('%term' => theme('placeholder', $edit['name']))));
        }
      }
      else {
        if ($status == SAVED_NEW) {
          drupal_set_message(t('Created new forum %term.', array('%term' => theme('placeholder', $edit['name']))));
        }
        else {
          drupal_set_message(t('The forum %term has been updated.', array('%term' => theme('placeholder', $edit['name']))));
        }
      }
117
118
119
120
121
      drupal_goto('admin/forum');
    default:
      $output = forum_overview();
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
122
  return $output;
123
124
125
126
127
128
129
}

/**
 * Implementation of hook_taxonomy().
 */
function forum_taxonomy($op, $type, $object) {
  if ($op == 'delete' && $type == 'term' && $object->vid == _forum_get_vid())  {
Dries Buytaert's avatar
Dries Buytaert committed
130
    $results = db_query('SELECT f.nid FROM {forum} f WHERE f.tid = %d', $object->tid);
131
132
133
134
    while ($node = db_fetch_object($results)) {
      $edit['nid'] = $node->nid;
      $edit['confirm'] = TRUE;
      node_delete($edit);
Dries Buytaert's avatar
   
Dries Buytaert committed
135
    }
136
137
  }
}
Dries Buytaert's avatar
   
Dries Buytaert committed
138

139
140
141
142
143
/**
 * Returns a confirmation page for deleting a forum taxonomy term
 *
 * @param $tid ID of the term to be deleted
 */
144
function _forum_confirm_delete($tid) {
145
146
147
148
  $term = taxonomy_get_term($tid);

  $extra = form_hidden('tid', $tid);
  $output = theme('confirm',
Steven Wittens's avatar
Steven Wittens committed
149
                  t('Are you sure you want to delete the forum %name?', array('%name' => theme('placeholder', $term->name))),
150
151
152
153
154
                  'admin/forums',
                  t('Deleting a forum or container will delete all sub-forums as well. This action cannot be undone.'),
                  t('Delete'),
                  t('Cancel'),
                  $extra);
155
  return $output;
156
157
158
159
160
161
162
163
}

/**
 * Returns a form for adding a container to the forum vocabulary
 *
 * @param $edit Associative array containing a container term to be added or edited.
 */
function forum_form_container($edit = array()) {
164
165
  $form = form_textfield(t('Container name'), 'name', $edit['name'], 50, 64, t('The container name is used to identify related forums.'), NULL, TRUE);
  $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('The container description can give users more information about the forums it contains.'));
166

167
168
  $form .= _forum_parent_select($edit['tid'], t('Parent'), 'parent][', 'container');
  $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('When listing containers, those with with light (small) weights get listed before containers with heavier (larger) weights. Containers with equal weights are sorted alphabetically.'));
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

  $form .= form_hidden('vid', _forum_get_vid());
  $form .= form_submit(t('Submit'));
  if ($edit['tid']) {
    $form .= form_submit(t('Delete'));
    $form .= form_hidden('tid', $edit['tid']);
  }

  return form($form);
}

/**
 * Returns a form for adding a forum to the forum vocabulary
 *
 * @param $edit Associative array containing a forum term to be added or edited.
 */
function forum_form_forum($edit = array()) {
186
187
  $form = form_textfield(t('Forum name'), 'name', $edit['name'], 50, 64, t('The forum name is used to identify related topic discussions.'), NULL, TRUE);
  $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('The forum description can give users more information about the discussion topics it contains.'));
188

189
190
  $form .= _forum_parent_select($edit['tid'], t('Parent'), 'parent][', 'forum');
  $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('When listing forums, those with light (small) weights get listed before forums with heavier (larger) weights. Forums with equal weights are sorted alphabetically.'));
191
192
193
194
195
196
197

  $form .= form_hidden('vid', _forum_get_vid());
  $form .= form_submit(t('Submit'));
  if ($edit['tid']) {
    $form .= form_submit(t('Delete'));
    $form .= form_hidden('tid', $edit['tid']);
  }
198

199
200
201
202
203
204
205
206
207
208
  return form($form);
}

/**
 * Returns a select box for available parent terms
 *
 * @param $tid ID of the term which is being added or edited
 * @param $title Title to display the select box with
 * @param $name Name to use in the forum
 */
209
function _forum_parent_select($tid, $title, $name, $child_type) {
210
211

  $parents = taxonomy_get_parents($tid);
212
213
214
215
216
217
218
219
  if ($parents) {
    $parent = array_shift($parents);
    $parent = $parent->tid;
  }
  else {
    $parent = 0;
  }

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  $children = taxonomy_get_tree(_forum_get_vid, $tid);

  // A term can't be the child of itself, nor of its children.
  foreach ($children as $child) {
    $exclude[] = $child->tid;
  }
  $exclude[] = $tid;

  $tree = taxonomy_get_tree(_forum_get_vid());
  $options[0] = '<'. t('root') .'>';
  if ($tree) {
    foreach ($tree as $term) {
      if (!in_array($term->tid, $exclude)) {
        $options[$term->tid] = _forum_depth($term->depth).$term->name;
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
235
236
    }
  }
237
238
239
240
241
242
  if ($child_type == 'container') {
    $description = t('Containers are usually placed at the top (root) level of your forum but you can also place a container inside a parent container or forum.');
  }
  else if ($child_type == 'forum') {
    $description = t('You may place your forum inside a parent container or forum, or at the top (root) level of your forum.');
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
243

244
  return form_select($title, $name, $parent, $options, $description, 0, FALSE, TRUE);
Dries Buytaert's avatar
   
Dries Buytaert committed
245
246
}

247
/**
248
 * Returns an overview list of existing forums and containers
249
 */
250
251
252
253
254
255
256
function forum_overview() {
  $header = array(t('Name'), t('Operations'));

  $tree = taxonomy_get_tree(_forum_get_vid());
  if ($tree) {
    foreach ($tree as $term) {
      if (in_array($term->tid, variable_get('forum_containers', array()))) {
257
        $rows[] = array(_forum_depth($term->depth) .' '. check_plain($term->name), l(t('edit container'), "admin/forum/edit/container/$term->tid"));
258
259
      }
      else {
260
        $rows[] = array(_forum_depth($term->depth) .' '. check_plain($term->name), l(t('edit forum'), "admin/forum/edit/forum/$term->tid"));
261
262
       }

Dries Buytaert's avatar
Dries Buytaert committed
263
264
    }
  }
265
  else {
266
    $rows[] = array(array('data' => t('There are no containers or forums.'), 'colspan' => 2));
267
268
  }
  return theme('table', $header, $rows);
Dries Buytaert's avatar
Dries Buytaert committed
269
270
}

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/**
 * Helper function used to generate indentation for forum list
 *
 * @param $depth Depth of the indentation
 * @param $graphic HTML text to be repeated for each stage of depth
 */
function _forum_depth($depth, $graphic = '--') {
  for ($n = 0; $n < $depth; $n++) {
    $result .= $graphic;
  }
  return $result;
}

/**
 * Returns the vocabulary id for forum navigation.
 */
function _forum_get_vid() {
  $vid = variable_get('forum_nav_vocabulary', '');
  if (empty($vid)) {
    // Check to see if a forum vocabulary exists
    $vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module='%s'", 'forum'));
    if (!$vid) {
293
      $vocabulary = taxonomy_save_vocabulary(array('name' => 'Forums', 'multiple' => 0, 'required' => 1, 'hierarchy' => 1, 'relations' => 0, 'module' => 'forum', 'nodes' => array('forum')));
294
295
296
297
298
299
300
301
302
303
304
      $vid = $vocabulary['vid'];
    }
    variable_set('forum_nav_vocabulary', $vid);
  }

  return $vid;
}

/**
 * Implementation of hook_settings
 */
305
306
307
function forum_admin_configure() {
  system_settings_save();

308
309
310
311
312
313
314
315
  $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. You may use images of whatever size you wish, but it is recommended to use 15x15 or 16x16. '));
  $number = drupal_map_assoc(array(5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100, 10000));
  $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 hot.'));
  $number = drupal_map_assoc(array(10, 25, 50, 75, 100));
  $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_radios(t('Default order'), 'forum_order', variable_get('forum_order', '1'), $forder, t('The default display order for topics.'));

Dries Buytaert's avatar
   
Dries Buytaert committed
316
  return system_settings_form($output);
317
318
}

319
320
321
/**
 * Implementation of hook_load().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
322
function forum_load($node) {
Dries Buytaert's avatar
   
Dries Buytaert committed
323
  $forum = db_fetch_object(db_query('SELECT * FROM {forum} WHERE nid = %d', $node->nid));
Dries Buytaert's avatar
   
Dries Buytaert committed
324
325
326
327

  return $forum;
}

328
329
330
331
332
333
/**
 * Implementation of hook_block().
 *
 * Generates a block containing the currently active forum topics and the
 * most recently added forum topics.
 */
334
335
336
function forum_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
Dries Buytaert's avatar
   
Dries Buytaert committed
337
338
      $blocks[0]['info'] = t('Active forum topics');
      $blocks[1]['info'] = t('New forum topics');
339
      return $blocks;
Dries Buytaert's avatar
   
Dries Buytaert committed
340

341
    case 'configure':
342
      $output = form_select(t('Number of topics'), 'forum_block_num_'. $delta, variable_get('forum_block_num_'. $delta, '5'), drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)));
343
      return $output;
Dries Buytaert's avatar
   
Dries Buytaert committed
344

345
    case 'save':
346
      variable_set('forum_block_num_'. $delta, $edit['forum_block_num_'. $delta]);
347
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
348

349
350
    case 'view':
      if (user_access('access content')) {
Dries Buytaert's avatar
   
Dries Buytaert committed
351
352
        switch ($delta) {
          case 0:
353
            $title = t('Active forum topics');
354
            $sql = db_rewrite_sql("SELECT n.nid, n.title, l.last_comment_timestamp, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND n.type = 'forum' ORDER BY l.last_comment_timestamp DESC");
355
356
            $content = node_title_list(db_query_range($sql, 0, variable_get('forum_block_num_0', '5')));
            break;
Dries Buytaert's avatar
   
Dries Buytaert committed
357
358

          case 1:
359
360
361
362
            $title = t('New forum topics');
            $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.type = 'forum' AND n.status = 1 ORDER BY n.nid DESC");
            $content = node_title_list(db_query_range($sql, 0, variable_get('forum_block_num_1', '5')));
            break;
Dries Buytaert's avatar
   
Dries Buytaert committed
363
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
364

365
366
367
368
        if ($content) {
          $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
369
        $block['subject'] = $title;
370
371
372
373
374
        $block['content'] = $content;

        return $block;
      }
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
375
376
}

Dries Buytaert's avatar
   
Dries Buytaert committed
377
378
379
/**
 * Implementation of hook_link().
 */
380
function forum_link($type, $node = 0, $main = 0) {
Dries Buytaert's avatar
Dries Buytaert committed
381
  global $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
382

Dries Buytaert's avatar
   
Dries Buytaert committed
383
384
  $links = array();

Dries Buytaert's avatar
   
Dries Buytaert committed
385
  if (!$main && $type == 'node' && $node->type == 'forum') {
Dries Buytaert's avatar
   
Dries Buytaert committed
386
387
    // get previous and next topic

Steven Wittens's avatar
Steven Wittens committed
388
    $sql = "SELECT n.nid, n.title, n.sticky, l.comment_count, l.last_comment_timestamp FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.status = 1 AND n.type = 'forum' ORDER BY n.sticky DESC, ". _forum_get_topic_order_sql(variable_get('forum_order', 1));
389
    $sql = db_rewrite_sql($sql);
Dries Buytaert's avatar
   
Dries Buytaert committed
390
    $result = db_query($sql, $node->tid);
Dries Buytaert's avatar
   
Dries Buytaert committed
391
392
393

    while ($topic = db_fetch_object($result)) {
      if ($stop == 1) {
394
        $next = new StdClass();
Dries Buytaert's avatar
   
Dries Buytaert committed
395
396
397
398
399
400
401
402
        $next->nid = $topic->nid;
        $next->title = $topic->title;
        break;
      }
      if ($topic->nid == $node->nid) {
        $stop = 1;
      }
      else {
403
        $prev = new StdClass();
Dries Buytaert's avatar
   
Dries Buytaert committed
404
405
406
407
408
409
        $prev->nid = $topic->nid;
        $prev->title = $topic->title;
      }
    }

    if ($prev) {
410
      $links[] = l(t('previous forum topic'), "node/$prev->nid", array('title' => check_plain($prev->title)));
Dries Buytaert's avatar
   
Dries Buytaert committed
411
412
413
    }

    if ($next) {
414
      $links[] = l(t('next forum topic'), "node/$next->nid", array('title' => check_plain($next->title)));
Dries Buytaert's avatar
   
Dries Buytaert committed
415
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
416
417
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
418
  return $links;
Dries Buytaert's avatar
   
Dries Buytaert committed
419
420
}

Dries Buytaert's avatar
   
Dries Buytaert committed
421
422
423
/**
 * Implementation of hook_menu().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
424
function forum_menu($may_cache) {
Dries Buytaert's avatar
   
Dries Buytaert committed
425
426
  $items = array();

Dries Buytaert's avatar
   
Dries Buytaert committed
427
428
429
  if ($may_cache) {
    $items[] = array('path' => 'node/add/forum', 'title' => t('forum topic'),
      'access' => user_access('create forum topics'));
430

Dries Buytaert's avatar
   
Dries Buytaert committed
431
432
433
    $items[] = array('path' => 'forum', 'title' => t('forums'),
      'callback' => 'forum_page',
      'access' => user_access('access content'),
434
      'type' => MENU_SUGGESTED_ITEM);
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

    $items[] = array('path' => 'admin/forum', 'title' => t('forums'),
      'callback' => 'forum_admin',
      'access' => user_access('administer forums'),
      'type' => MENU_NORMAL_ITEM);

    $items[] = array('path' => 'admin/forum/list', 'title' => t('list'),
      'access' => user_access('administer forums'),
      'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
    $items[] = array('path' => 'admin/forum/add/container', 'title' => t('add container'),
      'access' => user_access('administer forums'),
      'type' => MENU_LOCAL_TASK);
    $items[] = array('path' => 'admin/forum/add/forum', 'title' => t('add forum'),
      'access' => user_access('administer forums'),
      'type' => MENU_LOCAL_TASK);
450
451
452
453
    $items[] = array('path' => 'admin/forum/configure', 'title' => t('configure'),
      'callback' => 'forum_admin_configure',
      'access' => user_access('administer forums'),
      'type' => MENU_LOCAL_TASK);
454
455
456
457
458
459
460

    $items[] = array('path' => 'admin/forum/edit/container', 'title' => t('edit container'),
      'access' => user_access('administer forums'),
      'type' => MENU_CALLBACK);
    $items[] = array('path' => 'admin/forum/edit/forum', 'title' => t('edit forum'),
      'access' => user_access('administer forums'),
      'type' => MENU_CALLBACK);
Dries Buytaert's avatar
   
Dries Buytaert committed
461
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
462
463
464
465

  return $items;
}

466
467
468
/**
 * Implementation of hook_view().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
469
function forum_view(&$node, $teaser = FALSE, $page = FALSE) {
Dries Buytaert's avatar
   
Dries Buytaert committed
470

Dries Buytaert's avatar
   
Dries Buytaert committed
471
  if ($page) {
Dries Buytaert's avatar
   
Dries Buytaert committed
472
    $vocabulary = taxonomy_get_vocabulary(variable_get('forum_nav_vocabulary', ''));
Dries Buytaert's avatar
   
Dries Buytaert committed
473
    // Breadcrumb navigation
Dries Buytaert's avatar
   
Dries Buytaert committed
474
475
    $breadcrumb = array();
    $breadcrumb[] = array('path' => 'forum', 'title' => $vocabulary->name);
Dries Buytaert's avatar
   
Dries Buytaert committed
476
    if ($parents = taxonomy_get_parents_all($node->tid)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
477
478
      $parents = array_reverse($parents);
      foreach ($parents as $p) {
Dries Buytaert's avatar
   
Dries Buytaert committed
479
        $breadcrumb[] = array('path' => 'forum/'. $p->tid, 'title' => $p->name);
Dries Buytaert's avatar
   
Dries Buytaert committed
480
481
      }
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
482
483
    $breadcrumb[] = array('path' => 'node/'. $node->nid);
    menu_set_location($breadcrumb);
484
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
485

486
  $node = node_prepare($node, $teaser);
Dries Buytaert's avatar
   
Dries Buytaert committed
487
488
}

489
490
491
492
493
494
/**
 * Implementation of hook_validate().
 *
 * Check in particular that only a "leaf" term in the associated taxonomy
 * vocabulary is selected, not a "container" term.
 */
495
496
function forum_validate(&$node) {
  // Make sure all fields are set properly:
Dries Buytaert's avatar
   
Dries Buytaert committed
497
  $node->icon = $node->icon ? $node->icon : '';
Dries Buytaert's avatar
   
Dries Buytaert committed
498
499
500

  if ($node->taxonomy) {
    // Extract the node's proper topic ID.
Dries Buytaert's avatar
   
Dries Buytaert committed
501
    $vocabulary = variable_get('forum_nav_vocabulary', '');
502
    $containers = variable_get('forum_containers', array());
Dries Buytaert's avatar
   
Dries Buytaert committed
503
    foreach ($node->taxonomy as $term) {
Dries Buytaert's avatar
   
Dries Buytaert committed
504
      if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) {
505
506
        if (in_array($term, $containers)) {
          $term = taxonomy_get_term($term);
507
          form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => theme('placeholder', $term->name))));
508
509
510
511
        }
        else {
          $node->tid = $term;
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
512
      }
513
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
514
515
516
517
518
519
520
    if ($node->tid && $node->shadow) {
      $terms = array_keys(taxonomy_node_get_terms($node->nid));
      if (!in_array($node->tid, $terms)) {
        $terms[] = $node->tid;
      }
      $node->taxonomy = $terms;
    }
Dries Buytaert's avatar
Dries Buytaert committed
521
522
523
  }
}

Dries Buytaert's avatar
   
Dries Buytaert committed
524
525
526
527
528
529
530
/**
 * Implementation of hook_update().
 */
function forum_update($node) {
  db_query('UPDATE {forum} SET tid = %d WHERE nid = %d', $node->tid, $node->nid);
}

531
532
533
/**
 * Implementation of hook_form().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
534
function forum_form(&$node) {
Dries Buytaert's avatar
   
Dries Buytaert committed
535
  if (!$node->nid) {
Dries Buytaert's avatar
Dries Buytaert committed
536
    // new topic
Dries Buytaert's avatar
   
Dries Buytaert committed
537
    $node->taxonomy[] = arg(3);
538
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
539
540
541
  else {
    $node->taxonomy = array($node->tid);
  }
542

Dries Buytaert's avatar
   
Dries Buytaert committed
543
  $output = implode('', taxonomy_node_form('forum', $node));
Dries Buytaert's avatar
Dries Buytaert committed
544
545
546

  if ($node->nid) {
    // if editing, give option to leave shadows
Dries Buytaert's avatar
   
Dries Buytaert committed
547
548
    $shadow = (count(taxonomy_node_get_terms($node->nid)) > 1);
    $output .= form_checkbox(t('Leave shadow copy'), 'shadow', 1, $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
549
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
550

551
  $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '');
552
  $output .= filter_form('format', $node->format);
Dries Buytaert's avatar
   
Dries Buytaert committed
553
554
555
556

  return $output;
}

557
558
559
/**
 * Implementation of hook_insert().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
560
function forum_insert($node) {
Dries Buytaert's avatar
   
Dries Buytaert committed
561
  db_query('INSERT INTO {forum} (nid, tid) VALUES (%d, %d)', $node->nid, $node->tid);
Dries Buytaert's avatar
   
Dries Buytaert committed
562
563
}

564
565
566
/**
 * Implementation of hook_delete().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
567
function forum_delete(&$node) {
Dries Buytaert's avatar
   
Dries Buytaert committed
568
  db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
Dries Buytaert's avatar
   
Dries Buytaert committed
569
}
Dries Buytaert's avatar
   
Dries Buytaert committed
570

Dries Buytaert's avatar
   
Dries Buytaert committed
571
572
573
/**
 * Formats a topic for display
 *
574
 * @TODO Give a better description. Not sure where this function is used yet.
Dries Buytaert's avatar
   
Dries Buytaert committed
575
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
576
function _forum_format($topic) {
577
  if ($topic && $topic->timestamp) {
Dries Buytaert's avatar
   
Dries Buytaert committed
578
    return t('%time ago<br />by %author', array('%time' => format_interval(time() - $topic->timestamp), '%author' => format_name($topic)));
Dries Buytaert's avatar
   
Dries Buytaert committed
579
580
581
582
583
584
  }
  else {
    return message_na();
  }
}

Dries Buytaert's avatar
   
Dries Buytaert committed
585
586
587
/**
 * Returns a list of all forums for a given taxonomy id
 *
588
 * Forum objects contain the following fields
Dries Buytaert's avatar
   
Dries Buytaert committed
589
590
591
592
593
594
595
596
597
 * -num_topics Number of topics in the forum
 * -num_posts Total number of posts in all topics
 * -last_post Most recent post for the forum
 *
 * @param $tid
 *   Taxonomy ID of the vocabulary that holds the forum list.
 * @return
 *   Array of object containing the forum information.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
598
function forum_get_forums($tid = 0) {
599

Dries Buytaert's avatar
   
Dries Buytaert committed
600
601
602
603
  if (!$tid) {
    $tid = 0;
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
604
605
  $forums = array();
  $_forums = taxonomy_get_tree(variable_get('forum_nav_vocabulary', ''), $tid);
Dries Buytaert's avatar
   
Dries Buytaert committed
606

Dries Buytaert's avatar
   
Dries Buytaert committed
607
  if (count($_forums)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
608

Dries Buytaert's avatar
   
Dries Buytaert committed
609
610
    $counts = array();

Dries Buytaert's avatar
   
Dries Buytaert committed
611
    $sql = "SELECT r.tid, COUNT(n.nid) AS topic_count, SUM(l.comment_count) AS comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {term_node} r ON n.nid = r.nid WHERE n.status = 1 AND n.type = 'forum' GROUP BY r.tid";
612
    $sql = db_rewrite_sql($sql);
Dries Buytaert's avatar
   
Dries Buytaert committed
613
    $_counts = db_query($sql, $forum->tid);
Dries Buytaert's avatar
   
Dries Buytaert committed
614
615
616
    while ($count = db_fetch_object($_counts)) {
      $counts[$count->tid] = $count;
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
617
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
618

Dries Buytaert's avatar
   
Dries Buytaert committed
619
620
621
622
  foreach ($_forums as $forum) {
    if (in_array($forum->tid, variable_get('forum_containers', array()))) {
      $forum->container = 1;
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
623

Dries Buytaert's avatar
   
Dries Buytaert committed
624
625
626
627
628
629
630
631
632
633
634
    if ($counts[$forum->tid]) {
      $forum->num_topics = $counts[$forum->tid]->topic_count;
      $forum->num_posts = $counts[$forum->tid]->topic_count + $counts[$forum->tid]->comment_count;
    }
    else {
      $forum->num_topics = 0;
      $forum->num_posts = 0;
    }

    // This query does not use full ANSI syntax since MySQL 3.x does not support
    // table1 INNER JOIN table2 INNER JOIN table3 ON table2_criteria ON table3_criteria
Dries Buytaert's avatar
   
Dries Buytaert committed
635
    // used to join node_comment_statistics to users.
636
    $sql = "SELECT n.nid, l.last_comment_timestamp, IF(l.last_comment_uid, cu.name, l.last_comment_name) as last_comment_name, l.last_comment_uid FROM {node} n, {node_comment_statistics} l, {users} cu, {term_node} r WHERE  n.nid = r.nid AND r.tid = %d AND n.status = 1 AND n.type = 'forum' AND l.last_comment_uid = cu.uid AND n.nid = l.nid ORDER BY l.last_comment_timestamp DESC";
637
    $sql = db_rewrite_sql($sql);
Dries Buytaert's avatar
   
Dries Buytaert committed
638
    $topic = db_fetch_object(db_query_range($sql, $forum->tid, 0, 1));
639
640

    $last_post = new StdClass();
Dries Buytaert's avatar
   
Dries Buytaert committed
641
642
643
644
    $last_post->timestamp = $topic->last_comment_timestamp;
    $last_post->name = $topic->last_comment_name;
    $last_post->uid = $topic->last_comment_uid;
    $forum->last_post = $last_post;
Dries Buytaert's avatar
   
Dries Buytaert committed
645

Dries Buytaert's avatar
   
Dries Buytaert committed
646
647
648
649
    $forums[$forum->tid] = $forum;
  }

  return $forums;
Dries Buytaert's avatar
   
Dries Buytaert committed
650
651
}

652
653
654
655
function _forum_topics_read($term, $uid) {
  // Calculate the number of topics the user has read. Assume all entries older
  // than NODE_NEW_LIMIT are read, and include the recent posts that user has
  // read.
Dries Buytaert's avatar
   
Dries Buytaert committed
656
  $sql = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.created <= %d AND n.status = 1 AND n.type = 'forum'";
657
  $sql = db_rewrite_sql($sql);
Dries Buytaert's avatar
   
Dries Buytaert committed
658
659
  $ancient = db_result(db_query($sql, $term, NODE_NEW_LIMIT));
  $sql = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {history} h ON n.nid = h.nid AND h.uid = %d INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.status = 1 AND n.type = 'forum' AND n.created > %d";
660
  $sql = db_rewrite_sql($sql);
Dries Buytaert's avatar
   
Dries Buytaert committed
661
  $recent = db_result(db_query($sql, $uid, $term, NODE_NEW_LIMIT));
Dries Buytaert's avatar
   
Dries Buytaert committed
662

663
  return $ancient + $recent;
Dries Buytaert's avatar
   
Dries Buytaert committed
664
665
}

Dries Buytaert's avatar
Dries Buytaert committed
666
function forum_get_topics($tid, $sortby, $forum_per_page) {
Dries Buytaert's avatar
   
Dries Buytaert committed
667
  global $user, $forum_topic_list_header;
Dries Buytaert's avatar
   
Dries Buytaert committed
668

Dries Buytaert's avatar
   
Dries Buytaert committed
669
  $forum_topic_list_header = array(
Dries Buytaert's avatar
   
Dries Buytaert committed
670
671
    array('data' => '&nbsp;'),
    array('data' => t('Topic'), 'field' => 'n.title'),
Dries Buytaert's avatar
   
Dries Buytaert committed
672
    array('data' => t('Replies'), 'field' => 'l.comment_count'),
Dries Buytaert's avatar
   
Dries Buytaert committed
673
    array('data' => t('Created'), 'field' => 'n.created'),
Dries Buytaert's avatar
   
Dries Buytaert committed
674
    array('data' => t('Last reply'), 'field' => 'l.last_comment_timestamp'),
Dries Buytaert's avatar
   
Dries Buytaert committed
675
  );
Dries Buytaert's avatar
   
Dries Buytaert committed
676

Dries Buytaert's avatar
   
Dries Buytaert committed
677
  $order = _forum_get_topic_order($sortby);
Dries Buytaert's avatar
   
Dries Buytaert committed
678
  for ($i = 0; $i < count($forum_topic_list_header); $i++) {
Dries Buytaert's avatar
   
Dries Buytaert committed
679
680
    if ($forum_topic_list_header[$i]['field'] == $order['field']) {
      $forum_topic_list_header[$i]['sort'] = $order['sort'];
Dries Buytaert's avatar
   
Dries Buytaert committed
681
682
683
684
    }
  }

  $term = taxonomy_get_term($tid);
Dries Buytaert's avatar
   
Dries Buytaert committed
685

686
  $sql = db_rewrite_sql("SELECT n.nid, f.tid, n.title, n.sticky, u.name, u.uid, n.created AS timestamp, n.comment AS comment_mode, l.last_comment_timestamp, IF(l.last_comment_uid, cu.name, l.last_comment_name) AS last_comment_name, l.last_comment_uid, l.comment_count AS num_comments FROM {node} n, {node_comment_statistics} l, {users} cu, {term_node} r, {users} u, {forum} f WHERE n.status = 1 AND l.last_comment_uid = cu.uid AND n.nid = l.nid AND n.nid = r.nid AND r.tid = %d AND n.uid = u.uid AND n.nid = f.nid");
Dries Buytaert's avatar
   
Dries Buytaert committed
687
  $sql .= tablesort_sql($forum_topic_list_header, 'n.sticky DESC,');
Dries Buytaert's avatar
Dries Buytaert committed
688

689
  $sql_count = db_rewrite_sql("SELECT COUNT(n.nid) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.status = 1 AND n.type = 'forum'");
Dries Buytaert's avatar
   
Dries Buytaert committed
690

Steven Wittens's avatar
Steven Wittens committed
691
  $result = pager_query($sql, $forum_per_page, 0, $sql_count, $tid);
Dries Buytaert's avatar
   
Dries Buytaert committed
692
693

  while ($topic = db_fetch_object($result)) {
Dries Buytaert's avatar
Dries Buytaert committed
694
695
    if ($user->uid) {
      // folder is new if topic is new or there are new comments since last visit
Dries Buytaert's avatar
   
Dries Buytaert committed
696
      if ($topic->tid != $tid) {
Dries Buytaert's avatar
Dries Buytaert committed
697
        $topic->new = 0;
Dries Buytaert's avatar
   
Dries Buytaert committed
698
699
      }
      else {
Dries Buytaert's avatar
   
Dries Buytaert committed
700
        $history = _forum_user_last_visit($topic->nid);
Dries Buytaert's avatar
   
Dries Buytaert committed
701
        $topic->new_replies = comment_num_new($topic->nid, $history);
702
        $topic->new = $topic->new_replies || ($topic->timestamp > $history);
Dries Buytaert's avatar
   
Dries Buytaert committed
703
      }
704
705
    }
    else {
706
      // Do not track "new replies" status for topics if the user is anonymous.
Dries Buytaert's avatar
Dries Buytaert committed
707
708
      $topic->new_replies = 0;
      $topic->new = 0;
709
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
710

Dries Buytaert's avatar
   
Dries Buytaert committed
711
    if ($topic->num_comments > 0) {
712
      $last_reply = new StdClass();
Dries Buytaert's avatar
   
Dries Buytaert committed
713
714
715
716
717
      $last_reply->timestamp = $topic->last_comment_timestamp;
      $last_reply->name = $topic->last_comment_name;
      $last_reply->uid = $topic->last_comment_uid;
      $topic->last_reply = $last_reply;
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
718
719
720
    $topics[] = $topic;
  }

Dries Buytaert's avatar
Dries Buytaert committed
721
  return $topics;
Dries Buytaert's avatar
   
Dries Buytaert committed
722
723
}

Dries Buytaert's avatar
   
Dries Buytaert committed
724
725
726
/**
 * Finds the first unread node for a given forum.
 */
Dries Buytaert's avatar
Dries Buytaert committed
727
function _forum_new($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
728
729
  global $user;

Dries Buytaert's avatar
   
Dries Buytaert committed
730
  $sql = "SELECT n.nid FROM {node} n LEFT JOIN {history} h ON n.nid = h.nid AND h.uid = %d INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.status = 1 AND n.type = 'forum' AND h.nid IS NULL AND n.created > %d ORDER BY created";
731
  $sql = db_rewrite_sql($sql);
Dries Buytaert's avatar
   
Dries Buytaert committed
732
  $nid = db_result(db_query_range($sql, $user->uid, $tid, NODE_NEW_LIMIT, 0, 1));
Dries Buytaert's avatar
   
Dries Buytaert committed
733
734
735
736

  return $nid ? $nid : 0;
}

737
/**
738
 * Menu callback; prints a forum listing.
739
 */
Dries Buytaert's avatar
Dries Buytaert committed
740
function forum_page($tid = 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
741
  global $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
742

Dries Buytaert's avatar
   
Dries Buytaert committed
743
  if (module_exist('taxonomy')) {
Dries Buytaert's avatar
Dries Buytaert committed
744
745
    $forum_per_page = variable_get('forum_per_page', 25);
    $sortby = variable_get('forum_order', 1);
Dries Buytaert's avatar
   
Dries Buytaert committed
746

Dries Buytaert's avatar
Dries Buytaert committed
747
748
749
750
    $forums = forum_get_forums($tid);
    $parents = taxonomy_get_parents_all($tid);
    if ($tid && !in_array($tid, variable_get('forum_containers', array()))) {
      $topics = forum_get_topics($tid, $sortby, $forum_per_page);
Dries Buytaert's avatar
   
Dries Buytaert committed
751
    }
Dries Buytaert's avatar
Dries Buytaert committed
752

Dries Buytaert's avatar
   
Dries Buytaert committed
753
    return theme('forum_display', $forums, $topics, $parents, $tid, $sortby, $forum_per_page);
Dries Buytaert's avatar
   
Dries Buytaert committed
754
755
  }
  else {
756
    drupal_set_title(t('Warning'));
Dries Buytaert's avatar
   
Dries Buytaert committed
757
    return forum_help('admin/settings/forum');
Dries Buytaert's avatar
   
Dries Buytaert committed
758
759
760
  }
}

Dries Buytaert's avatar
   
Dries Buytaert committed
761
/**
Dries Buytaert's avatar
   
Dries Buytaert committed
762
763
 * Format the forum body.
 *
Dries Buytaert's avatar
   
Dries Buytaert committed
764
 * @ingroup themeable
Dries Buytaert's avatar
   
Dries Buytaert committed
765
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
766
function theme_forum_display($forums, $topics, $parents, $tid, $sortby, $forum_per_page) {
Dries Buytaert's avatar
   
Dries Buytaert committed
767
  global $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
768
  // forum list, topics list, topic browser and 'add new topic' link
Dries Buytaert's avatar
   
Dries Buytaert committed
769

Dries Buytaert's avatar
   
Dries Buytaert committed
770
  $vocabulary = taxonomy_get_vocabulary(variable_get('forum_nav_vocabulary', ''));
771
  $title = $vocabulary->name;
Dries Buytaert's avatar
   
Dries Buytaert committed
772

Dries Buytaert's avatar
   
Dries Buytaert committed
773
774
  // Breadcrumb navigation:
  $breadcrumb = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
775
  if ($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
776
    $breadcrumb[] = array('path' => 'forum', 'title' => $title);
Dries Buytaert's avatar
   
Dries Buytaert committed
777
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
778
779

  if ($parents) {
Dries Buytaert's avatar
   
Dries Buytaert committed
780
781
    $parents = array_reverse($parents);
    foreach ($parents as $p) {
782
783
      if ($p->tid == $tid) {
        $title = $p->name;
Dries Buytaert's avatar
   
Dries Buytaert committed
784
785
      }
      else {
Dries Buytaert's avatar
   
Dries Buytaert committed
786
        $breadcrumb[] = array('path' => 'forum/'. $p->tid, 'title' => $p->name);
Dries Buytaert's avatar
   
Dries Buytaert committed
787
788
789
      }
    }
  }
790
791
792

  drupal_set_title($title);

Dries Buytaert's avatar
   
Dries Buytaert committed
793
794
  $breadcrumb[] = array('path' => $_GET['q']);
  menu_set_location($breadcrumb);
Dries Buytaert's avatar
   
Dries Buytaert committed
795

Dries Buytaert's avatar
   
Dries Buytaert committed
796
  if (count($forums) || count($parents)) {
797
798
    $output  = '<div id="forum">';
    $output .= '<ul>';
Dries Buytaert's avatar
   
Dries Buytaert committed
799
800
801

    if (module_exist('tracker')) {
      if ($user->uid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
802
        $output .= ' <li>'. l(t('My forum discussions.'), "tracker/$user->uid") .'</li>';
Dries Buytaert's avatar
   
Dries Buytaert committed
803
804
      }

Dries Buytaert's avatar
   
Dries Buytaert committed
805
      $output .= ' <li>'. l(t('Active forum discussions.'), 'tracker') .'</li>';
Dries Buytaert's avatar
   
Dries Buytaert committed
806
807
808
    }

    if (user_access('create forum topics')) {
809
      $output .= '<li>'. l(t('Post new forum topic.'), "node/add/forum/$tid") .'</li>';
Dries Buytaert's avatar
   
Dries Buytaert committed
810
811
    }
    else if ($user->uid) {
812
      $output .= '<li>'. t('You are not allowed to post a new forum topic.') .'</li>';
Dries Buytaert's avatar
   
Dries Buytaert committed
813
814
815
816
    }
    else {
      $output .= '<li>'. t('<a href="%login">Login</a> to post a new forum topic.', array('%login' => url('user/login'))) .'</li>';
    }
817
    $output .= '</ul>';
Dries Buytaert's avatar
   
Dries Buytaert committed
818

Dries Buytaert's avatar
   
Dries Buytaert committed
819
    $output .= theme('forum_list', $forums, $parents, $tid);
Dries Buytaert's avatar
   
Dries Buytaert committed
820

Dries Buytaert's avatar
   
Dries Buytaert committed
821
    if ($tid && !in_array($tid, variable_get('forum_containers', array()))) {
Dries Buytaert's avatar
   
Dries Buytaert committed
822
823
      drupal_set_html_head('<link rel="alternate" type="application/rss+xml" title="RSS - '. $title .'" href="'. url('taxonomy/term/'. $tid .'/0/feed') .'" />');

Dries Buytaert's avatar
   
Dries Buytaert committed
824
      $output .= theme('forum_topic_list', $tid, $topics, $sortby, $forum_per_page);
Dries Buytaert's avatar
   
Dries Buytaert committed
825
      $output .= theme('xml_icon', url("taxonomy/term/$tid/0/feed"));
Dries Buytaert's avatar
   
Dries Buytaert committed
826
    }
827
    $output .= '</div>';
Dries Buytaert's avatar
   
Dries Buytaert committed
828
829
  }
  else {
830
    drupal_set_title(t('No forums defined'));
Dries Buytaert's avatar
   
Dries Buytaert committed
831
    $output = '';
Dries Buytaert's avatar
   
Dries Buytaert committed
832
833
  }

834
  return $output;
Dries Buytaert's avatar
   
Dries Buytaert committed
835
836
}

Dries Buytaert's avatar
   
Dries Buytaert committed
837
/**
Dries Buytaert's avatar
   
Dries Buytaert committed
838
839
 * Format the forum listing.
 *
Dries Buytaert's avatar
   
Dries Buytaert committed
840
 * @ingroup themeable
Dries Buytaert's avatar
   
Dries Buytaert committed
841
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
842
function theme_forum_list($forums, $parents, $tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
843
844
  global $user;

Dries Buytaert's avatar
   
Dries Buytaert committed
845
846
  if ($forums) {

Dries Buytaert's avatar
   
Dries Buytaert committed
847
    $header = array(t('Forum'), t('Topics'), t('Posts'), t('Last post'));
Dries Buytaert's avatar
   
Dries Buytaert committed
848
849

    foreach ($forums as $forum) {
Dries Buytaert's avatar
   
Dries Buytaert committed
850
      if ($forum->container) {
851
852
        $description  = '<div style="margin-left: '. ($forum->depth * 30) ."px;\">\n";
        $description .= ' <div class="name">'. l($forum->name, "forum/$forum->tid") ."</div>\n";
Dries Buytaert's avatar
   
Dries Buytaert committed
853
854
855
856
857
858

        if ($forum->description) {
          $description .= " <div class=\"description\">$forum->description</div>\n";
        }
        $description .= "</div>\n";

Dries Buytaert's avatar
   
Dries Buytaert committed
859
        $rows[] = array(array('data' => $description, 'class' => 'container', 'colspan' => '4'));
860
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
861
      else {
862
        $forum->old_topics = _forum_topics_read($forum->tid, $user->uid);
Dries Buytaert's avatar
   
Dries Buytaert committed
863
864
865
        if ($user->uid) {
          $new_topics = $forum->num_topics - $forum->old_topics;
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
866
867
868
        else {
          $new_topics = 0;
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
869

870
871
        $description  = '<div style="margin-left: '. ($forum->depth * 30) ."px;\">\n";
        $description .= ' <div class="name">'. l($forum->name, "forum/$forum->tid") ."</div>\n";
Dries Buytaert's avatar
   
Dries Buytaert committed
872

Dries Buytaert's avatar
   
Dries Buytaert committed
873
874
875
876
        if ($forum->description) {
          $description .= " <div class=\"description\">$forum->description</div>\n";
        }
        $description .= "</div>\n";
Dries Buytaert's avatar
   
Dries Buytaert committed
877

Dries Buytaert's avatar
   
Dries Buytaert committed
878
        $rows[] = array(
Dries Buytaert's avatar
   
Dries Buytaert committed
879
          array('data' => $description, 'class' => 'forum'),
880
          array('data' => $forum->num_topics . ($new_topics ? '<br />'. l(t('%a new', array('%a' => $new_topics)), "forum/$forum->tid", NULL, NULL, 'new') : ''), 'class' => 'topics'),
Dries Buytaert's avatar
   
Dries Buytaert committed
881
882
          array('data' => $forum->num_posts, 'class' => 'posts'),
          array('data' => _forum_format($forum->last_post), 'class' => 'last-reply'));
Dries Buytaert's avatar
   
Dries Buytaert committed
883
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
884
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
885
886
887

    return theme('table', $header, $rows);

Dries Buytaert's avatar
   
Dries Buytaert committed
888
889
890
891
  }

}

Dries Buytaert's avatar
   
Dries Buytaert committed
892
/**
Dries Buytaert's avatar
   
Dries Buytaert committed
893
894
 * Format the topic listing.
 *
Dries Buytaert's avatar
   
Dries Buytaert committed
895
 * @ingroup themeable
Dries Buytaert's avatar
   
Dries Buytaert committed
896
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
897
898
function theme_forum_topic_list($tid, $topics, $sortby, $forum_per_page) {
  global $forum_topic_list_header;
Dries Buytaert's avatar
   
Dries Buytaert committed
899
900

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

Dries Buytaert's avatar
   
Dries Buytaert committed
902
903
    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
904
      if ($topic->tid != $tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
905
        $rows[] = array(
Dries Buytaert's avatar
   
Dries Buytaert committed
906
          array('data' => _forum_icon($topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky), 'class' => 'icon'),
907
          array('data' => check_plain($topic->title), 'class' => 'title'),
Dries Buytaert's avatar
   
Dries Buytaert committed
908
          array('data' => l(t('This topic has been moved'), "forum/$topic->tid"), 'colspan' => '3')
Dries Buytaert's avatar
   
Dries Buytaert committed
909
        );
Dries Buytaert's avatar
   
Dries Buytaert committed
910
911
      }
      else {
Dries Buytaert's avatar
   
Dries Buytaert committed
912
        $rows[] = array(
Dries Buytaert's avatar
   
Dries Buytaert committed
913
          array('data' => _forum_icon($topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky), 'class' => 'icon'),
Dries Buytaert's avatar
   
Dries Buytaert committed
914
915
          array('data' => l($topic->title, "node/$topic->nid"), 'class' => 'topic'),
          array('data' => $topic->num_comments . ($topic->new_replies ? '<br />'. l(t('%a new', array('%a' => $topic->new_replies)), "node/$topic->nid", NULL, NULL, 'new') : ''), 'class' => 'replies'),
Dries Buytaert's avatar
   
Dries Buytaert committed
916
917
          array('data' => _forum_format($topic), 'class' => 'created'),
          array('data' => _forum_format($topic->last_reply), 'class' => 'last-reply')
Dries Buytaert's avatar
   
Dries Buytaert committed
918
        );
Dries Buytaert's avatar
   
Dries Buytaert committed
919
920
921
      }
    }

Dries Buytaert's avatar
   
Dries Buytaert committed
922
923
    if ($pager = theme('pager', NULL, $forum_per_page, 0, tablesort_pager())) {
      $rows[] = array(array('data' => $pager, 'colspan' => '5', 'class' => 'pager'));
Dries Buytaert's avatar
   
Dries Buytaert committed
924
925
    }
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
926

Dries Buytaert's avatar
   
Dries Buytaert committed
927
  $output .= theme('table', $forum_topic_list_header, $rows);
Dries Buytaert's avatar
   
Dries Buytaert committed
928

Dries Buytaert's avatar
   
Dries Buytaert committed
929
930
931
  return $output;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
932
function _forum_icon($new_posts, $num_posts = 0, $comment_mode = 0, $sticky = 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
933

Dries Buytaert's avatar
   
Dries Buytaert committed
934
  $base_path = variable_get('forum_icon_path', '');
Dries Buytaert's avatar
   
Dries Buytaert committed
935
  if ($base_path) {
Dries Buytaert's avatar
   
Dries Buytaert committed
936
937
    if ($num_posts > variable_get('forum_hot_topic', 15)) {
      $icon = $new_posts ? 'hot-new' : 'hot';
Dries Buytaert's avatar
   
Dries Buytaert committed
938
939
    }
    else {
Dries Buytaert's avatar