2001-12-05 18:46:24 +00:00
<?php
// $Id$
2004-08-21 06:42:38 +00:00
/**
* @file
* Enable threaded discussions about general topics.
*/
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_help().
*/
function forum_help($section) {
2004-01-23 18:42:43 +00:00
switch ($section) {
case 'admin/help#forum':
2004-05-09 19:28:43 +00:00
return t("
2004-01-23 18:42:43 +00:00
<h3>Creating a forum</h3>
2004-10-19 18:02:31 +00:00
<p>The forum module uses taxonomy to organize itself. To create a forum you first have to create a <a href=\"%taxonomy\">taxonomy vocabulary</a>. When doing this, choose a sensible name for it (such as \"fora\") and make sure under \"Types\" that \"forum\" is selected. Once you have done this, <a href=\"%taxo-terms\">add some terms</a> to it. Each term will become a forum. If you fill in the description field, users will be given additional information about the forum on the main forum page. For example: \"troubleshooting\" - \"Please ask your questions here.\"</p>
2004-06-21 08:26:20 +00:00
<p>When you are happy with your vocabulary, go to <a href=\"%forums\">administer » settings » forum</a> and set <strong>Forum vocabulary</strong> to the one you have just created. There will now be fora active on the site. For users to access them they must have the \"access content\" <a href=\"%permission\">permission</a> and to create a topic they must have the \"create forum topics\" <a href=\"%permission\">permission</a>. These permissions can be set in the <a href=\"%permission\">permission</a> pages.</p>
2004-01-23 18:42:43 +00:00
<h4>Icons</h4>
2004-06-21 08:26:20 +00:00
<p>To disable icons, set the icon path as blank in <a href=\"%forums\">administer » settings » forum</a>.</p>
2004-06-20 19:49:14 +00:00
<p>All files in the icon directory are assumed to be images. You may use images of whatever size you wish, but it is recommended to use 15x15 or 16x16.</p>", array("%taxonomy" => url('admin/taxonomy/add/vocabulary'), '%taxo-terms' => url('admin/taxonomy'), '%forums' => url('admin/settings/forum'), '%permission' => url('admin/user/configure/permission')));
2004-06-18 15:04:37 +00:00
case 'admin/modules#description':
2004-05-09 19:28:43 +00:00
return t('Enable threaded discussions about general topics.');
2004-06-18 15:04:37 +00:00
case 'admin/settings/forum':
2004-11-23 22:20:41 +00:00
return t("<p>Forums are threaded discussions based on the taxonomy system. For the forums to work, the taxonomy module has to be installed and enabled. When activated, a taxonomy vocabulary (eg. \"forums\") needs to be <a href=\"%created\">created</a> and bound to the node type \"forum topic\".</p>", array('%created' => url('admin/taxonomy/add/vocabulary')));
2004-01-27 18:47:07 +00:00
case 'node/add#forum':
2004-05-09 19:28:43 +00:00
return t('A forum is a threaded discussion, enabling users to communicate about a particular topic.');
2004-01-23 18:42:43 +00:00
}
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_node_name().
*/
2004-01-27 18:47:07 +00:00
function forum_node_name($node) {
2004-02-01 21:32:01 +00:00
return t('forum topic');
2001-12-05 18:46:24 +00:00
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_access().
*/
2001-12-05 18:46:24 +00:00
function forum_access($op, $node) {
2004-11-07 19:28:24 +00:00
global $user;
2004-02-01 21:32:01 +00:00
if ($op == 'create') {
return user_access('create forum topics');
2002-09-15 13:00:12 +00:00
}
2004-11-07 19:28:24 +00:00
if ($op == 'update' || $op == 'delete') {
if (user_access('edit own forum topics') && ($user->uid == $node->uid)) {
return TRUE;
}
}
2001-12-05 18:46:24 +00:00
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_perm().
*/
2002-09-15 13:00:12 +00:00
function forum_perm() {
2004-11-07 19:28:24 +00:00
return array('create forum topics', 'edit own forum topics');
2002-09-15 13:00:12 +00:00
}
2001-12-06 12:31:21 +00:00
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_settings().
*/
2003-02-11 20:01:17 +00:00
function forum_settings() {
2002-09-15 13:00:12 +00:00
2004-02-01 21:32:01 +00:00
if (module_exist('taxonomy')) {
$vocs[0] = '<'. t('none') .'>';
foreach (taxonomy_get_vocabularies('forum') as $vid => $voc) {
2002-12-18 21:43:03 +00:00
$vocs[$vid] = $voc->name;
}
2003-01-02 23:26:43 +00:00
if ($voc) {
2004-06-21 20:05:37 +00:00
$group = form_select(t('Forum vocabulary'), 'forum_nav_vocabulary', variable_get('forum_nav_vocabulary', ''), $vocs, t("The taxonomy vocabulary that will be used as the navigation tree. The vocabulary's terms define the forums."));
2004-03-09 21:34:24 +00:00
$group .= _taxonomy_term_select(t('Containers'), 'forum_containers', variable_get('forum_containers', array()), variable_get('forum_nav_vocabulary', ''), t('You can choose forums which will not have topics, but will be just containers for other forums. This lets you both group and nest forums.'), 1, '<'. t('none') .'>');
2003-11-28 20:03:00 +00:00
$output = form_group(t('Forum structure settings'), $group);
2003-11-27 18:12:57 +00:00
2004-05-09 19:28:43 +00:00
$group .= 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.'));
2004-09-27 20:15:54 +00:00
$group .= form_select(t('Hot topic threshold'), 'forum_hot_topic', variable_get('forum_hot_topic', 15), drupal_map_assoc(array(5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100, 10000)), t('The number of posts a topic must have to be considered <strong>hot</strong>.'));
$group .= form_select(t('Topics per page'), 'forum_per_page', variable_get('forum_per_page', 25), drupal_map_assoc(array(10, 25, 50, 75, 100)), t('The default number of topics displayed per page; links to browse older messages are automatically being displayed.'));
$group .= form_radios(t('Default order'), 'forum_order', variable_get('forum_order', '1'), array(1 => t('Date - newest first'), 2 => t('Date - oldest first'), 3 => t('Posts - most active first'), 4=> t('Posts - least active first')), t('The default display order for topics.'));
2003-11-28 20:03:00 +00:00
$output .= form_group(t('Forum viewing options'), $group);
2002-12-18 21:43:03 +00:00
}
}
2002-12-21 15:53:30 +00:00
2002-09-15 13:00:12 +00:00
return $output;
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_taxonomy().
*/
2003-01-15 23:01:42 +00:00
function forum_taxonomy($op, $type, $object) {
2004-02-01 21:32:01 +00:00
if ($type == 'vocabulary' && ($op == 'insert' || $op == 'update')) {
if (variable_get('forum_nav_vocabulary', '') == '' && in_array('forum', $object['nodes'])) {
2003-01-15 23:01:42 +00:00
// since none is already set, silently set this vocabulary as the navigation vocabulary
2004-02-01 21:32:01 +00:00
variable_set('forum_nav_vocabulary', $object['vid']);
2003-01-15 23:01:42 +00:00
}
}
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_load().
*/
2002-09-15 13:00:12 +00:00
function forum_load($node) {
2004-02-01 21:32:01 +00:00
$forum = db_fetch_object(db_query('SELECT * FROM {forum} WHERE nid = %d', $node->nid));
2002-09-15 13:00:12 +00:00
return $forum;
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_block().
*
* Generates a block containing the currently active forum topics and the
* most recently added forum topics.
*/
2004-10-31 07:34:47 +00:00
function forum_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$blocks[0]['info'] = t('Forum topics');
return $blocks;
2004-03-20 13:23:34 +00:00
2004-10-31 07:34:47 +00:00
case 'configure':
$output = form_select(t('Number of topics in block'), 'forum_block_num', variable_get('forum_block_num', '5'), drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)));
return $output;
2002-11-01 10:47:20 +00:00
2004-10-31 07:34:47 +00:00
case 'save':
variable_set('forum_block_num', $edit['forum_block_num']);
break;
2002-11-09 13:59:36 +00:00
2004-10-31 07:34:47 +00:00
case 'view':
if (user_access('access content')) {
2005-01-16 18:44:49 +00:00
$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";
$sql = node_rewrite_sql($sql);
$content = node_title_list(db_query_range($sql, 0, variable_get('forum_block_num', '5')), t('Active forum topics:'));
2002-09-15 13:00:12 +00:00
2005-01-16 18:44:49 +00:00
$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";
$sql = node_rewrite_sql($sql);
$content .= node_title_list(db_query_range($sql, 0, variable_get('forum_block_num', '5')), t('New forum topics:'));
2002-10-16 18:23:39 +00:00
2004-10-31 07:34:47 +00:00
if ($content) {
$content .= '<div class="more-link">'. l(t('more'), 'forum', array('title' => t('Read the latest forum topics.'))) .'</div>';
}
$block['subject'] = t('Forum topics');
$block['content'] = $content;
return $block;
}
}
2002-09-15 13:00:12 +00:00
}
2004-04-21 13:56:38 +00:00
/**
* Implementation of hook_link().
*/
2002-11-08 13:23:29 +00:00
function forum_link($type, $node = 0, $main = 0) {
2003-01-15 23:01:42 +00:00
global $user;
2002-12-18 21:43:03 +00:00
2003-04-21 14:55:03 +00:00
$links = array();
2004-02-01 21:32:01 +00:00
if (!$main && $type == 'node' && $node->type == 'forum') {
2002-09-15 13:00:12 +00:00
// get previous and next topic
2005-01-17 19:00:03 +00:00
$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));
2005-01-16 18:44:49 +00:00
$sql = node_rewrite_sql($sql);
$result = db_query($sql, $node->tid);
2002-09-15 13:00:12 +00:00
while ($topic = db_fetch_object($result)) {
if ($stop == 1) {
2004-08-22 17:03:42 +00:00
$next = new StdClass();
2002-09-15 13:00:12 +00:00
$next->nid = $topic->nid;
$next->title = $topic->title;
break;
}
if ($topic->nid == $node->nid) {
$stop = 1;
}
else {
2005-01-04 20:54:23 +00:00
$prev = new StdClass();
2002-09-15 13:00:12 +00:00
$prev->nid = $topic->nid;
$prev->title = $topic->title;
}
}
if ($prev) {
2004-06-18 15:04:37 +00:00
$links[] = l(t('previous forum topic'), "node/$prev->nid", array('title' => $prev->title));
2002-09-15 13:00:12 +00:00
}
if ($next) {
2004-06-18 15:04:37 +00:00
$links[] = l(t('next forum topic'), "node/$next->nid", array('title' => $next->title));
2002-09-15 13:00:12 +00:00
}
2002-01-31 20:23:44 +00:00
}
2003-04-21 14:55:03 +00:00
return $links;
2001-12-05 18:46:24 +00:00
}
2004-06-18 15:04:37 +00:00
/**
* Implementation of hook_menu().
*/
2004-09-16 07:17:56 +00:00
function forum_menu($may_cache) {
2004-06-18 15:04:37 +00:00
$items = array();
2004-09-16 07:17:56 +00:00
if ($may_cache) {
$items[] = array('path' => 'node/add/forum', 'title' => t('forum topic'),
'access' => user_access('create forum topics'));
$items[] = array('path' => 'forum', 'title' => t('forums'),
'callback' => 'forum_page',
'access' => user_access('access content'),
2005-01-24 21:01:57 +00:00
'type' => MENU_SUGGESTED_ITEM);
2004-09-16 07:17:56 +00:00
}
2004-06-18 15:04:37 +00:00
return $items;
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_view().
*/
- Patch #5347 by JonBob:
Here's a new patch that unifies the node/52 and book/view/52 paths for nodes. It involves a small change to hook_view(), which is discussed first:
Currently hook_view() expects node modules to return a themed node. However, each module does this the same way; they modify $node as necessary, then call theme('node', $node) and return the result. We can refactor this so that the calling function node_view() calls theme('node') instead. By doing this, it becomes possible for hook_nodeapi('view') to be called after hook_view() where the node contents are filtered, and before theme('node') where the body is enclosed in other HTML. This way the book module can insert its navigation into the body right before the theming.
Advantages of this refactoring:
- I can use it for book.module to remove the extra viewing path.
- The function of hook_nodeapi('view') becomes more like hook_view(), as neither will expect a return value.
- We more closely follow the flow of other nodeapi calls, which usually directly follow their corresponding specific node type hooks (instead of preceding them).
- The attachment.module people could use it to append their attachments in a list after the node.
- Gabor could use it instead of his filter perversion for his "articles in a series" module.
- A little less code in each view hook.
- The content hook is no longer needed, so that means even less code.
Disadvantages:
- Any modules written to use nodeapi('view') could be affected (but these would all be post-4.4 modules).
- Implementations of hook_view() would need to be updated (but return values would be ignored, so most would work without updates anyway).
Now the patch takes advantage of this API shift to inject its navigation at the end of all book nodes, regardless of the viewing path. In fact, since the paths become identical, I've removed the book/view handler entirely. We should probably provide an .htaccess rewrite for this (one is still needed for node/view/nn anyway). At the same time, there is a check in book_block() that shows the block appropriately on these pages.
2004-07-30 13:37:26 +00:00
function forum_view(&$node, $teaser = FALSE, $page = FALSE) {
2003-02-15 11:39:56 +00:00
2003-11-25 19:26:21 +00:00
if ($page) {
2004-01-25 21:11:01 +00:00
$vocabulary = taxonomy_get_vocabulary(variable_get('forum_nav_vocabulary', ''));
2003-09-20 15:11:41 +00:00
// Breadcrumb navigation
2004-06-18 15:04:37 +00:00
$breadcrumb = array();
$breadcrumb[] = array('path' => 'forum', 'title' => $vocabulary->name);
2004-01-25 21:11:01 +00:00
if ($parents = taxonomy_get_parents_all($node->tid)) {
2003-12-24 15:09:43 +00:00
$parents = array_reverse($parents);
foreach ($parents as $p) {
2004-06-18 15:04:37 +00:00
$breadcrumb[] = array('path' => 'forum/'. $p->tid, 'title' => $p->name);
2003-12-24 15:09:43 +00:00
}
}
2004-06-18 15:04:37 +00:00
$breadcrumb[] = array('path' => 'node/'. $node->nid);
menu_set_location($breadcrumb);
2002-11-08 13:23:29 +00:00
}
2003-12-16 21:06:34 +00:00
2004-10-23 17:18:23 +00:00
$node = node_prepare($node, $teaser);
2001-12-05 18:46:24 +00:00
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_validate().
*
* Check in particular that only a "leaf" term in the associated taxonomy
* vocabulary is selected, not a "container" term.
*/
2003-03-07 22:11:44 +00:00
function forum_validate(&$node) {
// Make sure all fields are set properly:
2004-02-01 21:32:01 +00:00
$node->icon = $node->icon ? $node->icon : '';
2004-01-25 21:11:01 +00:00
if ($node->taxonomy) {
// Extract the node's proper topic ID.
2004-02-01 21:32:01 +00:00
$vocabulary = variable_get('forum_nav_vocabulary', '');
2004-02-12 19:04:20 +00:00
$containers = variable_get('forum_containers', array());
2004-01-25 21:11:01 +00:00
foreach ($node->taxonomy as $term) {
2004-02-01 21:32:01 +00:00
if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) {
2004-02-12 19:04:20 +00:00
if (in_array($term, $containers)) {
$term = taxonomy_get_term($term);
2004-08-18 19:57:27 +00:00
form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => "<em>$term->name</em>")));
2004-02-12 19:04:20 +00:00
}
else {
$node->tid = $term;
}
2004-01-25 21:11:01 +00:00
}
2003-03-07 22:11:44 +00:00
}
2004-09-14 05:48:02 +00:00
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;
}
2003-01-15 23:01:42 +00:00
}
}
2004-09-14 05:48:02 +00:00
/**
* Implementation of hook_update().
*/
function forum_update($node) {
db_query('UPDATE {forum} SET tid = %d WHERE nid = %d', $node->tid, $node->nid);
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_form().
*/
2004-07-04 16:50:02 +00:00
function forum_form(&$node) {
2004-02-15 20:16:24 +00:00
if (!$node->nid) {
2003-01-15 23:01:42 +00:00
// new topic
2004-01-25 21:11:01 +00:00
$node->taxonomy[] = arg(3);
2002-05-19 23:05:05 +00:00
}
2004-09-14 05:48:02 +00:00
else {
$node->taxonomy = array($node->tid);
}
2002-05-19 23:05:05 +00:00
2004-07-04 16:50:02 +00:00
$output = implode('', taxonomy_node_form('forum', $node));
2003-01-15 23:01:42 +00:00
if ($node->nid) {
// if editing, give option to leave shadows
2004-09-14 05:48:02 +00:00
$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.'));
2003-01-15 23:01:42 +00:00
}
2002-09-15 13:00:12 +00:00
2004-09-27 20:15:54 +00:00
$output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '');
2004-09-28 19:13:03 +00:00
$output .= filter_form('format', $node->format);
2001-12-05 18:46:24 +00:00
return $output;
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_insert().
*/
2002-09-15 13:00:12 +00:00
function forum_insert($node) {
2004-09-14 05:48:02 +00:00
db_query('INSERT INTO {forum} (nid, tid) VALUES (%d, %d)', $node->nid, $node->tid);
2002-09-15 13:00:12 +00:00
}
2004-05-09 19:28:43 +00:00
/**
* Implementation of hook_delete().
*/
2002-09-15 13:00:12 +00:00
function forum_delete(&$node) {
2004-02-01 21:32:01 +00:00
db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
2002-09-15 13:00:12 +00:00
}
2001-12-05 18:46:24 +00:00
2004-09-14 05:48:02 +00:00
/**
* Formats a topic for display
*
2004-10-19 18:02:31 +00:00
* @TODO Give a better description. Not sure where this function is used yet.
2004-09-14 05:48:02 +00:00
*/
2002-09-15 13:00:12 +00:00
function _forum_format($topic) {
2004-06-29 20:35:58 +00:00
if ($topic && $topic->timestamp) {
2004-02-01 21:32:01 +00:00
return t('%time ago<br />by %author', array('%time' => format_interval(time() - $topic->timestamp), '%author' => format_name($topic)));
2002-09-15 13:00:12 +00:00
}
else {
return message_na();
}
}
2004-09-14 05:48:02 +00:00
/**
* Returns a list of all forums for a given taxonomy id
*
2004-10-19 18:02:31 +00:00
* Forum objects contain the following fields
2004-09-14 05:48:02 +00:00
* -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.
*/
2002-09-15 13:00:12 +00:00
function forum_get_forums($tid = 0) {
2005-01-04 20:54:23 +00:00
2002-09-15 13:00:12 +00:00
if (!$tid) {
$tid = 0;
}
2004-09-14 05:48:02 +00:00
$forums = array();
$_forums = taxonomy_get_tree(variable_get('forum_nav_vocabulary', ''), $tid);
2002-09-15 13:00:12 +00:00
2004-09-14 05:48:02 +00:00
if (count($_forums)) {
2002-09-15 13:00:12 +00:00
2004-09-14 05:48:02 +00:00
$counts = array();
2005-01-16 18:44:49 +00:00
$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";
$sql = node_rewrite_sql($sql);
$_counts = db_query($sql, $forum->tid);
2004-09-14 05:48:02 +00:00
while ($count = db_fetch_object($_counts)) {
$counts[$count->tid] = $count;
}
2002-12-14 23:23:35 +00:00
}
2004-01-31 21:16:42 +00:00
2004-09-14 05:48:02 +00:00
foreach ($_forums as $forum) {
if (in_array($forum->tid, variable_get('forum_containers', array()))) {
$forum->container = 1;
}
2002-09-15 13:00:12 +00:00
2004-09-14 05:48:02 +00:00
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
2004-11-21 08:25:17 +00:00
// used to join node_comment_statistics to users.
2005-01-16 18:44:49 +00:00
$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 /*! USE INDEX (node_comment_timestamp) */, {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";
$sql = node_rewrite_sql($sql);
$topic = db_fetch_object(db_query_range($sql, $forum->tid, 0, 1));
2005-01-04 20:54:23 +00:00
$last_post = new StdClass();
2004-09-14 05:48:02 +00:00
$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;
2002-09-15 13:00:12 +00:00
2004-09-14 05:48:02 +00:00
$forums[$forum->tid] = $forum;
}
return $forums;
2002-09-15 13:00:12 +00:00
}
2004-01-29 22:00:31 +00:00
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.
2005-01-16 18:44:49 +00:00
$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'";
$sql = node_rewrite_sql($sql);
$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";
$sql = node_rewrite_sql($sql);
$recent = db_result(db_query($sql, $uid, $term, NODE_NEW_LIMIT));
2002-09-15 13:00:12 +00:00
2004-01-29 22:00:31 +00:00
return $ancient + $recent;
2002-09-15 13:00:12 +00:00
}
2003-01-15 23:01:42 +00:00
function forum_get_topics($tid, $sortby, $forum_per_page) {
2003-08-21 15:47:50 +00:00
global $user, $forum_topic_list_header;
2002-09-15 13:00:12 +00:00
2003-08-21 15:47:50 +00:00
$forum_topic_list_header = array(
2004-02-01 21:32:01 +00:00
array('data' => ' '),
array('data' => t('Topic'), 'field' => 'n.title'),
2004-09-14 05:48:02 +00:00
array('data' => t('Replies'), 'field' => 'l.comment_count'),
2004-02-01 21:32:01 +00:00
array('data' => t('Created'), 'field' => 'n.created'),
2004-09-14 05:48:02 +00:00
array('data' => t('Last reply'), 'field' => 'l.last_comment_timestamp'),
2003-08-21 15:47:50 +00:00
);
2002-09-15 13:00:12 +00:00
2004-08-09 18:54:49 +00:00
$order = _forum_get_topic_order($sortby);
2003-10-07 18:16:41 +00:00
for ($i = 0; $i < count($forum_topic_list_header); $i++) {
2004-08-09 18:54:49 +00:00
if ($forum_topic_list_header[$i]['field'] == $order['field']) {
$forum_topic_list_header[$i]['sort'] = $order['sort'];
2003-08-21 15:47:50 +00:00
}
}
$term = taxonomy_get_term($tid);
2002-09-15 13:00:12 +00:00
2005-01-19 01:46:25 +00:00
$sql = node_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");
2004-06-27 16:02:31 +00:00
$sql .= tablesort_sql($forum_topic_list_header, 'n.sticky DESC,');
2003-01-15 23:01:42 +00:00
2005-01-19 01:46:25 +00:00
$sql_count = node_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'");
2002-09-15 13:00:12 +00:00
2005-01-17 19:00:03 +00:00
$result = pager_query($sql, $forum_per_page, 0, $sql_count, $tid);
2002-09-15 13:00:12 +00:00
while ($topic = db_fetch_object($result)) {
2003-01-15 23:01:42 +00:00
if ($user->uid) {
// folder is new if topic is new or there are new comments since last visit
2004-09-14 05:48:02 +00:00
if ($topic->tid != $tid) {
2003-01-15 23:01:42 +00:00
$topic->new = 0;
2002-09-15 13:00:12 +00:00
}
else {
2004-08-09 18:54:49 +00:00
$history = _forum_user_last_visit($topic->nid);
2004-09-14 05:48:02 +00:00
$topic->new_replies = comment_num_new($topic->nid, $history);
2004-01-29 22:00:31 +00:00
$topic->new = $topic->new_replies || ($topic->timestamp > $history);
2002-09-15 13:00:12 +00:00
}
2004-01-29 22:00:31 +00:00
}
else {
2004-05-09 19:28:43 +00:00
// Do not track "new replies" status for topics if the user is anonymous.
2003-01-15 23:01:42 +00:00
$topic->new_replies = 0;
$topic->new = 0;
2004-01-29 22:00:31 +00:00
}
2002-09-15 13:00:12 +00:00
2004-09-14 05:48:02 +00:00
if ($topic->num_comments > 0) {
2005-01-04 20:54:23 +00:00
$last_reply = new StdClass();
2004-09-14 05:48:02 +00:00
$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;
}
2002-09-15 13:00:12 +00:00
$topics[] = $topic;
}
2003-01-15 23:01:42 +00:00
return $topics;
2002-09-15 13:00:12 +00:00
}
2004-09-14 05:48:02 +00:00
/**
* Finds the first unread node for a given forum.
*/
2003-01-15 23:01:42 +00:00
function _forum_new($tid) {
2002-09-15 13:00:12 +00:00
global $user;
2005-01-16 18:44:49 +00:00
$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";
$sql = node_rewrite_sql($sql);
$nid = db_result(db_query_range($sql, $user->uid, $tid, NODE_NEW_LIMIT, 0, 1));
2002-09-15 13:00:12 +00:00
return $nid ? $nid : 0;
}
2004-05-09 19:28:43 +00:00
/**
2004-05-17 22:00:06 +00:00
* Menu callback; prints a forum listing.
2004-05-09 19:28:43 +00:00
*/
2004-11-06 11:54:09 +00:00
function forum_page($tid = 0) {
2004-08-09 18:54:49 +00:00
global $user;
2003-06-10 17:33:43 +00:00
2004-02-15 20:09:46 +00:00
if (module_exist('taxonomy')) {
2004-11-06 11:54:09 +00:00
$forum_per_page = variable_get('forum_per_page', 25);
$sortby = variable_get('forum_order', 1);
2002-09-15 13:00:12 +00:00
2004-11-06 11:54:09 +00:00
$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);
2002-12-18 21:43:03 +00:00
}
2004-11-06 11:54:09 +00:00
2005-01-22 08:38:25 +00:00
print theme('page', theme('forum_display', $forums, $topics, $parents, $tid, $sortby, $forum_per_page));
2001-12-05 18:46:24 +00:00
}
else {
2004-12-15 21:19:42 +00:00
drupal_set_title(t('Warning'));
print theme('page', forum_help('admin/settings/forum'));
2001-12-05 18:46:24 +00:00
}
}
2003-11-09 23:27:22 +00:00
/**
2003-12-08 06:32:19 +00:00
* Format the forum body.
*
2004-09-09 05:51:08 +00:00
* @ingroup themeable
2003-12-08 06:32:19 +00:00
*/
2004-08-09 18:54:49 +00:00
function theme_forum_display($forums, $topics, $parents, $tid, $sortby, $forum_per_page) {
2004-03-20 13:23:34 +00:00
global $user;
2004-02-01 21:32:01 +00:00
// forum list, topics list, topic browser and 'add new topic' link
2003-02-15 11:39:56 +00:00
2004-01-25 21:11:01 +00:00
$vocabulary = taxonomy_get_vocabulary(variable_get('forum_nav_vocabulary', ''));
2004-12-15 21:19:42 +00:00
drupal_set_title($title = $vocabulary->name);
2002-09-15 13:00:12 +00:00
2004-06-18 15:04:37 +00:00
// Breadcrumb navigation:
$breadcrumb = array();
2003-11-25 19:26:21 +00:00
if ($tid) {
2004-06-18 15:04:37 +00:00
$breadcrumb[] = array('path' => 'forum', 'title' => $title);
2003-11-25 19:26:21 +00:00
}
2002-09-15 13:00:12 +00:00
if ($parents) {
2003-08-15 15:17:23 +00:00
$parents = array_reverse($parents);
foreach ($parents as $p) {
2003-08-22 17:06:44 +00:00
if ($p->tid == $tid) {
$title = $p->name;
2002-09-15 13:00:12 +00:00
}
else {
2004-06-18 15:04:37 +00:00
$breadcrumb[] = array('path' => 'forum/'. $p->tid, 'title' => $p->name);
2002-09-15 13:00:12 +00:00
}
}
}
2004-06-18 15:04:37 +00:00
$breadcrumb[] = array('path' => $_GET['q']);
menu_set_location($breadcrumb);
2002-09-15 13:00:12 +00:00
2003-11-05 17:40:41 +00:00
if (count($forums) || count($parents)) {
2004-05-09 19:28:43 +00:00
$output = '<div id="forum">';
$output .= '<ul>';
2004-03-20 13:23:34 +00:00
if (module_exist('tracker')) {
if ($user->uid) {
2004-07-08 15:19:08 +00:00
$output .= ' <li>'. l(t('My forum discussions.'), "tracker/$user->uid") .'</li>';
2004-03-20 13:23:34 +00:00
}
2004-07-08 15:19:08 +00:00
$output .= ' <li>'. l(t('Active forum discussions.'), 'tracker') .'</li>';
2004-03-20 13:23:34 +00:00
}
if (user_access('create forum topics')) {
2004-05-09 19:28:43 +00:00
$output .= '<li>'. l(t('Post new forum topic.'), "node/add/forum/$tid") .'</li>';
2004-03-20 13:23:34 +00:00
}
else if ($user->uid) {
2004-05-09 19:28:43 +00:00
$output .= '<li>'. t('You are not allowed to post a new forum topic.') .'</li>';
2004-03-20 13:23:34 +00:00
}
else {
$output .= '<li>'. t('<a href="%login">Login</a> to post a new forum topic.', array('%login' => url('user/login'))) .'</li>';
}
2004-05-09 19:28:43 +00:00
$output .= '</ul>';
2004-03-20 13:23:34 +00:00
2004-02-01 21:32:01 +00:00
$output .= theme('forum_list', $forums, $parents, $tid);
2003-08-15 15:17:23 +00:00
2004-02-01 21:32:01 +00:00
if ($tid && !in_array($tid, variable_get('forum_containers', array()))) {
2004-08-09 18:54:49 +00:00
$output .= theme('forum_topic_list', $tid, $topics, $sortby, $forum_per_page);
2003-11-05 17:40:41 +00:00
}
2004-05-09 19:28:43 +00:00
$output .= '</div>';
2003-11-05 17:40:41 +00:00
}
else {
2004-12-15 21:19:42 +00:00
drupal_set_title(t('No forums defined'));
2003-11-05 17:40:41 +00:00
$output = '';
2003-08-15 15:17:23 +00:00
}
2005-01-22 08:38:25 +00:00
return $output;
2003-08-15 15:17:23 +00:00
}
2003-11-09 23:27:22 +00:00
/**
2003-12-08 06:32:19 +00:00
* Format the forum listing.
*
2004-09-09 05:51:08 +00:00
* @ingroup themeable
2003-12-08 06:32:19 +00:00
*/
2003-11-09 23:27:22 +00:00
function theme_forum_list($forums, $parents, $tid) {
2003-08-15 15:17:23 +00:00
global $user;
2002-09-15 13:00:12 +00:00
if ($forums) {
2004-02-01 21:32:01 +00:00
$header = array(t('Forum'), t('Topics'), t('Posts'), t('Last post'));
2002-09-15 13:00:12 +00:00
foreach ($forums as $forum) {
2003-10-20 17:32:48 +00:00
if ($forum->container) {
2004-05-09 19:28:43 +00:00
$description = '<div style="margin-left: '. ($forum->depth * 30) ."px;\">\n";
$description .= ' <div class="name">'. l($forum->name, "forum/$forum->tid") ."</div>\n";
2004-01-21 18:34:18 +00:00
if ($forum->description) {
$description .= " <div class=\"description\">$forum->description</div>\n";
}
$description .= "</div>\n";
2004-11-15 11:16:39 +00:00
$rows[] = array(array('data' => $description, 'class' => 'container', 'colspan' => '4'));
2002-11-08 13:23:29 +00:00
}
2003-10-20 17:32:48 +00:00
else {
2004-01-29 22:00:31 +00:00
$forum->old_topics = _forum_topics_read($forum->tid, $user->uid);
2003-10-20 17:32:48 +00:00
if ($user->uid) {
$new_topics = $forum->num_topics - $forum->old_topics;
}
2004-01-21 18:34:18 +00:00
else {
$new_topics = 0;
}
2002-09-15 13:00:12 +00:00
2004-05-09 19:28:43 +00:00
$description = '<div style="margin-left: '. ($forum->depth * 30) ."px;\">\n";
$description .= ' <div class="name">'. l($forum->name, "forum/$forum->tid") ."</div>\n";
2003-10-20 17:32:48 +00:00
2004-01-21 18:34:18 +00:00
if ($forum->description) {
$description .= " <div class=\"description\">$forum->description</div>\n";
}
$description .= "</div>\n";
2003-08-15 15:17:23 +00:00
2004-01-21 18:34:18 +00:00
$rows[] = array(
2004-02-01 21:32:01 +00:00
array('data' => $description, 'class' => 'forum'),
2004-05-09 19:28:43 +00:00
array('data' => $forum->num_topics . ($new_topics ? '<br />'. l(t('%a new', array('%a' => $new_topics)), "forum/$forum->tid", NULL, NULL, 'new') : ''), 'class' => 'topics'),
2004-02-01 21:32:01 +00:00
array('data' => $forum->num_posts, 'class' => 'posts'),
array('data' => _forum_format($forum->last_post), 'class' => 'last-reply'));
2004-01-21 18:34:18 +00:00
}
2002-09-15 13:00:12 +00:00
}
2004-10-09 17:15:55 +00:00
return theme('table', $header, $rows);
2002-09-15 13:00:12 +00:00
}
}
2003-11-09 23:27:22 +00:00
/**
2003-12-08 06:32:19 +00:00
* Format the topic listing.
*
2004-09-09 05:51:08 +00:00
* @ingroup themeable
2003-12-08 06:32:19 +00:00
*/
2004-08-09 18:54:49 +00:00
function theme_forum_topic_list($tid, $topics, $sortby, $forum_per_page) {
global $forum_topic_list_header;
2002-09-15 13:00:12 +00:00
if ($topics) {
2003-08-15 15:17:23 +00:00
2002-09-15 13:00:12 +00:00
foreach ($topics as $topic) {
// folder is new if topic is new or there are new comments since last visit
2003-01-15 23:01:42 +00:00
if ($topic->tid != $tid) {
2003-08-15 15:17:23 +00:00
$rows[] = array(
2004-06-27 16:02:31 +00:00
array('data' => _forum_icon($topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky), 'class' => 'icon'),
2004-02-01 21:32:01 +00:00
array('data' => $topic->title, 'class' => 'title'),
array('data' => l(t('This topic has been moved'), "forum/$topic->tid"), 'colspan' => '3')
2003-08-15 15:17:23 +00:00
);
2002-09-15 13:00:12 +00:00
}
else {
2003-08-15 15:17:23 +00:00
$rows[] = array(
2004-06-27 16:02:31 +00:00
array('data' => _forum_icon($topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky), 'class' => 'icon'),
2004-06-18 15:04:37 +00:00
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'),
2004-02-01 21:32:01 +00:00
array('data' => _forum_format($topic), 'class' => 'created'),
array('data' => _forum_format($topic->last_reply), 'class' => 'last-reply')
2003-08-15 15:17:23 +00:00
);
2002-09-15 13:00:12 +00:00
}
}
2004-02-01 21:32:01 +00:00
if ($pager = theme('pager', NULL, $forum_per_page, 0, tablesort_pager())) {
$rows[] = array(array('data' => $pager, 'colspan' => '5', 'class' => 'pager'));
2003-08-15 15:17:23 +00:00
}
}
2002-09-15 13:00:12 +00:00
2004-02-01 21:32:01 +00:00
$output .= theme('table', $forum_topic_list_header, $rows);
2003-08-15 15:17:23 +00:00
2002-09-15 13:00:12 +00:00
return $output;
}
2004-06-27 16:02:31 +00:00
function _forum_icon($new_posts, $num_posts = 0, $comment_mode = 0, $sticky = 0) {
2002-09-15 13:00:12 +00:00
2004-02-01 21:32:01 +00:00
$base_path = variable_get('forum_icon_path', '');
2002-09-15 13:00:12 +00:00
if ($base_path) {
2004-02-01 21:32:01 +00:00
if ($num_posts > variable_get('forum_hot_topic', 15)) {
$icon = $new_posts ? 'hot-new' : 'hot';
2002-09-15 13:00:12 +00:00
}
else {
2004-02-01 21:32:01 +00:00
$icon = $new_posts ? 'new' : 'default';
2002-09-15 13:00:12 +00:00
}
if ($comment_mode == 1) {
2004-02-01 21:32:01 +00:00
$icon = 'closed';
2002-09-15 13:00:12 +00:00
}
2004-06-27 16:02:31 +00:00
if ($sticky == 1) {
$icon = 'sticky';
}
2003-02-15 11:39:56 +00:00
// default
2004-08-04 20:40:01 +00:00
$file = "misc/forum-$icon.png";
2002-09-15 13:00:12 +00:00
2004-08-04 20:40:01 +00:00
$output = theme('image', $file);
2002-09-15 13:00:12 +00:00
}
else {
2004-02-01 21:32:01 +00:00
$output = ' ';
2002-09-15 13:00:12 +00:00
}
2004-01-28 22:10:34 +00:00
if ($new_posts) {
$output = "<a name=\"new\">$output</a>";
}
return $output;
2002-09-15 13:00:12 +00:00
}
function _forum_user_last_visit($nid) {
global $user;
2004-01-29 22:00:31 +00:00
static $history = array();
if (empty($history)) {
2004-02-01 21:32:01 +00:00
$result = db_query('SELECT nid, timestamp FROM {history} WHERE uid = %d', $user->uid);
2002-09-15 13:00:12 +00:00
while ($t = db_fetch_object($result)) {
2004-01-29 22:00:31 +00:00
$history[$t->nid] = $t->timestamp > NODE_NEW_LIMIT ? $t->timestamp : NODE_NEW_LIMIT;
2002-09-15 13:00:12 +00:00
}
}
2004-01-29 22:00:31 +00:00
return $history[$nid] ? $history[$nid] : NODE_NEW_LIMIT;
2002-09-15 13:00:12 +00:00
}
function _forum_get_topic_order($sortby) {
switch ($sortby) {
case 1:
2004-09-14 05:48:02 +00:00
return array('field' => 'l.last_comment_timestamp', 'sort' => 'desc');
2002-09-15 13:00:12 +00:00
break;
case 2:
2004-09-14 05:48:02 +00:00
return array('field' => 'l.last_comment_timestamp', 'sort' => 'asc');
2002-09-15 13:00:12 +00:00
break;
case 3:
2004-09-14 05:48:02 +00:00
return array('field' => 'l.comment_count', 'sort' => 'desc');
2002-09-15 13:00:12 +00:00
break;
case 4:
2004-09-14 05:48:02 +00:00
return array('field' => 'l.comment_count', 'sort' => 'asc');
2002-09-15 13:00:12 +00:00
break;
}
}
2004-08-09 18:54:49 +00:00
function _forum_get_topic_order_sql($sortby) {
$order = _forum_get_topic_order($sortby);
return $order['field'] .' '. $order['sort'];
}
2002-12-18 21:43:03 +00:00
?>