source: sipes/cord/modules/forum/forum.module @ c25d016

stableversion-3.0
Last change on this file since c25d016 was d7a822e, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se agrego el directorio del cord

  • Propiedad mode establecida a 100755
File size: 38.0 KB
Línea 
1<?php
2
3/**
4 * @file
5 * Enable threaded discussions about general topics.
6 */
7
8/**
9 * Implementation of hook_help().
10 */
11function forum_help($path, $arg) {
12  switch ($path) {
13    case 'admin/help#forum':
14      $output = '<p>'. t('The forum module lets you create threaded discussion forums with functionality similar to other message board systems. Forums are useful because they allow community members to discuss topics with one another while ensuring those conversations are archived for later reference. The <a href="@create-topic">forum topic</a> menu item (under <em>Create content</em> on the Navigation menu) creates the initial post of a new threaded discussion, or thread.', array('@create-topic' => url('node/add/forum'))) .'</p>';
15      $output .= '<p>'. t('A threaded discussion occurs as people leave comments on a forum topic (or on other comments within that topic). A forum topic is contained within a forum, which may hold many similar or related forum topics. Forums are (optionally) nested within a container, which may hold many similar or related forums. Both containers and forums may be nested within other containers and forums, and provide structure for your message board. By carefully planning this structure, you make it easier for users to find and comment on a specific forum topic.') .'</p>';
16      $output .= '<p>'. t('When administering a forum, note that:') .'</p>';
17      $output .= '<ul><li>'. t('a forum topic (and all of its comments) may be moved between forums by selecting a different forum while editing a forum topic.') .'</li>';
18      $output .= '<li>'. t('when moving a forum topic between forums, the <em>Leave shadow copy</em> option creates a link in the original forum pointing to the new location.') .'</li>';
19      $output .= '<li>'. t('selecting <em>Read only</em> under <em>Comment settings</em> while editing a forum topic will lock (prevent new comments) on the thread.') .'</li>';
20      $output .= '<li>'. t('selecting <em>Disabled</em> under <em>Comment settings</em> while editing a forum topic will hide all existing comments on the thread, and prevent new ones.') .'</li></ul>';
21      $output .= '<p>'. t('For more information, see the online handbook entry for <a href="@forum">Forum module</a>.', array('@forum' => 'http://drupal.org/handbook/modules/forum/')) .'</p>';
22      return $output;
23    case 'admin/content/forum':
24      return '<p>'. t('This page displays a list of existing forums and containers. Containers (optionally) hold forums, and forums hold forum topics (a forum topic is the initial post to a threaded discussion). To provide structure, both containers and forums may be placed inside other containers and forums. To rearrange forums and containers, grab a drag-and-drop handle under the <em>Name</em> column and drag the forum or container to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the <em>Save</em> button at the bottom of the page.') .'</p>';
25    case 'admin/content/forum/add/container':
26      return '<p>'. t('By grouping related or similar forums, containers help organize forums. For example, a container named "Food" may hold two forums named "Fruit" and "Vegetables", respectively.') .'</p>';
27    case 'admin/content/forum/add/forum':
28      return '<p>'. t('A forum holds related or similar forum topics (a forum topic is the initial post to a threaded discussion). For example, a forum named "Fruit" may contain forum topics titled "Apples" and "Bananas", respectively.') .'</p>';
29    case 'admin/content/forum/settings':
30      return '<p>'. t('These settings allow you to adjust the display of your forum topics. The content types available for use within a forum may be selected by editing the <em>Content types</em> on the <a href="@forum-vocabulary">forum vocabulary page</a>.', array('@forum-vocabulary' => url('admin/content/taxonomy/edit/vocabulary/'. variable_get('forum_nav_vocabulary', '')))) .'</p>';
31  }
32}
33
34/**
35 * Implementation of hook_theme()
36 */
37function forum_theme() {
38  return array(
39    'forums' => array(
40      'template' => 'forums',
41      'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
42    ),
43    'forum_list' => array(
44      'template' => 'forum-list',
45      'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
46    ),
47    'forum_topic_list' => array(
48      'template' => 'forum-topic-list',
49      'arguments' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
50    ),
51    'forum_icon' => array(
52      'template' => 'forum-icon',
53      'arguments' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0),
54    ),
55    'forum_topic_navigation' => array(
56      'template' => 'forum-topic-navigation',
57      'arguments' => array('node' => NULL),
58    ),
59    'forum_submitted' => array(
60      'template' => 'forum-submitted',
61      'arguments' => array('topic' => NULL),
62    ),
63  );
64}
65
66/**
67 * Fetch a forum term.
68 *
69 * @param $tid
70 *   The ID of the term which should be loaded.
71 *
72 * @return
73 *   An associative array containing the term data or FALSE if the term cannot be loaded, or is not part of the forum vocabulary.
74 */
75function forum_term_load($tid) {
76  $result = db_query(db_rewrite_sql('SELECT t.tid, t.vid, t.name, t.description, t.weight FROM {term_data} t WHERE t.tid = %d AND t.vid = %d', 't', 'tid'), $tid, variable_get('forum_nav_vocabulary', ''));
77  return db_fetch_array($result);
78}
79
80/**
81 * Implementation of hook_menu().
82 */
83function forum_menu() {
84  $items['forum'] = array(
85    'title' => 'Forums',
86    'page callback' => 'forum_page',
87    'access arguments' => array('access content'),
88    'type' => MENU_SUGGESTED_ITEM,
89    'file' => 'forum.pages.inc',
90  );
91  $items['admin/content/forum'] = array(
92    'title' => 'Forums',
93    'description' => 'Control forums and their hierarchy and change forum settings.',
94    'page callback' => 'drupal_get_form',
95    'page arguments' => array('forum_overview'),
96    'access arguments' => array('administer forums'),
97    'file' => 'forum.admin.inc',
98  );
99  $items['admin/content/forum/list'] = array(
100    'title' => 'List',
101    'type' => MENU_DEFAULT_LOCAL_TASK,
102    'weight' => -10,
103  );
104  $items['admin/content/forum/add/container'] = array(
105    'title' => 'Add container',
106    'page callback' => 'forum_form_main',
107    'page arguments' => array('container'),
108    'access arguments' => array('administer forums'),
109    'type' => MENU_LOCAL_TASK,
110    'parent' => 'admin/content/forum',
111    'file' => 'forum.admin.inc',
112  );
113  $items['admin/content/forum/add/forum'] = array(
114    'title' => 'Add forum',
115    'page callback' => 'forum_form_main',
116    'page arguments' => array('forum'),
117    'access arguments' => array('administer forums'),
118    'type' => MENU_LOCAL_TASK,
119    'parent' => 'admin/content/forum',
120    'file' => 'forum.admin.inc',
121  );
122  $items['admin/content/forum/settings'] = array(
123    'title' => 'Settings',
124    'page callback' => 'drupal_get_form',
125    'page arguments' => array('forum_admin_settings'),
126    'access arguments' => array('administer forums'),
127    'weight' => 5,
128    'type' => MENU_LOCAL_TASK,
129    'parent' => 'admin/content/forum',
130    'file' => 'forum.admin.inc',
131  );
132  $items['admin/content/forum/edit/%forum_term'] = array(
133    'page callback' => 'forum_form_main',
134    'access arguments' => array('administer forums'),
135    'type' => MENU_CALLBACK,
136    'file' => 'forum.admin.inc',
137  );
138  $items['admin/content/forum/edit/container/%forum_term'] = array(
139    'title' => 'Edit container',
140    'page callback' => 'forum_form_main',
141    'page arguments' => array('container', 5),
142    'access arguments' => array('administer forums'),
143    'type' => MENU_CALLBACK,
144    'file' => 'forum.admin.inc',
145  );
146  $items['admin/content/forum/edit/forum/%forum_term'] = array(
147    'title' => 'Edit forum',
148    'page callback' => 'forum_form_main',
149    'page arguments' => array('forum', 5),
150    'access arguments' => array('administer forums'),
151    'type' => MENU_CALLBACK,
152    'file' => 'forum.admin.inc',
153  );
154  return $items;
155}
156
157
158/**
159 * Implementation of hook_init().
160 */
161function forum_init() {
162  drupal_add_css(drupal_get_path('module', 'forum') .'/forum.css');
163}
164
165/**
166 * Implementation of hook_nodeapi().
167 */
168function forum_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
169  // We are going to return if $node->type is not one of the node
170  // types assigned to the forum vocabulary.  If forum_nav_vocabulary
171  // is undefined or the vocabulary does not exist, it clearly cannot
172  // be assigned to $node->type, so return to avoid E_ALL warnings.
173  $vid = variable_get('forum_nav_vocabulary', '');
174  $vocabulary = taxonomy_vocabulary_load($vid);
175  if (empty($vocabulary)) {
176    return;
177  }
178
179  // Operate only on node types assigned for the forum vocabulary.
180  if (!in_array($node->type, $vocabulary->nodes)) {
181    return;
182  }
183
184  switch ($op) {
185    case 'view':
186      if ($page && taxonomy_node_get_terms_by_vocabulary($node, $vid) && $tree = taxonomy_get_tree($vid)) {
187        // Get the forum terms from the (cached) tree
188        foreach ($tree as $term) {
189          $forum_terms[] = $term->tid;
190        }
191        foreach ($node->taxonomy as $term_id => $term) {
192          if (in_array($term_id, $forum_terms)) {
193            $node->tid = $term_id;
194          }
195        }
196        // Breadcrumb navigation
197        $breadcrumb[] = l(t('Home'), NULL);
198        $breadcrumb[] = l($vocabulary->name, 'forum');
199        if ($parents = taxonomy_get_parents_all($node->tid)) {
200          $parents = array_reverse($parents);
201          foreach ($parents as $p) {
202            $breadcrumb[] = l($p->name, 'forum/'. $p->tid);
203          }
204        }
205        drupal_set_breadcrumb($breadcrumb);
206
207        if (!$teaser) {
208          $node->content['forum_navigation'] = array(
209            '#value' => theme('forum_topic_navigation', $node),
210            '#weight' => 100,
211          );
212        }
213      }
214      break;
215
216    case 'prepare':
217      if (empty($node->nid)) {
218        // New topic
219        $node->taxonomy[arg(3)]->vid = $vid;
220        $node->taxonomy[arg(3)]->tid = arg(3);
221      }
222      break;
223
224    // Check in particular that only a "leaf" term in the associated taxonomy
225    // vocabulary is selected, not a "container" term.
226    case 'validate':
227      if ($node->taxonomy) {
228        // Extract the node's proper topic ID.
229        $vocabulary = $vid;
230        $containers = variable_get('forum_containers', array());
231        foreach ($node->taxonomy as $term) {
232          if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) {
233            if (in_array($term, $containers)) {
234              $term = taxonomy_get_term($term);
235              form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name)));
236            }
237          }
238        }
239      }
240      break;
241
242    // Assign forum taxonomy when adding a topic from within a forum.
243    case 'presave':
244      // Make sure all fields are set properly:
245      $node->icon = !empty($node->icon) ? $node->icon : '';
246
247      if ($node->taxonomy && $tree = taxonomy_get_tree($vid)) {
248        // Get the forum terms from the (cached) tree if we have a taxonomy.
249        foreach ($tree as $term) {
250          $forum_terms[] = $term->tid;
251        }
252        foreach ($node->taxonomy as $term_id) {
253          if (in_array($term_id, $forum_terms)) {
254            $node->tid = $term_id;
255          }
256        }
257        $old_tid = db_result(db_query_range("SELECT f.tid FROM {forum} f INNER JOIN {node} n ON f.vid = n.vid WHERE n.nid = %d ORDER BY f.vid DESC", $node->nid, 0, 1));
258        if ($old_tid && isset($node->tid) && ($node->tid != $old_tid) && !empty($node->shadow)) {
259          // A shadow copy needs to be created. Retain new term and add old term.
260          $node->taxonomy[] = $old_tid;
261        }
262      }
263      break;
264
265    case 'update':
266      if (empty($node->revision) && db_result(db_query('SELECT tid FROM {forum} WHERE nid=%d', $node->nid))) {
267        if (!empty($node->tid)) {
268          db_query('UPDATE {forum} SET tid = %d WHERE vid = %d', $node->tid, $node->vid);
269        }
270        // The node is removed from the forum.
271        else {
272          db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
273        }
274        break;
275      }
276      // Deliberate no break -- for new revisions and for previously unassigned terms we need an insert.
277
278    case 'insert':
279      if (!empty($node->tid)) {
280        db_query('INSERT INTO {forum} (tid, vid, nid) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid);
281      }
282      break;
283
284    case 'delete':
285      db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
286      break;
287
288    case 'load':
289      return db_fetch_array(db_query('SELECT tid AS forum_tid FROM {forum} WHERE vid = %d', $node->vid));
290  }
291
292  return;
293}
294
295/**
296 * Implementation of hook_node_info().
297 */
298function forum_node_info() {
299  return array(
300    'forum' => array(
301      'name' => t('Forum topic'),
302      'module' => 'forum',
303      'description' => t('A <em>forum topic</em> is the initial post to a new discussion thread within a forum.'),
304      'title_label' => t('Subject'),
305    )
306  );
307}
308
309/**
310 * Implementation of hook_access().
311 */
312function forum_access($op, $node, $account) {
313  switch ($op) {
314    case 'create':
315      return user_access('create forum topics', $account) ? TRUE : NULL;
316    case 'update':
317      return user_access('edit any forum topic', $account) || (user_access('edit own forum topics', $account) && ($account->uid == $node->uid)) ? TRUE : NULL;
318    case 'delete':
319      return user_access('delete any forum topic', $account) || (user_access('delete own forum topics', $account) && ($account->uid == $node->uid)) ? TRUE : NULL;
320  }
321}
322
323/**
324 * Implementation of hook_perm().
325 */
326function forum_perm() {
327  return array('create forum topics', 'delete own forum topics', 'delete any forum topic', 'edit own forum topics', 'edit any forum topic', 'administer forums');
328}
329
330/**
331 * Implementation of hook_taxonomy().
332 */
333function forum_taxonomy($op, $type, $term = NULL) {
334  if ($op == 'delete' && $term['vid'] == variable_get('forum_nav_vocabulary', '')) {
335    switch ($type) {
336      case 'term':
337        $results = db_query('SELECT tn.nid FROM {term_node} tn WHERE tn.tid = %d', $term['tid']);
338        while ($node = db_fetch_object($results)) {
339          // node_delete will also remove any association with non-forum vocabularies.
340          node_delete($node->nid);
341        }
342
343        // For containers, remove the tid from the forum_containers variable.
344        $containers = variable_get('forum_containers', array());
345        $key = array_search($term['tid'], $containers);
346        if ($key !== FALSE) {
347          unset($containers[$key]);
348        }
349        variable_set('forum_containers', $containers);
350        break;
351      case 'vocabulary':
352        variable_del('forum_nav_vocabulary');
353    }
354  }
355}
356
357/**
358 * Implementation of hook_form_alter().
359 */
360function forum_form_alter(&$form, $form_state, $form_id) {
361  $vid = variable_get('forum_nav_vocabulary', '');
362  if (isset($form['vid']) && $form['vid']['#value'] == $vid) {
363    // Hide critical options from forum vocabulary.
364    if ($form_id == 'taxonomy_form_vocabulary') {
365      $form['help_forum_vocab'] = array(
366        '#value' => t('This is the designated forum vocabulary. Some of the normal vocabulary options have been removed.'),
367        '#weight' => -1,
368      );
369      $form['content_types']['nodes']['#required'] = TRUE;
370      $form['hierarchy'] = array('#type' => 'value', '#value' => 1);
371      $form['settings']['required'] = array('#type' => 'value', '#value' => FALSE);
372      $form['settings']['relations'] = array('#type' => 'value', '#value' => FALSE);
373      $form['settings']['tags'] = array('#type' => 'value', '#value' => FALSE);
374      $form['settings']['multiple'] = array('#type' => 'value', '#value' => FALSE);
375      unset($form['delete']);
376    }
377    // Hide multiple parents select from forum terms.
378    elseif ($form_id == 'taxonomy_form_term') {
379      $form['advanced']['parent']['#access'] = FALSE;
380    }
381  }
382  if ($form_id == 'forum_node_form') {
383    // Make the vocabulary required for 'real' forum-nodes.
384    $vid = variable_get('forum_nav_vocabulary', '');
385    $form['taxonomy'][$vid]['#required'] = TRUE;
386    $form['taxonomy'][$vid]['#options'][''] = t('- Please choose -');
387  }
388}
389
390/**
391 * Implementation of hook_load().
392 */
393function forum_load($node) {
394  $forum = db_fetch_object(db_query('SELECT * FROM {forum} WHERE vid = %d', $node->vid));
395
396  return $forum;
397}
398
399/**
400 * Implementation of hook_block().
401 *
402 * Generates a block containing the currently active forum topics and the
403 * most recently added forum topics.
404 */
405function forum_block($op = 'list', $delta = 0, $edit = array()) {
406  switch ($op) {
407    case 'list':
408      $blocks[0]['info'] = t('Active forum topics');
409      $blocks[1]['info'] = t('New forum topics');
410      return $blocks;
411
412    case 'configure':
413      $form['forum_block_num_'. $delta] = array('#type' => 'select', '#title' => t('Number of topics'), '#default_value' => variable_get('forum_block_num_'. $delta, '5'), '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)));
414      return $form;
415
416    case 'save':
417      variable_set('forum_block_num_'. $delta, $edit['forum_block_num_'. $delta]);
418      break;
419
420    case 'view':
421      if (user_access('access content')) {
422        switch ($delta) {
423          case 0:
424            $title = t('Active forum topics');
425            $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count, l.last_comment_timestamp FROM {node} n INNER JOIN {term_node} tn ON tn.vid = n.vid INNER JOIN {term_data} td ON td.tid = tn.tid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND td.vid = %d ORDER BY l.last_comment_timestamp DESC");
426            $result = db_query_range($sql, variable_get('forum_nav_vocabulary', ''), 0, variable_get('forum_block_num_0', '5'));
427            $content = node_title_list($result);
428            break;
429
430          case 1:
431            $title = t('New forum topics');
432            $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count FROM {node} n INNER JOIN {term_node} tn ON tn.vid = n.vid INNER JOIN {term_data} td ON td.tid = tn.tid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND td.vid = %d ORDER BY n.nid DESC");
433            $result = db_query_range($sql, variable_get('forum_nav_vocabulary', ''), 0, variable_get('forum_block_num_1', '5'));
434            $content = node_title_list($result);
435            break;
436        }
437
438        if (!empty($content)) {
439          $block['subject'] = $title;
440          $block['content'] = $content . theme('more_link', url('forum'), t('Read the latest forum topics.'));
441          return $block;
442        }
443      }
444  }
445}
446
447/**
448 * Implementation of hook_form().
449 */
450function forum_form(&$node, $form_state) {
451  $type = node_get_types('type', $node);
452  $form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#default_value' => !empty($node->title) ? $node->title : '', '#required' => TRUE, '#weight' => -5);
453
454  if (!empty($node->nid)) {
455    $vid = variable_get('forum_nav_vocabulary', '');
456    $forum_terms = taxonomy_node_get_terms_by_vocabulary($node, $vid);
457    // if editing, give option to leave shadows
458    $shadow = (count($forum_terms) > 1);
459    $form['shadow'] = array('#type' => 'checkbox', '#title' => t('Leave shadow copy'), '#default_value' => $shadow, '#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.'));
460  }
461
462  $form['body_field'] = node_body_field($node, $type->body_label, 1);
463
464  $form['#submit'][] = 'forum_submit';
465  // Assign the forum topic submit handler.
466
467  return $form;
468}
469
470/**
471 * Implementation of hook_term_path().
472 */
473function forum_term_path($term) {
474  return 'forum/'. $term->tid;
475}
476
477/**
478 * Returns a list of all forums for a given taxonomy id
479 *
480 * Forum objects contain the following fields
481 * -num_topics Number of topics in the forum
482 * -num_posts Total number of posts in all topics
483 * -last_post Most recent post for the forum
484 *
485 * @param $tid
486 *   Taxonomy ID of the vocabulary that holds the forum list.
487 * @return
488 *   Array of object containing the forum information.
489 */
490function forum_get_forums($tid = 0) {
491
492  $forums = array();
493  $vid = variable_get('forum_nav_vocabulary', '');
494  $_forums = taxonomy_get_tree($vid, $tid);
495
496  if (count($_forums)) {
497  $counts = array();
498    $sql = "
499      SELECT r.tid AS tid, n.nid AS nid, l.comment_count AS nid_comment_count
500        FROM {node} n
501        INNER JOIN {node_comment_statistics} l ON n.nid = l.nid
502        INNER JOIN {term_node} r ON n.vid = r.vid
503        WHERE n.status = 1
504        GROUP BY r.tid, n.nid, l.comment_count";
505    $sql_rewritten = db_rewrite_sql($sql);
506    if ($sql_rewritten == $sql) {
507      $sql = "
508        SELECT r.tid, COUNT(n.nid) AS topic_count, SUM(l.comment_count) AS comment_count
509          FROM {node} n
510          INNER JOIN {node_comment_statistics} l ON n.nid = l.nid
511          INNER JOIN {term_node} r ON n.vid = r.vid
512          WHERE n.status = 1
513          GROUP BY r.tid";
514      $sql = db_rewrite_sql($sql);
515    }
516    else {
517      $sql = "
518        SELECT tid, COUNT(nid) AS topic_count, SUM(nid_comment_count) AS comment_count
519          FROM ($sql_rewritten) AS forum_content_list
520          GROUP BY tid";
521    }
522    $_counts = db_query($sql);
523    while ($count = db_fetch_object($_counts)) {
524      $counts[$count->tid] = $count;
525    }
526  }
527
528  foreach ($_forums as $forum) {
529    if (in_array($forum->tid, variable_get('forum_containers', array()))) {
530      $forum->container = 1;
531    }
532
533    if (!empty($counts[$forum->tid])) {
534      $forum->num_topics = $counts[$forum->tid]->topic_count;
535      $forum->num_posts = $counts[$forum->tid]->topic_count + $counts[$forum->tid]->comment_count;
536    }
537    else {
538      $forum->num_topics = 0;
539      $forum->num_posts = 0;
540    }
541
542    // This query does not use full ANSI syntax since MySQL 3.x does not support
543    // table1 INNER JOIN table2 INNER JOIN table3 ON table2_criteria ON table3_criteria
544    // used to join node_comment_statistics to users.
545    $sql = "SELECT ncs.last_comment_timestamp, IF (ncs.last_comment_uid != 0, u2.name, ncs.last_comment_name) AS last_comment_name, ncs.last_comment_uid FROM {node} n INNER JOIN {users} u1 ON n.uid = u1.uid INNER JOIN {term_node} tn ON n.vid = tn.vid INNER JOIN {node_comment_statistics} ncs ON n.nid = ncs.nid INNER JOIN {users} u2 ON ncs.last_comment_uid=u2.uid WHERE n.status = 1 AND tn.tid = %d ORDER BY ncs.last_comment_timestamp DESC";
546    $sql = db_rewrite_sql($sql);
547    $topic = db_fetch_object(db_query_range($sql, $forum->tid, 0, 1));
548
549    $last_post = new stdClass();
550    if (!empty($topic->last_comment_timestamp)) {
551      $last_post->timestamp = $topic->last_comment_timestamp;
552      $last_post->name = $topic->last_comment_name;
553      $last_post->uid = $topic->last_comment_uid;
554    }
555    $forum->last_post = $last_post;
556
557    $forums[$forum->tid] = $forum;
558  }
559
560  return $forums;
561}
562
563/**
564 * Calculate the number of nodes the user has not yet read and are newer
565 * than NODE_NEW_LIMIT.
566 */
567function _forum_topics_unread($term, $uid) {
568  $sql = "SELECT COUNT(DISTINCT n.nid) FROM {node} n INNER JOIN {term_node} tn ON n.vid = tn.vid AND tn.tid = %d LEFT JOIN {history} h ON n.nid = h.nid AND h.uid = %d WHERE n.status = 1 AND n.created > %d AND h.nid IS NULL";
569  $sql = db_rewrite_sql($sql);
570  return db_result(db_query($sql, $term, $uid, NODE_NEW_LIMIT));
571}
572
573function forum_get_topics($tid, $sortby, $forum_per_page) {
574  global $user, $forum_topic_list_header;
575
576  $forum_topic_list_header = array(
577    NULL,
578    array('data' => t('Topic'), 'field' => 'n.title'),
579    array('data' => t('Replies'), 'field' => 'l.comment_count'),
580    array('data' => t('Created'), 'field' => 'n.created'),
581    array('data' => t('Last reply'), 'field' => 'l.last_comment_timestamp'),
582  );
583
584  $order = _forum_get_topic_order($sortby);
585  for ($i = 0; $i < count($forum_topic_list_header); $i++) {
586    if ($forum_topic_list_header[$i]['field'] == $order['field']) {
587      $forum_topic_list_header[$i]['sort'] = $order['sort'];
588    }
589  }
590
591  $term = taxonomy_get_term($tid);
592
593  $sql = db_rewrite_sql("SELECT n.nid, r.tid, n.title, n.type, n.sticky, u.name, u.uid, n.created AS timestamp, n.comment AS comment_mode, l.last_comment_timestamp, IF(l.last_comment_uid != 0, cu.name, l.last_comment_name) AS last_comment_name, l.last_comment_uid, l.comment_count AS num_comments, f.tid AS forum_tid FROM {node_comment_statistics} l INNER JOIN {node} n ON n.nid = l.nid INNER JOIN {users} cu ON l.last_comment_uid = cu.uid INNER JOIN {term_node} r ON n.vid = r.vid INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {forum} f ON n.vid = f.vid WHERE n.status = 1 AND r.tid = %d");
594  $sql .= tablesort_sql($forum_topic_list_header, 'n.sticky DESC,');
595  $sql .= ', n.created DESC';  // Always add a secondary sort order so that the news forum topics are on top.
596
597  $sql_count = db_rewrite_sql("SELECT COUNT(DISTINCT n.nid) FROM {node} n INNER JOIN {term_node} r ON n.vid = r.vid AND r.tid = %d WHERE n.status = 1");
598
599  $result = pager_query($sql, $forum_per_page, 0, $sql_count, $tid);
600  $topics = array();
601  while ($topic = db_fetch_object($result)) {
602    if ($user->uid) {
603      // folder is new if topic is new or there are new comments since last visit
604      if ($topic->tid != $tid) {
605        $topic->new = 0;
606      }
607      else {
608        $history = _forum_user_last_visit($topic->nid);
609        $topic->new_replies = comment_num_new($topic->nid, $history);
610        $topic->new = $topic->new_replies || ($topic->timestamp > $history);
611      }
612    }
613    else {
614      // Do not track "new replies" status for topics if the user is anonymous.
615      $topic->new_replies = 0;
616      $topic->new = 0;
617    }
618
619    if ($topic->num_comments > 0) {
620      $last_reply = new stdClass();
621      $last_reply->timestamp = $topic->last_comment_timestamp;
622      $last_reply->name = $topic->last_comment_name;
623      $last_reply->uid = $topic->last_comment_uid;
624      $topic->last_reply = $last_reply;
625    }
626    $topics[] = $topic;
627  }
628
629  return $topics;
630}
631
632/**
633 * Finds the first unread node for a given forum.
634 */
635function _forum_new($tid) {
636  global $user;
637
638  $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 h.nid IS NULL AND n.created > %d ORDER BY created";
639  $sql = db_rewrite_sql($sql);
640  $nid = db_result(db_query_range($sql, $user->uid, $tid, NODE_NEW_LIMIT, 0, 1));
641
642  return $nid ? $nid : 0;
643}
644
645/**
646 * Process variables for forums.tpl.php
647 *
648 * The $variables array contains the following arguments:
649 * - $forums
650 * - $topics
651 * - $parents
652 * - $tid
653 * - $sortby
654 * - $forum_per_page
655 *
656 * @see forums.tpl.php
657 */
658function template_preprocess_forums(&$variables) {
659  global $user;
660
661  $vid = variable_get('forum_nav_vocabulary', '');
662  $vocabulary = taxonomy_vocabulary_load($vid);
663  $title = !empty($vocabulary->name) ? $vocabulary->name : '';
664
665  // Breadcrumb navigation:
666  $breadcrumb[] = l(t('Home'), NULL);
667  if ($variables['tid']) {
668    $breadcrumb[] = l($vocabulary->name, 'forum');
669  }
670  if ($variables['parents']) {
671    $variables['parents'] = array_reverse($variables['parents']);
672    foreach ($variables['parents'] as $p) {
673      if ($p->tid == $variables['tid']) {
674        $title = $p->name;
675      }
676      else {
677        $breadcrumb[] = l($p->name, 'forum/'. $p->tid);
678      }
679    }
680  }
681  drupal_set_breadcrumb($breadcrumb);
682  drupal_set_title(check_plain($title));
683
684  if ($variables['forums_defined'] = count($variables['forums']) || count($variables['parents'])) {
685    // Format the "post new content" links listing.
686    $forum_types = array();
687
688    // Loop through all node types for forum vocabulary.
689    foreach ($vocabulary->nodes as $type) {
690      // Check if the current user has the 'create' permission for this node type.
691      if (node_access('create', $type)) {
692        // Fetch the "General" name of the content type;
693        // Push the link with title and URL to the array.
694        $forum_types[$type] = array('title' => t('Post new @node_type', array('@node_type' => node_get_types('name', $type))), 'href' => 'node/add/'. str_replace('_', '-', $type) .'/'. $variables['tid']);
695      }
696    }
697
698    if (empty($forum_types)) {
699      // The user is logged-in; but denied access to create any new forum content type.
700      if ($user->uid) {
701        $forum_types['disallowed'] = array('title' => t('You are not allowed to post new content in the forum.'));
702      }
703      // The user is not logged-in; and denied access to create any new forum content type.
704      else {
705        $forum_types['login'] = array('title' => t('<a href="@login">Login</a> to post new content in the forum.', array('@login' => url('user/login', array('query' => drupal_get_destination())))), 'html' => TRUE);
706      }
707    }
708    $variables['links'] = $forum_types;
709
710    if (!empty($variables['forums'])) {
711      $variables['forums'] = theme('forum_list', $variables['forums'], $variables['parents'], $variables['tid']);
712    }
713    else {
714      $variables['forums'] = '';
715    }
716
717    if ($variables['tid'] && !in_array($variables['tid'], variable_get('forum_containers', array()))) {
718      $variables['topics'] = theme('forum_topic_list', $variables['tid'], $variables['topics'], $variables['sortby'], $variables['forum_per_page']);
719      drupal_add_feed(url('taxonomy/term/'. $variables['tid'] .'/0/feed'), 'RSS - '. $title);
720    }
721    else {
722      $variables['topics'] = '';
723    }
724
725    // Provide separate template suggestions based on what's being output. Topic id is also accounted for.
726    // Check both variables to be safe then the inverse. Forums with topic ID's take precedence.
727    if ($variables['forums'] && !$variables['topics']) {
728      $variables['template_files'][] = 'forums-containers';
729      $variables['template_files'][] = 'forums-'. $variables['tid'];
730      $variables['template_files'][] = 'forums-containers-'. $variables['tid'];
731    }
732    elseif (!$variables['forums'] && $variables['topics']) {
733      $variables['template_files'][] = 'forums-topics';
734      $variables['template_files'][] = 'forums-'. $variables['tid'];
735      $variables['template_files'][] = 'forums-topics-'. $variables['tid'];
736    }
737    else {
738      $variables['template_files'][] = 'forums-'. $variables['tid'];
739    }
740
741  }
742  else {
743    drupal_set_title(t('No forums defined'));
744    $variables['links'] = array();
745    $variables['forums'] = '';
746    $variables['topics'] = '';
747  }
748}
749
750/**
751 * Process variables to format a forum listing.
752 *
753 * $variables contains the following information:
754 * - $forums
755 * - $parents
756 * - $tid
757 *
758 * @see forum-list.tpl.php
759 * @see theme_forum_list()
760 */
761function template_preprocess_forum_list(&$variables) {
762  global $user;
763  $row = 0;
764  // Sanitize each forum so that the template can safely print the data.
765  foreach ($variables['forums'] as $id => $forum) {
766    $variables['forums'][$id]->description = !empty($forum->description) ? filter_xss_admin($forum->description) : '';
767    $variables['forums'][$id]->link = url("forum/$forum->tid");
768    $variables['forums'][$id]->name = check_plain($forum->name);
769    $variables['forums'][$id]->is_container = !empty($forum->container);
770    $variables['forums'][$id]->zebra = $row % 2 == 0 ? 'odd' : 'even';
771    $row++;
772
773    $variables['forums'][$id]->new_text = '';
774    $variables['forums'][$id]->new_url = '';
775    $variables['forums'][$id]->new_topics = 0;
776    $variables['forums'][$id]->old_topics = $forum->num_topics;
777    if ($user->uid) {
778      $variables['forums'][$id]->new_topics = _forum_topics_unread($forum->tid, $user->uid);
779      if ($variables['forums'][$id]->new_topics) {
780        $variables['forums'][$id]->new_text = format_plural($variables['forums'][$id]->new_topics, '1 new', '@count new');
781        $variables['forums'][$id]->new_url = url("forum/$forum->tid", array('fragment' => 'new'));
782      }
783      $variables['forums'][$id]->old_topics = $forum->num_topics - $variables['forums'][$id]->new_topics;
784    }
785    $variables['forums'][$id]->last_reply = theme('forum_submitted', $forum->last_post);
786  }
787  // Give meaning to $tid for themers. $tid actually stands for term id.
788  $variables['forum_id'] = $variables['tid'];
789  unset($variables['tid']);
790}
791
792/**
793 * Preprocess variables to format the topic listing.
794 *
795 * $variables contains the following data:
796 * - $tid
797 * - $topics
798 * - $sortby
799 * - $forum_per_page
800 *
801 * @see forum-topic-list.tpl.php
802 * @see theme_forum_topic_list()
803 */
804function template_preprocess_forum_topic_list(&$variables) {
805  global $forum_topic_list_header;
806
807  // Create the tablesorting header.
808  $ts = tablesort_init($forum_topic_list_header);
809  $header = '';
810  foreach ($forum_topic_list_header as $cell) {
811    $cell = tablesort_header($cell, $forum_topic_list_header, $ts);
812    $header .= _theme_table_cell($cell, TRUE);
813  }
814  $variables['header'] = $header;
815
816  if (!empty($variables['topics'])) {
817    $row = 0;
818    foreach ($variables['topics'] as $id => $topic) {
819      $variables['topics'][$id]->icon = theme('forum_icon', $topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky);
820      $variables['topics'][$id]->zebra = $row % 2 == 0 ? 'odd' : 'even';
821      $row++;
822
823      // We keep the actual tid in forum table, if it's different from the
824      // current tid then it means the topic appears in two forums, one of
825      // them is a shadow copy.
826      if ($topic->forum_tid != $variables['tid']) {
827        $variables['topics'][$id]->moved = TRUE;
828        $variables['topics'][$id]->title = check_plain($topic->title);
829        $variables['topics'][$id]->message = l(t('This topic has been moved'), "forum/$topic->forum_tid");
830      }
831      else {
832        $variables['topics'][$id]->moved = FALSE;
833        $variables['topics'][$id]->title = l($topic->title, "node/$topic->nid");
834        $variables['topics'][$id]->message = '';
835      }
836      $variables['topics'][$id]->created = theme('forum_submitted', $topic);
837      $variables['topics'][$id]->last_reply = theme('forum_submitted', isset($topic->last_reply) ? $topic->last_reply : NULL);
838
839      $variables['topics'][$id]->new_text = '';
840      $variables['topics'][$id]->new_url = '';
841      if ($topic->new_replies) {
842        $variables['topics'][$id]->new_text = format_plural($topic->new_replies, '1 new', '@count new');
843        $variables['topics'][$id]->new_url = url("node/$topic->nid", array('query' => comment_new_page_count($topic->num_comments, $topic->new_replies, $topic), 'fragment' => 'new'));
844      }
845
846    }
847  }
848  else {
849    // Make this safe for the template
850    $variables['topics'] = array();
851  }
852  // Give meaning to $tid for themers. $tid actually stands for term id.
853  $variables['topic_id'] = $variables['tid'];
854  unset($variables['tid']);
855
856  $variables['pager'] = theme('pager', NULL, $variables['forum_per_page'], 0);
857}
858
859/**
860 * Process variables to format the icon for each individual topic.
861 *
862 * $variables contains the following data:
863 * - $new_posts
864 * - $num_posts = 0
865 * - $comment_mode = 0
866 * - $sticky = 0
867 *
868 * @see forum-icon.tpl.php
869 * @see theme_forum_icon()
870 */
871function template_preprocess_forum_icon(&$variables) {
872  $variables['hot_threshold'] = variable_get('forum_hot_topic', 15);
873  if ($variables['num_posts'] > $variables['hot_threshold']) {
874    $variables['icon'] = $variables['new_posts'] ? 'hot-new' : 'hot';
875  }
876  else {
877    $variables['icon'] = $variables['new_posts'] ? 'new' : 'default';
878  }
879
880  if ($variables['comment_mode'] == COMMENT_NODE_READ_ONLY || $variables['comment_mode'] == COMMENT_NODE_DISABLED) {
881    $variables['icon'] = 'closed';
882  }
883
884  if ($variables['sticky'] == 1) {
885    $variables['icon'] = 'sticky';
886  }
887}
888
889/**
890 * Preprocess variables to format the next/previous forum topic navigation links.
891 *
892 * $variables contains $node.
893 *
894 * @see forum-topic-navigation.tpl.php
895 * @see theme_forum_topic_navigation()
896 */
897function template_preprocess_forum_topic_navigation(&$variables) {
898  $output = '';
899
900  // get previous and next topic
901  $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 ORDER BY n.sticky DESC, ". _forum_get_topic_order_sql(variable_get('forum_order', 1));
902  $result = db_query(db_rewrite_sql($sql), isset($variables['node']->tid) ? $variables['node']->tid : 0);
903
904  $stop = $variables['prev'] = $variables['next'] = 0;
905
906  while ($topic = db_fetch_object($result)) {
907    if ($stop == 1) {
908      $variables['next'] = $topic->nid;
909      $variables['next_title'] = check_plain($topic->title);
910      $variables['next_url'] = url("node/$topic->nid");
911      break;
912    }
913    if ($topic->nid == $variables['node']->nid) {
914      $stop = 1;
915    }
916    else {
917      $variables['prev'] = $topic->nid;
918      $variables['prev_title'] = check_plain($topic->title);
919      $variables['prev_url'] = url("node/$topic->nid");
920    }
921  }
922}
923
924/**
925 * Process variables to format submission info for display in the forum list and topic list.
926 *
927 * $variables will contain: $topic
928 *
929 * @see forum-submitted.tpl.php
930 * @see theme_forum_submitted()
931 */
932function template_preprocess_forum_submitted(&$variables) {
933  $variables['author'] = isset($variables['topic']->uid) ? theme('username', $variables['topic']) : '';
934  $variables['time'] = isset($variables['topic']->timestamp) ? format_interval(time() - $variables['topic']->timestamp) : '';
935}
936
937function _forum_user_last_visit($nid) {
938  global $user;
939  static $history = array();
940
941  if (empty($history)) {
942    $result = db_query('SELECT nid, timestamp FROM {history} WHERE uid = %d', $user->uid);
943    while ($t = db_fetch_object($result)) {
944      $history[$t->nid] = $t->timestamp > NODE_NEW_LIMIT ? $t->timestamp : NODE_NEW_LIMIT;
945    }
946  }
947  return isset($history[$nid]) ? $history[$nid] : NODE_NEW_LIMIT;
948}
949
950function _forum_get_topic_order($sortby) {
951  switch ($sortby) {
952    case 1:
953      return array('field' => 'l.last_comment_timestamp', 'sort' => 'desc');
954      break;
955    case 2:
956      return array('field' => 'l.last_comment_timestamp', 'sort' => 'asc');
957      break;
958    case 3:
959      return array('field' => 'l.comment_count', 'sort' => 'desc');
960      break;
961    case 4:
962      return array('field' => 'l.comment_count', 'sort' => 'asc');
963      break;
964  }
965}
966
967function _forum_get_topic_order_sql($sortby) {
968  $order = _forum_get_topic_order($sortby);
969  return $order['field'] .' '. strtoupper($order['sort']);
970}
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.