2002-02-16 13:38:00 +00:00
<?php
2001-10-20 18:57:09 +00:00
// $Id$
2000-12-14 14:13:37 +00:00
2004-07-10 07:58:47 +00:00
/**
* @file
2004-08-21 06:42:38 +00:00
* Enables users to comment on published content.
2004-07-10 07:58:47 +00:00
*
* When enabled, the Drupal comment module creates a discussion
* board for each Drupal node. Users can post comments to discuss
* a forum topic, weblog post, story, collaborative book page, etc.
*/
2005-05-05 20:12:49 +00:00
/*
* Constants
*/
define('COMMENT_PUBLISHED', 0);
define('COMMENT_NOT_PUBLISHED', 1);
2004-06-04 18:50:29 +00:00
/**
* Implementation of hook_help().
*/
2004-07-10 07:58:47 +00:00
function comment_help($section = "admin/help#comment") {
2003-08-05 18:33:39 +00:00
switch ($section) {
2003-10-09 18:53:22 +00:00
case 'admin/help#comment':
2004-06-04 18:50:29 +00:00
return t("
2004-07-10 07:58:47 +00:00
<p>When enabled, the Drupal comment module creates a discussion board for each Drupal node. Users can post comments to discuss a forum topic, weblog post, story, collaborative book page, etc. An administrator can give comment permissions to user groups, and users can (optionally) edit their last comment, assuming no others have been posted since.</p>
2004-01-23 18:42:43 +00:00
<h3>User control of comment display</h3>
<p>Attached to each comment board is a control panel for customizing the way that comments are displayed. Users can control the chronological ordering of posts (newest or oldest first) and the number of posts to display on each page. Additional settings include:</p>
2004-07-10 07:58:47 +00:00
<ul><li><strong>Threaded</strong> — Displays the posts grouped according to conversations and subconversations.</li>
<li><strong>Flat</strong> — Displays the posts in chronological order, with no threading whatsoever.</li>
<li><strong>Expanded</strong> — Displays the title and text for each post.</li>
<li><strong>Collapsed</strong> — Displays only the title for each post.</li></ul>
2005-10-07 06:11:12 +00:00
<p>When a user chooses <em>save settings</em>, the comments are then redisplayed using the user's new choices. Administrators can set the default settings for the comment control panel, along with other comment defaults, in <a href=\"%comment-config\">administer » comments » configure</a>.</p>
2003-08-05 18:33:39 +00:00
2004-01-23 18:42:43 +00:00
<h3>Additional comment configurations</h3>
2005-02-12 07:51:14 +00:00
<p>Comments behave like other user submissions in Drupal. Filters, smileys and HTML that work in nodes will also work with comments. Administrators can control access to various comment module functions through <a href=\"%permissions\">administer » access control » permissions</a>. Know that in a new Drupal installation, all comment permissions are disabled by default. The choice of which permissions to grant to which roles (groups of users) is left up to the site administrator. The following permissions:</p>
2004-07-10 07:58:47 +00:00
<ul><li><strong>Access comments</strong> — Allows users to view comments.</li>
<li><strong>Administrate comments</strong> — Allows users complete control over configuring, editing and deleting all comments.</li>
<li><strong>Post comments</strong> — Allows users to post comments into an administrator moderation queue.</li>
<li><strong>Post comments without approval</strong> — Allows users to directly post comments, bypassing the moderation queue.</li></ul>
2003-08-05 18:33:39 +00:00
2004-01-23 18:42:43 +00:00
<h3>Notification of new comments</h3>
2004-07-10 07:58:47 +00:00
<p>Drupal provides specific features to inform site members when new comments have been posted.</p>
<p>Drupal displays the total number of comments attached to each node, and tracks comments read by individual site members. Members which have logged in will see a notice accompanying nodes which contain comments they have not read. Some administrators may want to <a href=\"%download-notify\">download, install and configure the notify module</a>. Users can then request that Drupal send them an e-mail when new comments are posted (the notify module requires that cron.php be configured properly).</p>
2005-10-07 06:11:12 +00:00
<p>The <em>tracker</em> module, disabled by default, displays all the site's recent posts. There is a link to the <a href=\"%tracker\">recent posts</a> page in the navigation block. This page is a useful way to browse new or updated nodes and comments. Content which the user has not yet read is tagged with a red star (this graphic depends on the current theme). Visit the comment board for any node, and Drupal will display a red <em>\"new\"</em> label beside the text of unread comments.</p>", array('%comment-config' => url('admin/comment/configure'), '%permissions' => url('admin/access/permissions'), '%tracker' => url('tracker'), '%download-notify' => 'http://drupal.org/project/releases', '%comment-initial' => url('admin/comment/configure/roles')));
2003-10-03 14:55:27 +00:00
case 'admin/comment':
2004-06-20 20:12:00 +00:00
case 'admin/comment/new':
2005-05-14 17:23:18 +00:00
return t("<p>Below is a list of the latest comments posted to your site. Click on a subject to see the comment, the author's name to edit the author's user information , \"edit\" to modify the text, and \"delete\" to remove their submission.</p>");
2004-06-18 15:04:37 +00:00
case 'admin/comment/approval':
2005-03-18 07:07:04 +00:00
return t("<p>Below is a list of the comments posted to your site that need approval. To approve a comment, click on \"edit\" and then change its \"moderation status\" to Approved. Click on a subject to see the comment, the author's name to edit the author's user information, \"edit\" to modify the text, and \"delete\" to remove their submission.</p>");
2004-07-10 07:58:47 +00:00
case 'admin/comment/configure':
case 'admin/comment/configure/settings':
2005-03-18 07:07:04 +00:00
return t("<p>Comments can be attached to any node, and their settings are below. The display comes in two types: a \"flat list\" where everything is flush to the left side, and comments come in chronological order, and a \"threaded list\" where replies to other comments are placed immediately below and slightly indented, forming an outline. They also come in two styles: \"expanded\", where you see both the title and the contents, and \"collapsed\" where you only see the title. Preview comment forces a user to look at their comment by clicking on a \"Preview\" button before they can actually add the comment.</p>");
2004-07-10 07:58:47 +00:00
case 'admin/modules#description':
2005-04-01 15:55:02 +00:00
return t('Allows users to comment on and discuss published content.');
2004-06-04 18:50:29 +00:00
}
2002-02-22 19:44:22 +00:00
}
2004-07-08 19:58:10 +00:00
/**
* Implementation of hook_menu().
*/
2004-09-16 07:17:56 +00:00
function comment_menu($may_cache) {
2004-07-08 19:58:10 +00:00
$items = array();
2004-09-16 07:17:56 +00:00
if ($may_cache) {
$access = user_access('administer comments');
$items[] = array('path' => 'admin/comment', 'title' => t('comments'),
'callback' => 'comment_admin_overview', 'access' => $access);
// Tabs:
$items[] = array('path' => 'admin/comment/list', 'title' => t('list'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/comment/configure', 'title' => t('configure'),
'callback' => 'comment_configure', 'access' => $access, 'type' => MENU_LOCAL_TASK);
// Subtabs:
$items[] = array('path' => 'admin/comment/list/new', 'title' => t('new comments'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/comment/list/approval', 'title' => t('approval queue'),
'callback' => 'comment_admin_overview', 'access' => $access,
2005-09-07 20:45:53 +00:00
'callback arguments' => array('approval'),
2004-09-16 07:17:56 +00:00
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/comment/configure/settings', 'title' => t('settings'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$access = user_access('post comments');
2005-07-19 17:51:59 +00:00
$items[] = array('path' => 'comment/reply', 'title' => t('reply to comment'),
'callback' => 'comment_save_settings', 'access' => 1, 'type' => MENU_CALLBACK);
2004-12-15 21:19:42 +00:00
$items[] = array('path' => 'comment/edit', 'title' => t('edit comment'),
2004-09-16 07:17:56 +00:00
'callback' => 'comment_edit', 'access' => $access, 'type' => MENU_CALLBACK);
2005-07-19 17:51:59 +00:00
$items[] = array('path' => 'comment/delete', 'title' => t('delete comment'),
'callback' => 'comment_delete', 'access' => $access, 'type' => MENU_CALLBACK);
2004-07-08 19:58:10 +00:00
}
2005-03-20 19:42:14 +00:00
else {
if (arg(0) == 'comment' && arg(1) == 'reply' && is_numeric(arg(2))) {
2005-07-17 18:29:32 +00:00
$node = node_load(arg(2));
2005-03-20 19:42:14 +00:00
if ($node->nid) {
$items[] = array('path' => 'comment/reply', 'title' => t('reply to comment'),
'callback' => 'comment_reply', 'access' => node_access('view', $node), 'type' => MENU_CALLBACK);
}
}
if ((arg(0) == 'node') && is_numeric(arg(1)) && is_numeric(arg(2))) {
$items[] = array('path' => ('node/'. arg(1) .'/'. arg(2)), 'title' => t('view'),
'callback' => 'node_page',
'type' => MENU_CALLBACK);
}
2004-10-16 07:22:26 +00:00
}
2004-07-08 19:58:10 +00:00
return $items;
}
/**
* Implementation of hook_perm().
*/
function comment_perm() {
2005-10-07 06:11:12 +00:00
return array('access comments', 'post comments', 'administer comments', 'post comments without approval');
2004-07-08 19:58:10 +00:00
}
/**
* Implementation of hook_block().
*
* Generates a block with the most recent comments.
*/
function comment_block($op = 'list', $delta = 0) {
if ($op == 'list') {
$blocks[0]['info'] = t('Recent comments');
return $blocks;
}
2004-10-31 07:34:47 +00:00
else if ($op == 'view' && user_access('access comments')) {
2005-09-19 15:11:05 +00:00
$result = db_query_range(db_rewrite_sql('SELECT c.nid, c.* FROM {comments} c INNER JOIN {node} n ON n.nid = c.nid WHERE n.status = 1 AND c.status = %d ORDER BY c.timestamp DESC', 'c'), COMMENT_PUBLISHED, 0, 10);
2004-07-08 19:58:10 +00:00
$items = array();
while ($comment = db_fetch_object($result)) {
2004-10-15 05:10:35 +00:00
$items[] = l($comment->subject, 'node/'. $comment->nid, NULL, NULL, 'comment-'. $comment->cid) .'<br />'. t('%time ago', array('%time' => format_interval(time() - $comment->timestamp)));
2004-07-08 19:58:10 +00:00
}
$block['subject'] = t('Recent comments');
$block['content'] = theme('item_list', $items);
return $block;
}
}
/**
* Implementation of hook_link().
*/
function comment_link($type, $node = 0, $main = 0) {
$links = array();
if ($type == 'node' && $node->comment) {
if ($main) {
// Main page: display the number of comments that have been posted.
if (user_access('access comments')) {
$all = comment_num_all($node->nid);
$new = comment_num_new($node->nid);
if ($all) {
$links[] = l(format_plural($all, '1 comment', '%count comments'), "node/$node->nid", array('title' => t('Jump to the first comment of this posting.')), NULL, 'comment');
if ($new) {
$links[] = l(format_plural($new, '1 new comment', '%count new comments'), "node/$node->nid", array('title' => t('Jump to the first new comment of this posting.')), NULL, 'new');
}
}
else {
if ($node->comment == 2) {
if (user_access('post comments')) {
$links[] = l(t('add new comment'), "comment/reply/$node->nid", array('title' => t('Add a new comment to this page.')));
}
else {
$links[] = theme('comment_post_forbidden');
}
}
}
}
}
else {
// Node page: add a "post comment" link if the user is allowed to
// post comments, if this node is not read-only, and if the comment form isn't already shown
if ($node->comment == 2 && variable_get('comment_form_location', 0) == 0) {
if (user_access('post comments')) {
$links[] = l(t('add new comment'), "comment/reply/$node->nid", array('title' => t('Share your thoughts and opinions related to this posting.')), NULL, 'comment');
}
else {
$links[] = theme('comment_post_forbidden');
}
}
}
}
if ($type == 'comment') {
$links = comment_links($node, $main);
}
return $links;
}
/**
* Implementation of hook_nodeapi().
2004-09-14 05:48:02 +00:00
*
2004-07-08 19:58:10 +00:00
*/
function comment_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'settings':
2005-10-11 19:44:35 +00:00
$form['comment_'. $node->type] = array('#type' => 'radios', '#title' => t('Default comment setting'), '#default_value' => variable_get('comment_'. $node->type, 2), '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')), '#description' => t('Users with the <em>administer comments</em> permission will be able to override this setting.'));
2005-10-07 06:11:12 +00:00
return $form;
2004-07-08 19:58:10 +00:00
case 'fields':
return array('comment');
2005-01-24 21:20:16 +00:00
2005-10-07 06:11:12 +00:00
case 'form':
2004-07-08 19:58:10 +00:00
if (user_access('administer comments')) {
$selected = isset($node->comment) ? $node->comment : variable_get("comment_$node->type", 2);
2005-10-11 19:44:35 +00:00
$form['user_comments'] = array('#type' => 'fieldset', '#title' => t('User Comments'), '#collapsible' => TRUE, '#collapsed' => TRUE);
$form['user_comments']['comment'] = array('#type' => 'radios', '#parents' => array('comment'), '#default_value' => $selected, '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')));
2005-10-07 06:11:12 +00:00
return $form;
2004-07-08 19:58:10 +00:00
}
break;
2005-01-24 21:20:16 +00:00
2004-09-14 05:48:02 +00:00
case 'load':
2005-02-11 19:01:53 +00:00
return db_fetch_array(db_query("SELECT last_comment_timestamp, last_comment_name, comment_count FROM {node_comment_statistics} WHERE nid = %d", $node->nid));
2004-07-08 19:58:10 +00:00
case 'validate':
2005-07-25 09:41:29 +00:00
if (!user_access('administer comments')) {
2004-07-08 19:58:10 +00:00
// Force default for normal users:
$node->comment = variable_get("comment_$node->type", 2);
}
break;
2005-01-24 21:20:16 +00:00
2004-09-14 05:48:02 +00:00
case 'insert':
2005-02-11 19:01:53 +00:00
db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->created, $node->uid);
2004-12-11 11:41:17 +00:00
break;
2005-01-24 21:20:16 +00:00
2004-07-08 19:58:10 +00:00
case 'delete':
2004-09-14 05:48:02 +00:00
db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid);
db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
2004-07-08 19:58:10 +00:00
break;
2005-01-24 21:20:16 +00:00
2004-12-31 09:30:12 +00:00
case 'update index':
$text = '';
2005-05-05 20:12:49 +00:00
$comments = db_query('SELECT subject, comment, format FROM {comments} WHERE nid = %d AND status = %d', $node->nid, COMMENT_PUBLISHED);
2004-12-31 09:30:12 +00:00
while ($comment = db_fetch_object($comments)) {
2005-07-29 21:06:33 +00:00
$text .= '<h2>'. check_plain($comment->subject) .'</h2>'. check_markup($comment->comment, $comment->format, FALSE);
2004-12-31 09:30:12 +00:00
}
return $text;
2005-01-24 21:20:16 +00:00
2004-12-31 09:30:12 +00:00
case 'search result':
$comments = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $node->nid));
return format_plural($comments, '1 comment', '%count comments');
2005-09-19 19:13:35 +00:00
2005-09-18 10:37:57 +00:00
case 'rss item':
return array(array('key' => 'comments', 'value' => url('node/'.$node->nid, NULL, 'comment', TRUE)));
2004-07-08 19:58:10 +00:00
}
}
/**
* Implementation of hook_user().
*
* Provides signature customization for the user's comments.
*/
function comment_user($type, $edit, &$user, $category = NULL) {
if ($type == 'form' && $category == 'account') {
// when user tries to edit his own data
2005-10-11 19:44:35 +00:00
$form['comment_settings'] = array('#type' => 'fieldset', '#title' => t('Comment settings'), '#collapsible' => TRUE, '#collapsed' => FALSE, '#weight' => 4);
$form['comment_settings']['signature'] = array('#type' => 'textarea', '#title' => t('Signature'), '#default_value' => $edit['comment_settings']['signature'], '#cols' => 60, '#rows' => 5, '#description' => ('Your signature will be publicly displayed at the end of your comments.'));
2005-10-07 06:11:12 +00:00
return $form;
2004-07-08 19:58:10 +00:00
}
}
2004-06-04 18:50:29 +00:00
/**
2004-06-18 15:04:37 +00:00
* Menu callback; presents the comment settings page.
2004-06-04 18:50:29 +00:00
*/
2004-06-18 15:04:37 +00:00
function comment_configure() {
2005-10-11 19:44:35 +00:00
$form['viewing_options'] = array('#type' => 'fieldset', '#title' => t('Comment viewing options'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => 0);
2004-06-18 15:04:37 +00:00
2005-10-11 19:44:35 +00:00
$form['viewing_options']['comment_default_mode'] = array('#type' => 'radios', '#title' => t('Default display mode'), '#default_value' => variable_get('comment_default_mode', 4), '#options' => _comment_get_modes(), '#description' => t('The default view for comments. Expanded views display the body of the comment. Threaded views keep replies together.'));
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['viewing_options']['comment_default_order'] = array('#type' => 'radios', '#title' => t('Default display order'), '#default_value' => variable_get('Default display order', 1), '#options' => _comment_get_orders(), '#description' => t('The default sorting for new users and anonymous users while viewing comments. These users may change their view using the comment control panel. For registered users, this change is remembered as a persistent user preference.'));
2002-01-03 22:02:23 +00:00
2005-10-07 06:11:12 +00:00
$form['viewing_options']['comment_default_per_page'] = array(
2005-10-11 19:44:35 +00:00
'#type' => 'select',
'#title' => t('Default comments per page'),
'#default_value' => variable_get('comment_default_per_page', 50),
'#options' => _comment_per_page(),
'#description' => t('Default number of comments for each page: more comments are distributed in several pages.')
2005-10-07 06:11:12 +00:00
);
2005-10-11 19:44:35 +00:00
$form['viewing_options']['comment_controls'] = array('#type' => 'radios', '#title' => t('Comment controls'), '#default_value' => variable_get('comment_controls', 3), '#options' => array(t('Display above the comments'), t('Display below the comments'), t('Display above and below the comments'), t('Do not display')), '#description' => t('Position of the comment controls box. The comment controls let the user change the default display mode and display order of comments.'));
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['posting_settings'] = array('#type' => 'fieldset', '#title' => t('Comment posting settings'), '#collapsible' => true, '#collapsed' => true, '#weight' => 0);
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['posting_settings']['comment_anonymous'] = array('#type' => 'radios', '#title' => t('Comment controls'), '#default_value' => variable_get('comment_anonymous', 1), '#options' => array(t('Anonymous posters may not enter their contact information'), t('Anonymous posters may leave their contact information'), t('Anonymous posters must leave their contact information')),'#description' => t('This feature is only useful if you allow anonymous users to post comments. See the <a href="%url">permissions page</a>.', array('%url' => url('admin/access/permissions'))));
2005-10-07 06:11:12 +00:00
$form['posting_settings']['comment_subject_field'] = array(
2005-10-11 19:44:35 +00:00
'#type' => 'radios',
'#title' => t('Comment subject field'),
'#default_value' => variable_get('comment_subject_field', 1),
'#options' => array(t('Disabled'), t('Enabled')),
'#description' => t('Can users provide a unique subject for their comments?')
2005-10-07 06:11:12 +00:00
);
2005-10-11 19:44:35 +00:00
$form['posting_settings']['comment_preview'] = array('#type' => 'radios', '#title' => t('Preview comment'), '#default_value' => variable_get('comment_preview', 1), '#options' => array(t('Optional'), t('Required')));
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['posting_settings']['comment_form_location'] = array('#type' => 'radios', '#title' => t('Location of comment submission form'), '#default_value' => variable_get('comment_form_location', 0), '#options' => array(t('Display on separate page'), t('Display below post or comments')));
2005-10-07 06:11:12 +00:00
return system_settings_form('comment_settings_form', $form);
2001-12-31 13:02:53 +00:00
}
2004-06-04 18:50:29 +00:00
/**
* This is *not* a hook_access() implementation. This function is called
* to determine whether the current user has access to a particular comment.
*
* Authenticated users can edit their comments as long they have not been
* replied to. This prevents people from changing or revising their
* statements based on the replies their posts got. Furthermore, users
* can't reply to their own comments and are encouraged instead to extend
* their original comment.
*/
2001-12-30 16:16:38 +00:00
function comment_access($op, $comment) {
2001-12-08 11:37:07 +00:00
global $user;
2004-06-04 18:50:29 +00:00
if ($op == 'edit') {
2005-07-19 17:51:59 +00:00
return ($user->uid && $user->uid == $comment->uid && comment_num_replies($comment->cid) == 0) || user_access('administer comments');
2001-12-08 11:37:07 +00:00
}
}
2004-06-04 18:50:29 +00:00
2004-04-18 15:17:10 +00:00
function comment_node_url() {
2004-07-10 07:58:47 +00:00
return arg(0) .'/'. arg(1);
2003-09-15 15:58:20 +00:00
}
2001-12-08 11:37:07 +00:00
2001-12-30 16:16:38 +00:00
function comment_edit($cid) {
global $user;
2004-12-29 18:41:52 +00:00
$comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d', $cid));
2004-01-13 19:25:37 +00:00
$comment = drupal_unpack($comment);
2004-10-15 11:13:11 +00:00
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
2004-06-04 18:50:29 +00:00
if (comment_access('edit', $comment)) {
2005-10-07 06:11:12 +00:00
return comment_form(object2array($comment));
2004-12-15 21:19:42 +00:00
}
else {
drupal_access_denied();
2001-12-30 16:16:38 +00:00
}
}
2004-07-10 07:58:47 +00:00
function comment_reply($nid, $pid = NULL) {
2004-10-17 19:09:09 +00:00
// set the breadcrumb trail
2005-07-17 18:29:32 +00:00
$node = node_load($nid);
2004-10-17 19:09:09 +00:00
menu_set_location(array(array('path' => "node/$nid", 'title' => $node->title), array('path' => "comment/reply/$nid")));
2003-02-15 11:39:56 +00:00
2004-06-04 18:50:29 +00:00
$output = '';
2002-04-14 20:46:41 +00:00
2004-07-10 07:58:47 +00:00
// are we posting or previewing a reply?
if ($_POST['op'] == t('Post comment')) {
$edit = $_POST['edit'];
2005-07-19 17:51:59 +00:00
$edit = comment_validate($edit);
2004-12-15 21:19:42 +00:00
drupal_set_title(t('Post comment'));
2005-07-19 17:51:59 +00:00
if (!$cid = comment_save($edit)) {
// comment could not be posted. show edit form with errors
return comment_preview($edit);
}
else {
drupal_goto("node/$nid#comment-$cid");
}
2004-07-10 07:58:47 +00:00
}
else if ($_POST['op'] == t('Preview comment')) {
$edit = $_POST['edit'];
2005-07-19 17:51:59 +00:00
$edit = comment_validate($edit);
2004-12-15 21:19:42 +00:00
drupal_set_title(t('Preview comment'));
2005-04-24 16:34:36 +00:00
return comment_preview($edit);
2004-07-10 07:58:47 +00:00
}
2002-09-15 13:00:12 +00:00
2004-07-10 07:58:47 +00:00
// or are we merely showing the form?
if (user_access('access comments')) {
// if this is a reply to another comment, show that comment first
// else, we'll just show the user the node they're commenting on.
2002-04-14 20:46:41 +00:00
if ($pid) {
2005-05-05 20:12:49 +00:00
$comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $pid, COMMENT_PUBLISHED));
2004-01-13 19:25:37 +00:00
$comment = drupal_unpack($comment);
2004-10-15 11:13:11 +00:00
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
2004-06-04 18:50:29 +00:00
$output .= theme('comment_view', $comment);
2002-04-14 20:46:41 +00:00
}
2004-06-04 18:50:29 +00:00
else if (user_access('access content')) {
2004-10-17 19:09:09 +00:00
$output .= node_view($node);
2002-04-14 20:46:41 +00:00
$pid = 0;
}
2001-12-08 11:37:07 +00:00
2004-07-10 07:58:47 +00:00
// should we show the reply box?
2003-08-08 22:57:10 +00:00
if (node_comment_mode($nid) != 2) {
2005-07-19 17:51:59 +00:00
drupal_set_message(t("This discussion is closed: you can't post new comments."), 'error');
2002-04-22 09:05:36 +00:00
}
2004-06-04 18:50:29 +00:00
else if (user_access('post comments')) {
2005-10-07 06:11:12 +00:00
$output .= comment_form(array('pid' => $pid, 'nid' => $nid), t('Reply'));
2002-04-14 20:46:41 +00:00
}
else {
2005-07-19 17:51:59 +00:00
drupal_set_message(t('You are not authorized to post comments.'), 'error');
2002-04-14 20:46:41 +00:00
}
2002-04-22 09:05:36 +00:00
}
else {
2005-07-19 17:51:59 +00:00
drupal_set_message(t('You are not authorized to view comments.'), 'error');
2001-12-08 11:37:07 +00:00
}
2003-12-09 20:15:18 +00:00
2005-04-24 16:34:36 +00:00
return $output;
2001-12-08 11:37:07 +00:00
}
2005-10-07 06:11:12 +00:00
function comment_validate(&$edit) {
2004-05-31 12:46:03 +00:00
global $user;
2004-05-31 19:14:43 +00:00
2005-10-07 06:11:12 +00:00
// Invoke other validation handlers
comment_invoke_comment($edit, 'validate');
2005-07-19 17:51:59 +00:00
// only admins can change these fields
if (!user_access('administer comments')) {
$edit['uid'] = $user->uid;
$edit['timestamp'] = time();
$edit['status'] = user_access('post comments without approval') ? 0 : 1;
}
else {
2005-10-08 12:21:47 +00:00
$date = isset($edit['date']) ? $edit['date'] : 'now';
if (strtotime($date) != -1) {
$edit['timestamp'] = strtotime($date);
2005-07-19 17:51:59 +00:00
}
else {
form_set_error('date', t('You have to specify a valid date.'));
}
if ($edit['uid']) {
// if a registered user posted the comment, we assume you only want to transfer authorship
// to another registered user. Name changes are freely allowed on anon comments.
if ($account = user_load(array('name' => $edit['author']))) {
$edit['uid'] = $account->uid;
}
else {
form_set_error('author', t('You have to specify a valid author.'));
}
}
else {
$edit['uid'] = 0;
$edit['name'] = $edit['author'];
}
}
2005-02-27 02:56:12 +00:00
// Validate the comment's subject. If not specified, extract
// one from the comment's body.
2005-03-31 09:25:33 +00:00
if (trim($edit['subject']) == '') {
// The body may be in any format, so we:
// 1) Filter it into HTML
// 2) Strip out all HTML tags
// 3) Convert entities back to plain-text.
2005-07-29 21:06:33 +00:00
// Note: format is checked by check_markup().
$edit['subject'] = truncate_utf8(decode_entities(strip_tags(check_markup($edit['comment'], $edit['format']))), 29, TRUE);
2005-02-27 02:56:12 +00:00
}
2004-05-31 12:46:03 +00:00
2005-02-27 02:56:12 +00:00
// Validate the comment's body.
2004-05-31 12:46:03 +00:00
if ($edit['comment'] == '') {
form_set_error('comment', t('The body of your comment is empty.'));
}
2005-02-27 02:56:12 +00:00
// Validate filter format
2004-08-13 18:17:10 +00:00
if (array_key_exists('format', $edit) && !filter_access($edit['format'])) {
The Input formats - filter patch has landed. I still need to make update instructions for modules and update the hook docs.
Here's an overview of the changes:
1) Multiple Input formats: they are complete filter configurations (what filters to use, in what order and with which settings). Input formats are admin-definable, and usage of them is role-dependant. For example, you can set it up so that regular users can only use limited HTML, while admins can free HTML without any tag limitations.
The input format can be chosen per content item (nodes, comments, blocks, ...) when you add/edit them. If only a single format is available, there is no choice, and nothing changes with before.
The default install (and the upgrade) contains a basic set of formats which should satisfy the average user's needs.
2) Filters have toggles
Because now you might want to enable a filter only on some input formats, an explicit toggle is provided by the filter system. Modules do not need to worry about it and filters that still have their own on/off switch should get rid of it.
3) Multiple filters per module
This was necessary to accomodate the next change, and it's also a logical extension of the filter system.
4) Embedded PHP is now a filter
Thanks to the multiple input formats, I was able to move the 'embedded PHP' feature from block.module, page.module and book.module into a simple filter which executes PHP code. This filter is part of filter.module, and by default there is an input format 'PHP', restricted to the administrator only, which contains this filter.
This change means that block.module now passes custom block contents through the filter system.
As well as from reducing code duplication and avoiding two type selectors for page/book nodes, you can now combine PHP code with other filters.
5) User-supplied PHP code now requires <?php ?> tags.
This is required for teasers to work with PHP code. Because PHP evaluation is now just another step in the filter process, we can't do this. Also, because teasers are generated before filtering, this would result in errors when the teaser generation would cut off a piece of PHP code.
Also, regular PHP syntax explicitly includes the <?php ?> tags for PHP files, so it makes sense to use the same convention for embedded PHP in Drupal.
6) Filter caching was added.
Benchmarking shows that even for a simple setup (basic html filtering + legacy URL rewriting), filtercache can offer speedups. Unlike the old filtercache, this uses the normal cache table.
7) Filtertips were moved from help into a hook_filter_tips(). This was required to accomodate the fact that there are multiple filters per module, and that filter settings are format dependant. Shoehorning filter tips into _help was ugly and silly. The display of the filter tips is done through the input format selector, so filter_tips_short() no longer exists.
8) A more intelligent linebreak convertor was added, which doesn't stop working if you use block-level tags and which adds <p> tags.
2004-08-10 18:34:29 +00:00
form_set_error('format', t('The supplied input format is invalid.'));
}
2005-02-27 02:56:12 +00:00
// Check validity of name, mail and homepage (if given)
2004-05-31 12:46:03 +00:00
if (!$user->uid) {
2005-10-07 06:11:12 +00:00
if (variable_get('comment_anonymous', 1) > 1) {
2004-05-31 12:46:03 +00:00
if ($edit['name']) {
2005-03-31 09:25:33 +00:00
$taken = db_result(db_query("SELECT COUNT(uid) FROM {users} WHERE LOWER(name) = '%s'", $edit['name']), 0);
2004-05-31 12:46:03 +00:00
if ($taken != 0) {
form_set_error('name', t('The name you used belongs to a registered user.'));
}
}
2005-10-07 06:11:12 +00:00
else if (variable_get('comment_anonymous', 1) == 3) {
2004-05-31 12:46:03 +00:00
form_set_error('name', t('You have to leave your name.'));
}
if ($edit['mail']) {
if (!valid_email_address($edit['mail'])) {
2004-06-20 19:43:28 +00:00
form_set_error('mail', t('The e-mail address you specified is not valid.'));
2004-05-31 12:46:03 +00:00
}
}
2005-10-07 06:11:12 +00:00
else if (variable_get('comment_anonymous', 1) == 3) {
2004-05-31 12:46:03 +00:00
form_set_error('mail', t('You have to leave an e-mail address.'));
}
if ($edit['homepage']) {
if (!valid_url($edit['homepage'], TRUE)) {
form_set_error('homepage', t('The URL of your homepage is not valid. Remember that it must be fully qualified, i.e. of the form <code>http://example.com/directory</code>.'));
}
}
}
}
2005-09-18 12:04:10 +00:00
2005-02-27 02:56:12 +00:00
return $edit;
2004-05-31 12:46:03 +00:00
}
2001-12-08 11:37:07 +00:00
function comment_preview($edit) {
2003-02-15 11:39:56 +00:00
global $user;
2001-12-08 11:37:07 +00:00
2004-06-04 18:50:29 +00:00
$output = '';
2003-12-09 20:15:18 +00:00
2005-05-22 21:14:59 +00:00
$comment = array2object($edit);
2003-05-29 08:21:00 +00:00
2004-06-04 18:50:29 +00:00
// Attach the user and time information.
2005-07-19 17:51:59 +00:00
if ($edit['author']) {
$account = user_load(array('name' => $edit['author']));
}
elseif ($user->uid) {
$account = $user;
}
if ($account) {
$comment->uid = $account->uid;
$comment->name = check_plain($account->name);
}
$comment->timestamp = $edit['timestamp'] ? $edit['timestamp'] : time();
2001-12-22 14:12:18 +00:00
2005-10-01 08:43:51 +00:00
// Preview the comment with security check.
if (!form_get_errors()) {
$output .= theme('comment_view', $comment);
}
2005-10-08 12:21:47 +00:00
$output .= comment_form($edit, t('Reply'));
2002-03-05 20:15:17 +00:00
2004-06-04 18:50:29 +00:00
if ($edit['pid']) {
2005-05-05 20:12:49 +00:00
$comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $edit['pid'], COMMENT_PUBLISHED));
2004-01-13 19:25:37 +00:00
$comment = drupal_unpack($comment);
2004-10-15 11:13:11 +00:00
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
2004-06-04 18:50:29 +00:00
$output .= theme('comment_view', $comment);
2002-03-05 20:15:17 +00:00
}
else {
2005-07-17 18:29:32 +00:00
$output .= node_view(node_load($edit['nid']));
2004-06-04 18:50:29 +00:00
$edit['pid'] = 0;
2002-03-05 20:15:17 +00:00
}
2003-12-09 20:15:18 +00:00
return $output;
2001-12-08 11:37:07 +00:00
}
2005-07-19 17:51:59 +00:00
/**
* Accepts a submission of new or changed comment content.
*
* @param $edit
* A comment array.
*
* @return
* If the comment is successfully saved the comment ID is returned. If the comment
* is not saved, FALSE is returned.
*/
function comment_save($edit) {
2002-09-15 13:00:12 +00:00
global $user;
2005-07-19 17:51:59 +00:00
if (user_access('post comments') && (user_access('administer coments') || node_comment_mode($edit['nid']) == 2)) {
2004-07-04 16:50:02 +00:00
if (!form_get_errors()) {
2004-06-04 18:50:29 +00:00
// Check for duplicate comments. Note that we have to use the
// validated/filtered data to perform such check.
2004-12-02 20:24:53 +00:00
$duplicate = db_result(db_query("SELECT COUNT(cid) FROM {comments} WHERE pid = %d AND nid = %d AND subject = '%s' AND comment = '%s'", $edit['pid'], $edit['nid'], $edit['subject'], $edit['comment']), 0);
2004-05-31 12:46:03 +00:00
if ($duplicate != 0) {
2005-03-31 09:25:33 +00:00
watchdog('content', t('Comment: duplicate %subject.', array('%subject' => theme('placeholder', $edit['subject']))), WATCHDOG_WARNING);
2004-05-18 18:41:46 +00:00
}
2001-12-08 11:37:07 +00:00
2004-12-02 20:24:53 +00:00
if ($edit['cid']) {
2005-07-19 17:51:59 +00:00
// Update the comment in the database.
db_query("UPDATE {comments} SET status = '%s', timestamp = '%d', subject = '%s', comment = '%s', format = '%s', uid = %d, name = '%s' WHERE cid = %d", $edit['status'], $edit['timestamp'], $edit['subject'], $edit['comment'], $edit['format'], $edit['uid'], $edit['name'], $edit['cid']);
2002-09-15 13:00:12 +00:00
2004-09-14 05:48:02 +00:00
_comment_update_node_statistics($edit['nid']);
2004-06-04 18:50:29 +00:00
// Allow modules to respond to the updating of a comment.
2005-10-07 06:11:12 +00:00
comment_invoke_comment($edit, 'update');
2001-12-30 16:16:38 +00:00
2005-01-09 10:06:26 +00:00
// Add an entry to the watchdog log.
2005-03-31 09:25:33 +00:00
watchdog('content', t('Comment: updated %subject.', array('%subject' => theme('placeholder', $edit['subject']))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $edit['nid'], NULL, NULL, 'comment-'. $edit['cid']));
2001-12-30 16:16:38 +00:00
}
else {
2004-06-04 18:50:29 +00:00
// Add the comment to database.
2005-05-05 20:12:49 +00:00
$status = user_access('post comments without approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED;
2004-06-04 18:50:29 +00:00
$roles = variable_get('comment_roles', array());
2004-05-10 20:34:25 +00:00
$score = 0;
foreach (array_intersect(array_keys($roles), array_keys($user->roles)) as $rid) {
$score = max($roles[$rid], $score);
}
2002-09-15 13:00:12 +00:00
$users = serialize(array(0 => $score));
2004-12-02 20:24:53 +00:00
// Here we are building the thread field. See the comment
// in comment_render().
2004-06-04 18:50:29 +00:00
if ($edit['pid'] == 0) {
2004-12-02 20:24:53 +00:00
// This is a comment with no parent comment (depth 0): we start
// by retrieving the maximum thread level.
2004-06-04 18:50:29 +00:00
$max = db_result(db_query('SELECT MAX(thread) FROM {comments} WHERE nid = %d', $edit['nid']));
2003-08-12 18:32:54 +00:00
2004-06-04 18:50:29 +00:00
// Strip the "/" from the end of the thread.
$max = rtrim($max, '/');
2003-08-12 18:32:54 +00:00
2004-12-02 20:24:53 +00:00
// Next, we increase this value by one. Note that we can't
// use 1, 2, 3, ... 9, 10, 11 because we order by string and
// 10 would be right after 1. We use 1, 2, 3, ..., 9, 91,
// 92, 93, ... instead. Ugly but fast.
$decimals = (string) substr($max, 0, strlen($max) - 1);
2003-08-12 18:32:54 +00:00
$units = substr($max, -1, 1);
if ($units) {
$units++;
}
else {
$units = 1;
}
if ($units == 10) {
2004-06-04 18:50:29 +00:00
$units = '90';
2003-08-12 18:32:54 +00:00
}
2004-06-04 18:50:29 +00:00
// Finally, build the thread field for this new comment.
2004-12-02 20:24:53 +00:00
$thread = $decimals . $units .'/';
2003-08-12 18:32:54 +00:00
}
else {
2004-12-02 20:24:53 +00:00
// This is comment with a parent comment: we increase
// the part of the thread value at the proper depth.
2003-08-12 18:32:54 +00:00
// Get the parent comment:
2004-06-04 18:50:29 +00:00
$parent = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $edit['pid']));
2003-08-12 18:32:54 +00:00
2004-06-04 18:50:29 +00:00
// Strip the "/" from the end of the parent thread.
2004-12-02 20:24:53 +00:00
$parent->thread = (string) rtrim((string) $parent->thread, '/');
2003-08-12 18:32:54 +00:00
2004-06-04 18:50:29 +00:00
// Get the max value in _this_ thread.
2004-05-10 20:34:25 +00:00
$max = db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $edit['nid']));
2003-08-12 18:32:54 +00:00
2004-06-04 18:50:29 +00:00
if ($max == '') {
// First child of this parent.
2004-12-02 20:24:53 +00:00
$thread = $parent->thread .'.1/';
2003-08-12 18:32:54 +00:00
}
else {
2004-06-04 18:50:29 +00:00
// Strip the "/" at the end of the thread.
$max = rtrim($max, '/');
2003-08-12 18:32:54 +00:00
2004-06-04 18:50:29 +00:00
// We need to get the value at the correct depth.
$parts = explode('.', $max);
$parent_depth = count(explode('.', $parent->thread));
2003-08-12 18:32:54 +00:00
$last = $parts[$parent_depth];
2004-12-02 20:24:53 +00:00
// Next, we increase this value by one. Note that we can't
// use 1, 2, 3, ... 9, 10, 11 because we order by string and
// 10 would be right after 1. We use 1, 2, 3, ..., 9, 91,
// 92, 93, ... instead. Ugly but fast.
2003-08-12 18:32:54 +00:00
$decimals = (string)substr($last, 0, strlen($last) - 1);
$units = substr($last, -1, 1);
$units++;
if ($units == 10) {
2004-06-04 18:50:29 +00:00
$units = '90';
2003-08-12 18:32:54 +00:00
}
2004-06-04 18:50:29 +00:00
// Finally, build the thread field for this new comment.
2004-12-02 20:24:53 +00:00
$thread = $parent->thread .'.'. $decimals . $units .'/';
2003-08-12 18:32:54 +00:00
}
}
2004-12-02 20:24:53 +00:00
$edit['cid'] = db_next_id('{comments}_cid');
2004-09-14 05:48:02 +00:00
$edit['timestamp'] = time();
if ($edit['uid'] = $user->uid) {
$edit['name'] = $user->name;
}
2005-07-19 17:51:59 +00:00
db_query("INSERT INTO {comments} (cid, nid, pid, uid, subject, comment, format, hostname, timestamp, status, score, users, thread, name, mail, homepage) VALUES (%d, %d, %d, %d, '%s', '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s')", $edit['cid'], $edit['nid'], $edit['pid'], $edit['uid'], $edit['subject'], $edit['comment'], $edit['format'], $_SERVER['REMOTE_ADDR'], $edit['timestamp'], $edit['status'], $score, $users, $thread, $edit['name'], $edit['mail'], $edit['homepage']);
2004-09-14 05:48:02 +00:00
_comment_update_node_statistics($edit['nid']);
2002-09-15 13:00:12 +00:00
2004-06-04 18:50:29 +00:00
// Tell the other modules a new comment has been submitted.
2005-10-07 06:11:12 +00:00
comment_invoke_comment($edit, 'insert');
2004-05-31 12:46:03 +00:00
2004-06-04 18:50:29 +00:00
// Add an entry to the watchdog log.
2005-03-31 09:25:33 +00:00
watchdog('content', t('Comment: added %subject.', array('%subject' => theme('placeholder', $edit['subject']))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $edit['nid'], NULL, NULL, 'comment-'. $edit['cid']));
2001-12-30 16:16:38 +00:00
}
2001-12-22 14:12:18 +00:00
2004-06-04 18:50:29 +00:00
// Clear the cache so an anonymous user can see his comment being added.
2002-11-17 06:42:52 +00:00
cache_clear_all();
2004-05-31 12:46:03 +00:00
2004-12-07 16:55:38 +00:00
// Explain the approval queue if necessary, and then
2004-07-13 20:51:29 +00:00
// redirect the user to the node he's commenting on.
2005-05-05 20:12:49 +00:00
if ($status == COMMENT_NOT_PUBLISHED) {
2004-07-13 20:51:29 +00:00
drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.'));
2004-05-31 12:46:03 +00:00
}
2005-07-19 17:51:59 +00:00
return $edit['cid'];
2004-05-31 12:46:03 +00:00
}
else {
2005-07-19 17:51:59 +00:00
return FALSE;
2001-12-08 11:37:07 +00:00
}
}
2002-09-15 13:00:12 +00:00
else {
2005-07-20 15:13:12 +00:00
$txt = t('Comment: unauthorized comment submitted or comment submitted to a closed node %subject.', array('%subject' => theme('placeholder', $edit['subject'])));
2005-07-19 17:51:59 +00:00
watchdog('content', $txt, WATCHDOG_WARNING);
drupal_set_message($txt, 'error');
return FALSE;
2001-12-08 11:37:07 +00:00
}
}
function comment_links($comment, $return = 1) {
2003-02-15 11:39:56 +00:00
global $user;
2001-12-08 11:37:07 +00:00
2001-12-27 20:35:40 +00:00
$links = array();
2002-12-02 19:14:41 +00:00
2004-06-04 18:50:29 +00:00
// If we are viewing just this comment, we link back to the node.
2001-12-08 11:37:07 +00:00
if ($return) {
2004-06-04 18:50:29 +00:00
$links[] = l(t('parent'), comment_node_url(), NULL, NULL, "comment-$comment->cid");
2001-12-08 11:37:07 +00:00
}
2001-12-27 20:35:40 +00:00
2002-09-15 13:00:12 +00:00
if (node_comment_mode($comment->nid) == 2) {
2004-06-04 18:50:29 +00:00
if (user_access('administer comments') && user_access('access administration pages')) {
2005-07-19 17:51:59 +00:00
$links[] = l(t('delete'), "comment/delete/$comment->cid");
$links[] = l(t('edit'), "comment/edit/$comment->cid");
2004-08-05 05:40:53 +00:00
$links[] = l(t('reply'), "comment/reply/$comment->nid/$comment->cid");
2003-12-24 13:13:07 +00:00
}
2004-06-04 18:50:29 +00:00
else if (user_access('post comments')) {
if (comment_access('edit', $comment)) {
2004-08-05 05:40:53 +00:00
$links[] = l(t('edit'), "comment/edit/$comment->cid");
2002-09-15 13:00:12 +00:00
}
2004-08-05 05:40:53 +00:00
$links[] = l(t('reply'), "comment/reply/$comment->nid/$comment->cid");
2001-12-30 16:16:38 +00:00
}
else {
2004-06-04 18:50:29 +00:00
$links[] = theme('comment_post_forbidden');
2001-12-30 16:16:38 +00:00
}
2001-12-08 11:37:07 +00:00
}
2002-09-15 13:00:12 +00:00
2004-02-15 16:28:33 +00:00
return $links;
2001-12-08 11:37:07 +00:00
}
2002-09-15 13:00:12 +00:00
function comment_render($node, $cid = 0) {
2003-05-30 11:13:53 +00:00
global $user;
2004-06-04 18:50:29 +00:00
$mode = $_GET['mode'];
$order = $_GET['order'];
$comments_per_page = $_GET['comments_per_page'];
$comment_page = $_GET['comment_page'];
2001-12-08 11:37:07 +00:00
2004-06-04 18:50:29 +00:00
$output = '';
2001-12-08 11:37:07 +00:00
2004-06-04 18:50:29 +00:00
if (user_access('access comments')) {
// Pre-process variables.
2002-09-15 13:00:12 +00:00
$nid = $node->nid;
2001-12-30 16:16:38 +00:00
if (empty($nid)) {
$nid = 0;
2001-12-08 11:37:07 +00:00
}
if (empty($mode)) {
2004-06-04 18:50:29 +00:00
$mode = $user->mode ? $user->mode : ($_SESSION['comment_mode'] ? $_SESSION['comment_mode'] : variable_get('comment_default_mode', 4));
2001-12-08 11:37:07 +00:00
}
if (empty($order)) {
2004-06-04 18:50:29 +00:00
$order = $user->sort ? $user->sort : ($_SESSION['comment_sort'] ? $_SESSION['comment_sort'] : variable_get('comment_default_order', 1));
2001-12-08 11:37:07 +00:00
}
2003-05-30 11:13:53 +00:00
if (empty($comments_per_page)) {
2004-06-04 18:50:29 +00:00
$comments_per_page = $user->comments_per_page ? $user->comments_per_page : ($_SESSION['comment_comments_per_page'] ? $_SESSION['comment_comments_per_page'] : variable_get('comment_default_per_page', '50'));
2003-05-30 11:13:53 +00:00
}
2002-09-15 13:00:12 +00:00
2003-11-25 19:26:21 +00:00
$output .= "<a id=\"comment\"></a>\n";
2001-12-08 11:37:07 +00:00
2002-05-16 09:32:01 +00:00
if ($cid) {
2004-06-04 18:50:29 +00:00
// Single comment view.
2005-08-30 15:22:29 +00:00
$result = db_query('SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, u.data, c.score, c.users FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d GROUP BY c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, u.picture, c.homepage, u.uid, u.name, u.picture, u.data, c.score, c.users', $cid, COMMENT_PUBLISHED);
2002-09-15 13:00:12 +00:00
2001-12-08 11:37:07 +00:00
if ($comment = db_fetch_object($result)) {
2004-10-15 11:13:11 +00:00
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
2004-06-18 15:04:37 +00:00
$output .= theme('comment_view', $comment, theme('links', module_invoke_all('link', 'comment', $comment, 1)));
2001-12-08 11:37:07 +00:00
}
2002-05-05 19:02:02 +00:00
}
2001-12-08 11:37:07 +00:00
else {
2004-06-04 18:50:29 +00:00
// Multiple comment view
2002-09-15 13:00:12 +00:00
2005-05-05 20:12:49 +00:00
$query .= "SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name , c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, u.data, c.score, c.users, c.thread FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d AND c.status = %d";
2003-08-12 18:32:54 +00:00
2004-10-07 14:33:54 +00:00
$query .= ' GROUP BY c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, u.picture, c.homepage, u.uid, u.name, u.picture, u.data, c.score, c.users, c.thread';
2002-09-15 13:00:12 +00:00
2003-08-12 18:32:54 +00:00
/*
** We want to use the standard pager, but threads would need every
** comment to build the thread structure, so we need to store some
** extra info.
**
** We use a "thread" field to store this extra info. The basic idea
** is to store a value and to order by that value. The "thread" field
** keeps this data in a way which is easy to update and convenient
** to use.
**
** A "thread" value starts at "1". If we add a child (A) to this
** comment, we assign it a "thread" = "1.1". A child of (A) will have
** "1.1.1". Next brother of (A) will get "1.2". Next brother of the
** parent of (A) will get "2" and so on.
**
** First of all note that the thread field stores the depth of the
** comment: depth 0 will be "X", depth 1 "X.X", depth 2 "X.X.X", etc.
**
** Now to get the ordering right, consider this example:
**
** 1
** 1.1
** 1.1.1
** 1.2
** 2
**
** If we "ORDER BY thread ASC" we get the above result, and this is
** the natural order sorted by time. However, if we "ORDER BY thread
** DESC" we get:
**
** 2
** 1.2
** 1.1.1
** 1.1
** 1
**
** Clearly, this is not a natural way to see a thread, and users
** will get confused. The natural order to show a thread by time
** desc would be:
**
** 2
** 1
** 1.2
** 1.1
** 1.1.1
**
** which is what we already did before the standard pager patch. To
** achieve this we simply add a "/" at the end of each "thread" value.
** This way out thread fields will look like depicted below:
**
** 1/
** 1.1/
** 1.1.1/
** 1.2/
** 2/
**
** we add "/" since this char is, in ASCII, higher than every number,
** so if now we "ORDER BY thread DESC" we get the correct order. Try
** it, it works ;). However this would spoil the "ORDER BY thread ASC"
** Here, we do not need to consider the trailing "/" so we use a
** substring only.
*/
2002-09-15 13:00:12 +00:00
if ($order == 1) {
2003-08-12 18:32:54 +00:00
if ($mode == 1 || $mode == 2) {
2004-06-04 18:50:29 +00:00
$query .= ' ORDER BY c.timestamp DESC';
2003-08-12 18:32:54 +00:00
}
else {
2004-06-04 18:50:29 +00:00
$query .= ' ORDER BY c.thread DESC';
2003-08-12 18:32:54 +00:00
}
2002-05-05 19:02:02 +00:00
}
2002-09-15 13:00:12 +00:00
else if ($order == 2) {
2003-08-12 18:32:54 +00:00
if ($mode == 1 || $mode == 2) {
2004-06-04 18:50:29 +00:00
$query .= ' ORDER BY c.timestamp';
2003-08-12 18:32:54 +00:00
}
else {
/*
** See comment above. Analysis learns that this doesn't cost
** too much. It scales much much better than having the whole
** comment structure.
*/
2004-06-04 18:50:29 +00:00
$query .= ' ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))';
2003-08-12 18:32:54 +00:00
}
2002-09-15 13:00:12 +00:00
}
2005-10-07 06:11:12 +00:00
// Start a form, for use with comment control.
$result = pager_query($query, $comments_per_page, 0, "SELECT COUNT(*) FROM {comments} WHERE nid = %d AND status = %d", $nid, COMMENT_PUBLISHED);
2005-04-07 05:24:08 +00:00
if (db_num_rows($result) && (variable_get('comment_controls', 3) == 0 || variable_get('comment_controls', 3) == 2)) {
2005-10-07 06:11:12 +00:00
$output .= comment_controls($mode, $order, $comments_per_page, $nid, 'top');
2001-12-08 11:37:07 +00:00
}
2001-12-27 20:35:40 +00:00
2003-08-12 18:32:54 +00:00
while ($comment = db_fetch_object($result)) {
2004-01-13 19:25:37 +00:00
$comment = drupal_unpack($comment);
2004-10-15 11:13:11 +00:00
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
2004-06-04 18:50:29 +00:00
$comment->depth = count(explode('.', $comment->thread)) - 1;
2002-09-15 13:00:12 +00:00
2003-08-12 18:32:54 +00:00
if ($mode == 1) {
2005-10-07 06:11:12 +00:00
$output .= theme('comment_flat_collapsed', $comment);
2002-05-05 19:02:02 +00:00
}
2002-09-15 13:00:12 +00:00
else if ($mode == 2) {
2005-10-07 06:11:12 +00:00
$output .= theme('comment_flat_expanded', $comment);
2001-12-08 11:37:07 +00:00
}
2002-09-15 13:00:12 +00:00
else if ($mode == 3) {
2005-10-07 06:11:12 +00:00
$output .= theme('comment_thread_min', $comment);
2002-05-05 19:02:02 +00:00
}
2003-08-12 18:32:54 +00:00
else if ($mode == 4) {
2005-10-07 06:11:12 +00:00
$output .= theme('comment_thread_max', $comment);
2003-08-12 18:32:54 +00:00
}
2004-07-08 19:58:10 +00:00
}
2004-06-18 15:04:37 +00:00
2005-04-07 05:21:30 +00:00
// Use the standard pager; $pager_total is the number of returned rows,
// is global and defined in pager.inc.
2005-09-24 07:53:26 +00:00
$output .= theme('pager', NULL, $comments_per_page, 0, array('comments_per_page' => $comments_per_page));
2004-06-18 15:04:37 +00:00
2005-10-07 06:11:12 +00:00
if (db_num_rows($result) && (variable_get('comment_controls', 3) == 1 || variable_get('comment_controls', 3) == 3)) {
$output .= comment_controls($mode, $order, $comments_per_page, $nid, 'bottom');
2004-07-08 19:58:10 +00:00
}
}
// If enabled, show new comment form.
2005-10-07 06:11:12 +00:00
if (user_access('post comments') && node_comment_mode($nid) == 2 && (variable_get('comment_form_location', 0) == 1)) {
$output .= comment_form(array('nid' => $nid), t('Post new comment'));
2004-07-08 19:58:10 +00:00
}
}
return $output;
2004-06-18 15:04:37 +00:00
}
2000-12-14 14:13:37 +00:00
2004-07-10 18:11:18 +00:00
/**
* Menu callback; delete a comment.
*/
2004-07-10 07:58:47 +00:00
function comment_delete($cid) {
2004-05-18 18:41:46 +00:00
$comment = db_fetch_object(db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', $cid));
2004-10-15 11:13:11 +00:00
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
2003-12-24 13:13:07 +00:00
2004-07-10 07:58:47 +00:00
$output = '';
2003-12-24 13:13:07 +00:00
2004-07-10 18:11:18 +00:00
// We'll only delete if the user has confirmed the
2004-07-10 07:58:47 +00:00
// deletion using the form in our else clause below.
2005-03-03 20:51:27 +00:00
if ($comment->cid && $_POST['edit']['confirm']) {
2004-08-16 18:02:48 +00:00
drupal_set_message(t('The comment and all its replies have been deleted.'));
2003-12-24 13:13:07 +00:00
2004-07-10 07:58:47 +00:00
// Delete comment and its replies.
_comment_delete_thread($comment);
2001-12-30 16:16:38 +00:00
2004-09-14 05:48:02 +00:00
_comment_update_node_statistics($comment->nid);
2005-02-01 19:45:58 +00:00
// Clear the cache so an anonymous user sees that his comment was deleted.
2004-07-10 07:58:47 +00:00
cache_clear_all();
2004-09-14 05:48:02 +00:00
2005-02-01 19:45:58 +00:00
drupal_goto("node/$comment->nid");
}
2004-07-10 07:58:47 +00:00
else if ($comment->cid) {
2005-10-07 06:11:12 +00:00
$output = confirm_form('comment_confirm_delete',
array(),
2005-03-31 09:25:33 +00:00
t('Are you sure you want to delete the comment %title?', array('%title' => theme('placeholder', $comment->subject))),
2005-03-03 20:51:27 +00:00
'node/'. $comment->nid,
t('Any replies to this comment will be lost. This action cannot be undone.'),
2005-10-07 06:11:12 +00:00
t('Delete'),
t('Cancel'));
2001-12-30 16:16:38 +00:00
}
else {
2004-08-16 18:02:48 +00:00
drupal_set_message(t('The comment no longer exists.'));
2001-12-30 16:16:38 +00:00
}
2004-07-10 07:58:47 +00:00
2005-04-24 16:34:36 +00:00
return $output;
2001-08-03 18:39:17 +00:00
}
2004-07-10 18:11:18 +00:00
/**
* Menu callback; present an administrative comment listing.
*/
function comment_admin_overview($type = 'new') {
2003-08-21 15:47:50 +00:00
$header = array(
2004-08-19 15:41:57 +00:00
array('data' => t('Subject'), 'field' => 'subject'),
array('data' => t('Author'), 'field' => 'u.name'),
array('data' => t('Status'), 'field' => 'status'),
array('data' => t('Time'), 'field' => 'c.timestamp', 'sort' => 'desc'),
2004-11-15 11:16:39 +00:00
array('data' => t('Operations'), 'colspan' => '2')
2003-08-21 15:47:50 +00:00
);
2005-02-01 19:45:58 +00:00
$destination = drupal_get_destination();
2005-05-05 20:12:49 +00:00
$status = ($type == 'approval') ? COMMENT_NOT_PUBLISHED : COMMENT_PUBLISHED;
2004-11-21 08:25:17 +00:00
$sql = 'SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.status = '. db_escape_string($status);
2003-08-21 15:47:50 +00:00
$sql .= tablesort_sql($header);
2005-01-19 01:46:25 +00:00
$result = pager_query($sql, 50);
2002-09-15 13:00:12 +00:00
while ($comment = db_fetch_object($result)) {
2004-10-15 11:13:11 +00:00
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
2004-06-02 05:35:51 +00:00
$rows[] = array(
2005-03-31 09:25:33 +00:00
l($comment->subject, "node/$comment->nid", array('title' => truncate_utf8($comment->comment, 128)), NULL, "comment-$comment->cid") ." ". theme('mark', node_mark($comment->nid, $comment->timestamp)),
2005-08-01 05:14:05 +00:00
theme('username', $comment),
2005-05-05 20:12:49 +00:00
($comment->status == COMMENT_PUBLISHED ? t('Published') : t('Not published')),
2004-06-04 18:50:29 +00:00
format_date($comment->timestamp, 'small'),
2005-07-19 17:51:59 +00:00
l(t('edit'), "comment/edit/$comment->cid", array(), $destination),
l(t('delete'), "comment/delete/$comment->cid", array(), $destination)
2004-06-02 05:35:51 +00:00
);
2002-09-15 13:00:12 +00:00
}
2004-11-15 11:16:39 +00:00
if (!$rows) {
$rows[] = array(array('data' => t('No comments available.'), 'colspan' => '6'));
2002-09-15 13:00:12 +00:00
}
2005-09-27 18:10:19 +00:00
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 50, 0, tablesort_pager());
return $output;
2002-09-15 13:00:12 +00:00
}
2004-07-08 19:58:10 +00:00
/**
- Patch #12232 by Steven/UnConed: search module improvements.
1) Clean up the text analyser: make it handle UTF-8 and all sorts of characters. The word splitter now does intelligent splitting into words and supports all Unicode characters. It has smart handling of acronyms, URLs, dates, ...
2) It now indexes the filtered output, which means it can take advantage of HTML tags. Meaningful tags (headers, strong, em, ...) are analysed and used to boost certain words scores. This has the side-effect of allowing the indexing of PHP nodes.
3) Link analyser for node links. The HTML analyser also checks for links. If they point to a node on the current site (handles path aliases) then the link's words are counted as part of the target node. This helps bring out commonly linked FAQs and answers to the top of the results.
4) Index comments along with the node. This means that the search can make a difference between a single node/comment about 'X' and a whole thread about 'X'. It also makes the search results much shorter and more relevant (before this patch, comments were even shown first).
5) We now keep track of total counts as well as a per item count for a word. This allows us to divide the word score by the total before adding up the scores for different words, and automatically makes noisewords have less influence than rare words. This dramatically improves the relevancy of multiword searches. This also makes the disadvantage of now using OR searching instead of AND searching less problematic.
6) Includes support for text preprocessors through a hook. This is required to index Chinese and Japanese, because these languages do not use spaces between words. An external utility can be used to split these into words through a simple wrapper module. Other uses could be spell checking (although it would have no UI).
7) Indexing is now regulated: only a certain amount of items will be indexed per cron run. This prevents PHP from running out of memory or timing out. This also makes the reindexing required for this patch automatic. I also added an index coverage estimate to the search admin screen.
8) Code cleanup! Moved all the search stuff from common.inc into search.module, rewired some hooks and simplified the functions used. The search form and results now also use valid XHTML and form_ functions. The search admin was moved from search/configure to admin/search for consistency.
9) Improved search output: we also show much more info per item: date, author, node type, amount of comments and a cool dynamic excerpt à la Google. The search form is now much more simpler and the help is only displayed as tips when no search results are found.
10) By moving all search logic to SQL, I was able to add a pager to the search results. This improves usability and performance dramatically.
2004-10-31 03:03:27 +00:00
*** misc functions: helpers, privates, history
2004-07-08 19:58:10 +00:00
**/
2004-07-10 07:58:47 +00:00
function comment_save_settings() {
2004-07-08 19:58:10 +00:00
global $user;
2005-08-17 20:07:35 +00:00
2004-07-10 07:58:47 +00:00
$edit = $_POST['edit'];
2005-10-07 06:11:12 +00:00
2005-08-17 20:07:35 +00:00
$mode = $edit['mode'];
$order = $edit['order'];
$comments_per_page = $edit['comments_per_page'];
2005-10-07 06:11:12 +00:00
if ($user->uid) {
$user = user_save($user, array('mode' => $mode, 'sort' => $order, 'comments_per_page' => $comments_per_page));
2004-07-08 19:58:10 +00:00
}
else {
$_SESSION['comment_mode'] = $mode;
$_SESSION['comment_sort'] = $order;
$_SESSION['comment_comments_per_page'] = $comments_per_page;
}
2005-08-17 20:07:35 +00:00
2004-07-10 07:58:47 +00:00
drupal_goto('node/'. $edit['nid'] .'#comment');
2004-07-08 19:58:10 +00:00
}
function comment_num_all($nid) {
static $cache;
if (!isset($cache[$nid])) {
2004-09-14 05:48:02 +00:00
$cache[$nid] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid));
2004-07-08 19:58:10 +00:00
}
return $cache[$nid];
}
function comment_num_replies($pid) {
static $cache;
if (!isset($cache[$pid])) {
2005-05-05 20:12:49 +00:00
$cache[$pid] = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE pid = %d AND status = %d', $pid, COMMENT_PUBLISHED));
2004-07-08 19:58:10 +00:00
}
return $cache[$pid];
}
/**
* get number of new comments for current user and specified node
*
* @param $nid node-id to count comments for
* @param $timestamp time to count from (defaults to time of last user access
* to node)
*/
function comment_num_new($nid, $timestamp = 0) {
global $user;
if ($user->uid) {
// Retrieve the timestamp at which the current user last viewed the
// specified node.
if (!$timestamp) {
$timestamp = node_last_viewed($nid);
}
2005-03-12 08:52:29 +00:00
$timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT);
2002-09-15 13:00:12 +00:00
2004-07-08 19:58:10 +00:00
// Use the timestamp to retrieve the number of new comments.
2005-05-05 20:12:49 +00:00
$result = db_result(db_query('SELECT COUNT(c.cid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = %d AND timestamp > %d AND c.status = %d', $nid, $timestamp, COMMENT_PUBLISHED));
2002-09-15 13:00:12 +00:00
2004-07-08 19:58:10 +00:00
return $result;
2002-09-15 13:00:12 +00:00
}
else {
2004-07-08 19:58:10 +00:00
return 0;
2002-09-15 13:00:12 +00:00
}
}
/*
2005-10-07 06:11:12 +00:00
** Generate the basic commenting form, for appending to a node or display on a separate page.
** This is rendered by theme_comment_form.
2002-09-15 13:00:12 +00:00
*/
2005-10-07 06:11:12 +00:00
function comment_form($edit, $title = NULL) {
2004-01-03 12:32:21 +00:00
global $user;
2004-05-18 18:41:46 +00:00
if ($user->uid) {
2005-07-19 17:51:59 +00:00
if ($edit['cid'] && user_access('administer comments')) {
if ($edit['author']) {
$author = $edit['author'];
}
elseif ($edit['name']) {
$author = $edit['name'];
}
else {
$author = $edit['registered_name'];
}
2005-10-07 06:11:12 +00:00
if ($edit['status']) {
$status = $edit['status'];
}
else {
$status = 0;
}
if ($edit['date']) {
$date = $edit['date'];
}
else {
$date = format_date($edit['timestamp'], 'custom', 'Y-m-d H:i O');
}
2005-10-11 19:44:35 +00:00
$form['admin'] = array('#type' => 'fieldset', '#title' => t('Administration'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -2);
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['admin']['author'] = array('#type' => 'textfield', '#parents' => array('author'), '#title' => t('Authored by'), '#size' => 30, '#maxlength' => 60, '#autocomplete_path' => 'user/autocomplete', '#default_value' => $author, '#weight' => -1);
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['admin']['date'] = array('#type' => 'textfield', '#parents' => array('date'), '#title' => t('Authored on'), '#size' => 20, '#maxlength' => 25, '#default_value' => $date, '#weight' => -1);
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['admin']['status'] = array('#type' => 'radios', '#parents' => array('status'), '#title' => t('Status'), '#default_value' => $status, '#options' => array(t('Published'), t('Not published')), '#weight' => -1);
2005-10-07 06:11:12 +00:00
2005-07-19 17:51:59 +00:00
}
else {
2005-10-11 19:44:35 +00:00
$form['author'] = array('#type' => 'item', '#title' => t('Your name'), '#value' => theme('username', $user)
2005-10-07 06:11:12 +00:00
);
2005-07-19 17:51:59 +00:00
}
2004-05-18 18:41:46 +00:00
}
2005-10-07 06:11:12 +00:00
else if (variable_get('comment_anonymous', 1) == 2) {
2005-10-11 19:44:35 +00:00
$form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', 'Anonymous')
2005-10-07 06:11:12 +00:00
);
2005-10-11 19:44:35 +00:00
$form['mail'] = array('#type' => 'textfield', '#title' => t('E-mail'), '#maxlength' => 64, '#size' => 30, '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.')
2005-10-07 06:11:12 +00:00
);
2005-10-11 19:44:35 +00:00
$form['homepage'] = array('#type' => 'textfield', '#title' => t('Homepage'), '#maxlength' => 255, '#size' => 30, '#default_value' => $edit['homepage']);
2004-05-18 18:41:46 +00:00
}
2005-10-07 06:11:12 +00:00
else if (variable_get('comment_anonymous', 1) == 3) {
2005-10-11 19:44:35 +00:00
$form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', 'Anonymous'), '#required' => TRUE);
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['name'] = array('#type' => 'textfield', '#title' => t('E-mail'), '#maxlength' => 64, '#size' => 30, '#default_value' => $edit['mail'],'#description' => t('The content of this field is kept private and will not be shown publicly.'), '#required' => TRUE);
2005-10-07 06:11:12 +00:00
2005-10-11 19:44:35 +00:00
$form['homepage'] = array('#type' => 'textfield', '#title' => t('Homepage'), '#maxlength' => 255, '#size' => 30, '#default_value' => $edit['homepage']);
2004-07-08 15:24:30 +00:00
}
2004-05-18 18:41:46 +00:00
2005-10-07 06:11:12 +00:00
if (variable_get('comment_subject_field', 1) == 1) {
2005-10-11 19:44:35 +00:00
$form['subject'] = array('#type' => 'textfield', '#title' => t('Subject'), '#size' => 60, '#maxlength' => 64, '#default_value' => $edit['subject']);
2004-05-18 18:41:46 +00:00
}
2004-01-03 12:32:21 +00:00
2005-10-11 19:44:35 +00:00
$form['comment'] = array('#type' => 'textarea', '#title' => t('Comment'), '#cols' => 60, '#rows' => 15, '#default_value' => $edit['comment'] ? $edit['comment'] : $user->signature, '#required' => TRUE
2005-10-07 06:11:12 +00:00
);
$form = array_merge($form, filter_form($node->format));
2004-01-03 12:32:21 +00:00
2005-10-11 19:44:35 +00:00
$form['cid'] = array('#type' => 'hidden', '#value' => $edit['cid']);
$form['pid'] = array('#type' => 'hidden', '#value' => $edit['pid']);
$form['nid'] = array('#type' => 'hidden', '#value' => $edit['nid']);
$form['uid'] = array('#type' => 'hidden', '#value' => $edit['uid']);
2004-01-03 12:32:21 +00:00
2005-10-11 19:44:35 +00:00
$form['preview'] = array('#type' => 'submit', '#value' => t('Preview comment'), '#weight' => 19);
$form['#token'] = 'comment' . $edit['nid'] . $edit['pid'];
2004-05-31 12:46:03 +00:00
2004-12-23 06:47:24 +00:00
// Only show post button if preview is optional or if we are in preview mode.
// We show the post button in preview mode even if there are form errors so that
// optional form elements (e.g., captcha) can be updated in preview mode.
2005-10-07 06:11:12 +00:00
if ((variable_get('comment_preview', 1) == 0) || ($_POST['op'] == t('Preview comment')) || ($_POST['op'] == t('Post comment'))) {
2005-10-11 19:44:35 +00:00
$form['submit'] = array('#type' => 'submit', '#value' => t('Post comment'), '#weight' => 20);
2005-10-07 06:11:12 +00:00
}
if ($_REQUEST['destination']) {
2005-10-11 19:44:35 +00:00
$form['#attributes']['destination'] = $_REQUEST['destination'];
2004-01-03 12:32:21 +00:00
}
2005-10-11 19:44:35 +00:00
$form['#action'] = url('comment/reply/'. $edit['nid']);
2004-01-03 12:32:21 +00:00
2005-10-07 06:11:12 +00:00
// Graft in extra form additions
$form = array_merge($form, comment_invoke_comment($form, 'form'));
return theme('box', $title, drupal_get_form('comment_form', $form));
}
/*
** Renderer or visualization functions this can be optionally
** overridden by themes.
*/
function theme_comment_form($form) {
return form_render($form);
2004-01-03 12:32:21 +00:00
}
2005-05-22 21:14:59 +00:00
function theme_comment_preview($comment, $links = '', $visible = 1) {
$output = '<div class="preview">';
$output .= theme('comment_view', $comment, $links, $visible);
$output .= '</div>';
return $output;
};
2004-06-04 18:50:29 +00:00
function theme_comment_view($comment, $links = '', $visible = 1) {
2004-05-20 10:23:52 +00:00
2004-06-04 18:50:29 +00:00
// Emit selectors:
$output = '';
2005-01-30 09:53:19 +00:00
if (($comment->new = node_mark($comment->nid, $comment->timestamp)) != MARK_READ) {
2003-11-15 10:03:31 +00:00
$output .= "<a id=\"new\"></a>\n";
}
2004-02-07 10:57:27 +00:00
$output .= "<a id=\"comment-$comment->cid\"></a>\n";
2003-11-15 10:03:31 +00:00
2004-06-04 18:50:29 +00:00
// Switch to folded/unfolded view of the comment
2003-11-15 10:03:31 +00:00
if ($visible) {
2005-07-29 21:06:33 +00:00
$comment->comment = check_markup($comment->comment, $comment->format, FALSE);
2005-10-07 06:11:12 +00:00
// Comment API hook
comment_invoke_comment($comment, 'view');
2004-05-31 12:46:03 +00:00
$output .= theme('comment', $comment, $links);
2003-11-15 10:03:31 +00:00
}
else {
2004-06-04 18:50:29 +00:00
$output .= theme('comment_folded', $comment);
2003-11-15 10:03:31 +00:00
}
2004-05-20 10:23:52 +00:00
2003-11-15 10:03:31 +00:00
return $output;
}
2005-10-07 06:11:12 +00:00
function comment_controls($mode = 2, $order = 1, $comments_per_page = 50, $nid = 0, $top_or_bottom = '') {
2002-09-15 13:00:12 +00:00
2005-10-11 19:44:35 +00:00
$form['mode'] = array('#type' => 'select', '#default_value' => $mode, '#options' => _comment_get_modes(), '#weight' => 1);
2004-05-01 09:22:16 +00:00
2005-10-11 19:44:35 +00:00
$form['order'] = array('#type' => 'select', '#default_value' => $order, '#options' => _comment_get_orders(), '#weight' => 2);
2002-09-15 13:00:12 +00:00
2005-10-07 06:11:12 +00:00
foreach (_comment_per_page() as $i) {
$options[] = t('%a comments per page', array('%a' => $i));
}
2005-10-11 19:44:35 +00:00
$form['comments_per_page'] = array('#type' => 'select', '#default_value' => $comments_per_page, '#options' => $options, '#weight' => 3);
2002-09-15 13:00:12 +00:00
2005-10-11 19:44:35 +00:00
$form['submit'] = array('#type' => 'submit', '#value' => t('Save settings'), '#weight' => 20);
2002-09-15 13:00:12 +00:00
2005-10-11 19:44:35 +00:00
$form['nid'] = array('#type' => 'hidden', '#value' => $nid);
2002-09-15 13:00:12 +00:00
2005-10-11 19:44:35 +00:00
$form['#action'] = 'comment/reply';
2002-09-15 13:00:12 +00:00
2005-10-07 06:11:12 +00:00
return drupal_get_form('comment_controls'. $top_or_bottom, $form, 'comment_controls');
2002-09-15 13:00:12 +00:00
}
2005-10-07 06:11:12 +00:00
function theme_comment_controls($form) {
$output .= '<div class="container-inline">';
$output .= form_render($form);
$output .= '</div>';
$output .= '<div class="description">' . t('Select your preferred way to display the comments and click "Save settings" to activate your changes.') . '</div>';
2003-05-13 18:36:38 +00:00
2005-10-07 06:11:12 +00:00
return theme('box', t('Comment viewing options'), $output);
2002-09-15 13:00:12 +00:00
}
2003-11-09 23:27:22 +00:00
function theme_comment($comment, $links = 0) {
2004-03-12 08:09:09 +00:00
$output = "<div class=\"comment\">\n";
2005-01-30 09:53:19 +00:00
$output .= '<div class="subject">'. l($comment->subject, $_GET['q'], NULL, NULL, "comment-$comment->cid") . ' ' . theme('mark', $comment->new) ."</div>\n";
2005-08-01 05:14:05 +00:00
$output .= '<div class="credit">'. t('by %a on %b', array('%a' => theme('username', $comment), '%b' => format_date($comment->timestamp))) ."</div>\n";
2004-05-20 10:23:52 +00:00
$output .= "<div class=\"body\">$comment->comment</div>\n";
2004-03-12 08:09:09 +00:00
$output .= "<div class=\"links\">$links</div>\n";
$output .= "</div>\n";
2003-11-15 10:03:31 +00:00
return $output;
2002-09-15 13:00:12 +00:00
}
2003-11-09 23:27:22 +00:00
function theme_comment_folded($comment) {
2004-03-12 08:09:09 +00:00
$output = "<div class=\"comment-folded\">\n";
2005-01-30 09:53:19 +00:00
$output .= ' <span class="subject">'. l($comment->subject, comment_node_url() .'/'. $comment->cid, NULL, NULL, "comment-$comment->cid") . ' '. theme('mark', $comment->new) .'</span> ';
2005-08-01 05:14:05 +00:00
$output .= '<span class="credit">'. t('by') .' '. theme('username', $comment) ."</span>\n";
2004-03-12 08:09:09 +00:00
$output .= "</div>\n";
return $output;
2002-09-15 13:00:12 +00:00
}
2005-10-07 06:11:12 +00:00
function theme_comment_flat_collapsed($comment) {
return theme('comment_view', $comment, '', 0);
2004-06-04 18:50:29 +00:00
return '';
2002-09-15 13:00:12 +00:00
}
2005-10-07 06:11:12 +00:00
function theme_comment_flat_expanded($comment) {
return theme('comment_view', $comment, theme('links', module_invoke_all('link', 'comment', $comment, 0)));
2002-09-15 13:00:12 +00:00
}
2005-10-07 06:11:12 +00:00
function theme_comment_thread_min($comment, $pid = 0) {
$output = '<div style="margin-left:'. ($comment->depth * 25) ."px;\">\n";
$output .= theme('comment_view', $comment, '', 0);
$output .= "</div>\n";
2003-11-15 10:03:31 +00:00
return $output;
2002-09-15 13:00:12 +00:00
}
2005-10-07 06:11:12 +00:00
function theme_comment_thread_max($comment, $level = 0) {
2004-06-04 18:50:29 +00:00
$output = '';
2003-08-12 18:32:54 +00:00
if ($comment->depth) {
2004-06-04 18:50:29 +00:00
$output .= '<div style="margin-left:'. ($comment->depth * 25) ."px;\">\n";
2002-09-15 13:00:12 +00:00
}
2005-10-07 06:11:12 +00:00
$output .= theme('comment_view', $comment, theme('links', module_invoke_all('link', 'comment', $comment, 0)));
2002-09-15 13:00:12 +00:00
2003-08-12 18:32:54 +00:00
if ($comment->depth) {
2003-12-15 19:41:24 +00:00
$output .= "</div>\n";
2002-09-15 13:00:12 +00:00
}
2003-11-15 10:03:31 +00:00
return $output;
2002-09-15 13:00:12 +00:00
}
2003-11-09 23:27:22 +00:00
function theme_comment_post_forbidden() {
2002-09-15 13:00:12 +00:00
global $user;
if ($user->uid) {
2003-12-24 13:13:07 +00:00
return t("you can't post comments");
2002-09-15 13:00:12 +00:00
}
else {
2004-07-14 05:44:36 +00:00
if (variable_get('user_register', 1)) {
return t('<a href="%login">login</a> or <a href="%register">register</a> to post comments', array('%login' => url('user/login'), '%register' => url('user/register')));
}
else {
return t('<a href="%login">login</a> to post comments', array('%login' => url('user/login')));
}
2002-09-15 13:00:12 +00:00
}
}
2004-07-08 19:58:10 +00:00
function _comment_delete_thread($comment) {
// Delete the comment:
db_query('DELETE FROM {comments} WHERE cid = %d', $comment->cid);
2005-03-31 09:25:33 +00:00
watchdog('content', t('Comment: deleted %subject.', array('%subject' => theme('placeholder', $comment->subject))));
2002-03-05 20:15:17 +00:00
2005-10-07 06:11:12 +00:00
comment_invoke_comment($comment, 'delete');
2004-09-14 05:48:02 +00:00
2005-10-07 06:11:12 +00:00
// Delete the comment's replies
2004-09-14 05:48:02 +00:00
$result = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE pid = %d', $comment->cid);
2004-07-08 19:58:10 +00:00
while ($comment = db_fetch_object($result)) {
2004-10-15 11:13:11 +00:00
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
2004-07-08 19:58:10 +00:00
_comment_delete_thread($comment);
2003-02-16 14:57:35 +00:00
}
}
2004-06-04 18:50:29 +00:00
/**
* Return an array of viewing modes for comment listings.
*
* We can't use a global variable array because the locale system
* is not initialized yet when the comment module is loaded.
*/
2003-10-03 15:14:15 +00:00
function _comment_get_modes() {
2005-10-07 06:11:12 +00:00
return array(t('Flat list - collapsed'), t('Flat list - expanded'), t('Threaded list - collapsed'), t('Threaded list - expanded'));
2003-10-03 15:14:15 +00:00
}
2004-06-04 18:50:29 +00:00
/**
* Return an array of viewing orders for comment listings.
*
* We can't use a global variable array because the locale system
* is not initialized yet when the comment module is loaded.
*/
2003-10-03 15:14:15 +00:00
function _comment_get_orders() {
2004-06-04 18:50:29 +00:00
return array(1 => t('Date - newest first'), 2 => t('Date - oldest first'));
2003-10-03 15:14:15 +00:00
}
2004-06-04 18:50:29 +00:00
/**
* Return an array of "comments per page" settings from which the user
* can choose.
*/
2004-01-17 10:32:52 +00:00
function _comment_per_page() {
2005-09-29 08:04:51 +00:00
return drupal_map_assoc(array(10, 30, 50, 70, 90, 150, 200, 250, 300));
2004-01-17 10:32:52 +00:00
}
2004-09-14 05:48:02 +00:00
/**
* Updates the comment statistics for a given node. This should be called any
* time a comment is added, deleted, or updated.
*
* The following fields are contained in the node_comment_statistics table.
* - last_comment_timestamp: the timestamp of the last comment for this node or the node create stamp if no comments exist for the node.
* - last_comment_name: the name of the anonymous poster for the last comment
* - last_comment_uid: the uid of the poster for the last comment for this node or the node authors uid if no comments exists for the node.
2004-10-17 19:09:09 +00:00
* - comment_count: the total number of approved/published comments on this node.
2004-09-14 05:48:02 +00:00
*/
function _comment_update_node_statistics($nid) {
2005-05-05 20:12:49 +00:00
$count = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE nid = %d AND status = %d', $nid, COMMENT_PUBLISHED));
2004-09-14 05:48:02 +00:00
2005-02-11 19:01:53 +00:00
// comments exist
if ($count > 0) {
2005-05-05 20:12:49 +00:00
$last_reply = db_fetch_object(db_query_range('SELECT cid, name, timestamp, uid FROM {comments} WHERE nid = %d AND status = %d ORDER BY cid DESC', $nid, COMMENT_PUBLISHED, 0, 1));
2005-02-11 19:01:53 +00:00
db_query("UPDATE {node_comment_statistics} SET comment_count = %d, last_comment_timestamp = %d, last_comment_name = '%s', last_comment_uid = %d WHERE nid = %d", $count, $last_reply->timestamp, $last_reply->uid ? NULL : $last_reply->name, $last_reply->uid, $nid);
}
// no comments
else {
db_query("UPDATE {node_comment_statistics} SET comment_count = %d, last_comment_timestamp = %d, last_comment_name = '%s', last_comment_uid = %d WHERE nid = %d", 0, NULL, 0, 0, $nid);
}
}
2005-08-25 21:14:17 +00:00
2005-10-07 06:11:12 +00:00
/**
* Invoke a hook_comment() operation in all modules.
*
* @param &$comment
* A comment object.
* @param $op
* A string containing the name of the comment operation.
* @return
* The returned value of the invoked hooks.
*/
function comment_invoke_comment(&$comment, $op) {
$return = array();
foreach (module_implements('comment') as $name) {
$function = $name .'_comment';
$result = $function($comment, $op);
if (is_array($result)) {
$return = array_merge($return, $result);
}
else if (isset($result)) {
$return[] = $result;
}
}
return $return;
}