Newer
Older
// $Id$
*
* 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.
*/
Dries Buytaert
committed
* Comment is awaiting approval.
Dries Buytaert
committed
*/
Dries Buytaert
committed
define('COMMENT_NOT_PUBLISHED', 0);
Dries Buytaert
committed
* Comment is published.
Dries Buytaert
committed
define('COMMENT_PUBLISHED', 1);
* Comments are displayed in a flat list - collapsed.
define('COMMENT_MODE_FLAT_COLLAPSED', 1);
/**
* Comments are displayed in a flat list - expanded.
*/
define('COMMENT_MODE_FLAT_EXPANDED', 2);
/**
* Comments are displayed as a threaded list - collapsed.
*/
define('COMMENT_MODE_THREADED_COLLAPSED', 3);
/**
* Comments are displayed as a threaded list - expanded.
*/
define('COMMENT_MODE_THREADED_EXPANDED', 4);
* Anonymous posters cannot enter their contact information.
*/
define('COMMENT_ANONYMOUS_MAYNOT_CONTACT', 0);
/**
* Anonymous posters may leave their contact information.
*/
define('COMMENT_ANONYMOUS_MAY_CONTACT', 1);
* Anonymous posters are required to leave their contact information.
define('COMMENT_ANONYMOUS_MUST_CONTACT', 2);
/**
* Comment form should be displayed on a separate page.
*/
define('COMMENT_FORM_SEPARATE_PAGE', 0);
/**
* Comment form should be shown below post or list of comments.
*/
define('COMMENT_FORM_BELOW', 1);
/**
* Comments for this node are disabled.
*/
define('COMMENT_NODE_DISABLED', 0);
/**
* Comments for this node are locked.
*/
define('COMMENT_NODE_READ_ONLY', 1);
/**
* Comments are enabled on this node.
*/
define('COMMENT_NODE_READ_WRITE', 2);
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Comment preview is optional.
Dries Buytaert
committed
*/
define('COMMENT_PREVIEW_OPTIONAL', 0);
/**
* Comment preview is required.
*/
Dries Buytaert
committed
define('COMMENT_PREVIEW_REQUIRED', 1);
/**
* Implementation of hook_help().
*/
Gábor Hojtsy
committed
function comment_help($path, $arg) {
switch ($path) {
$output = '<p>' . t('The comment module allows visitors to comment on your posts, creating ad hoc discussion boards. Any <a href="@content-type">content type</a> may have its <em>Default comment setting</em> set to <em>Read/Write</em> to allow comments, or <em>Disabled</em>, to prevent comments. Comment display settings and other controls may also be customized for each content type.', array('@content-type' => url('admin/build/types'))) . '</p>';
$output .= '<p>' . t('Comment permissions are assigned to user roles, and are used to determine whether anonymous users (or other roles) are allowed to comment on posts. If anonymous users are allowed to comment, their individual contact information may be retained in cookies stored on their local computer for use in later comment submissions. When a comment has no replies, it may be (optionally) edited by its author. The comment module uses the same input formats and HTML tags available when creating other forms of content.') . '</p>';
$output .= '<p>' . t('For more information, see the online handbook entry for <a href="@comment">Comment module</a>.', array('@comment' => 'http://drupal.org/handbook/modules/comment/')) . '</p>';
Dries Buytaert
committed
return $output;
Dries Buytaert
committed
case 'admin/content/comment':
return '<p>' . t("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>';
Dries Buytaert
committed
case 'admin/content/comment/approval':
Dries Buytaert
committed
return '<p>' . t("Below is a list of the unapproved comments posted to your site. To approve comments, select them with the checkbox, choose <em>Publish the selected comments</em> from <em>Update options</em> and click the <em>Update</em> button. To delete them, choose <em>Delete the selected comments</em> instead. Use <em>edit</em> to individually modify a comment's content.") . '</p>';
Gábor Hojtsy
committed
}
Dries Buytaert
committed
/**
* Implementation of hook_theme().
Dries Buytaert
committed
*/
function comment_theme() {
return array(
'comment_block' => array(
'arguments' => array(),
),
'comment_preview' => array(
Dries Buytaert
committed
'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1),
Dries Buytaert
committed
),
'comment_view' => array(
Dries Buytaert
committed
'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1),
Dries Buytaert
committed
),
'comment' => array(
'template' => 'comment',
'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array()),
Dries Buytaert
committed
),
'comment_folded' => array(
'template' => 'comment-folded',
Dries Buytaert
committed
'arguments' => array('comment' => NULL),
),
'comment_flat_collapsed' => array(
Dries Buytaert
committed
'arguments' => array('comment' => NULL, 'node' => NULL),
Dries Buytaert
committed
),
'comment_flat_expanded' => array(
Dries Buytaert
committed
'arguments' => array('comment' => NULL, 'node' => NULL),
Dries Buytaert
committed
),
'comment_thread_collapsed' => array(
Dries Buytaert
committed
'arguments' => array('comment' => NULL, 'node' => NULL),
Dries Buytaert
committed
),
'comment_thread_expanded' => array(
Dries Buytaert
committed
'arguments' => array('comment' => NULL, 'node' => NULL),
Dries Buytaert
committed
),
'comment_post_forbidden' => array(
'arguments' => array('nid' => NULL),
),
'comment_wrapper' => array(
'template' => 'comment-wrapper',
'arguments' => array('content' => NULL, 'node' => NULL),
Dries Buytaert
committed
),
Gábor Hojtsy
committed
'comment_submitted' => array(
'arguments' => array('comment' => NULL),
),
Dries Buytaert
committed
);
}
Dries Buytaert
committed
function comment_menu() {
$items['admin/content/comment'] = array(
'title' => 'Comments',
Dries Buytaert
committed
'description' => 'List and edit site comments and the comment approval queue.',
Dries Buytaert
committed
'page callback' => 'comment_admin',
'access arguments' => array('administer comments'),
);
Dries Buytaert
committed
$items['admin/content/comment/new'] = array(
'title' => 'Published comments',
Dries Buytaert
committed
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
Dries Buytaert
committed
$items['admin/content/comment/approval'] = array(
'title' => 'Approval queue',
Dries Buytaert
committed
'page arguments' => array('approval'),
Dries Buytaert
committed
'access arguments' => array('administer comments'),
Dries Buytaert
committed
'type' => MENU_LOCAL_TASK,
);
$items['comment/delete'] = array(
'title' => 'Delete comment',
'page callback' => 'comment_delete',
Dries Buytaert
committed
'access arguments' => array('administer comments'),
'type' => MENU_CALLBACK,
);
$items['comment/edit'] = array(
'title' => 'Edit comment',
Dries Buytaert
committed
'page callback' => 'comment_edit',
'access arguments' => array('post comments'),
'type' => MENU_CALLBACK,
);
$items['comment/reply/%node'] = array(
'title' => 'Reply to comment',
Dries Buytaert
committed
'page callback' => 'comment_reply',
'page arguments' => array(2),
Dries Buytaert
committed
'access callback' => 'node_access',
'access arguments' => array('view', 2),
'type' => MENU_CALLBACK,
);
Dries Buytaert
committed
$items['comment/approve'] = array(
'title' => 'Approve a comment',
Dries Buytaert
committed
'page callback' => 'comment_approve',
'page arguments' => array(2),
'access arguments' => array('administer comments'),
'type' => MENU_CALLBACK,
);
Dries Buytaert
committed
/**
* Implementation of hook_node_type().
*/
function comment_node_type($op, $info) {
$settings = array(
'comment',
'comment_default_mode',
'comment_default_per_page',
'comment_anonymous',
'comment_subject_field',
'comment_preview',
'comment_form_location',
);
Dries Buytaert
committed
switch ($op) {
case 'delete':
foreach ($settings as $setting) {
variable_del($setting . '_' . $info->type);
Dries Buytaert
committed
}
break;
}
}
/**
* Implementation of hook_perm().
*/
function comment_perm() {
return array(
Angie Byron
committed
'administer comments' => array(
'title' => t('Administer comments'),
'description' => t('Manage and approve comments, and configure comment administration settings.'),
),
'access comments' => array(
'title' => t('Access comments'),
'description' => t('View comments attached to content.'),
),
'post comments' => array(
'title' => t('Post comments'),
'description' => t('Add comments to content (approval required).'),
),
'post comments without approval' => array(
'title' => t('Post comments without approval'),
'description' => t('Add comments to content (no approval required).'),
),
);
Dries Buytaert
committed
* Implementation of hook_block_list().
Dries Buytaert
committed
function comment_block_list() {
$blocks['recent']['info'] = t('Recent comments');
Dries Buytaert
committed
return $blocks;
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implementation of hook_block_configure().
*/
function comment_block_configure($delta = '') {
$form['comment_block_count'] = array(
'#type' => 'select',
'#title' => t('Number of recent comments'),
'#default_value' => variable_get('comment_block_count', 10),
'#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)),
'#description' => t('Number of comments displayed in the <em>Recent comments</em> block.'),
);
Dries Buytaert
committed
return $form;
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implementation of hook_block_save().
*/
function comment_block_save($delta = '', $edit = array()) {
variable_set('comment_block_count', (int)$edit['comment_block_count']);
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implementation of hook_block_view().
*
* Generates a block with the most recent comments.
*/
function comment_block_view($delta = '') {
if (user_access('access comments')) {
$block['subject'] = t('Recent comments');
$block['content'] = theme('comment_block');
Dries Buytaert
committed
return $block;
* Find the most recent comments that are available to the current user.
*
* This is done in two steps:
* 1. Query the {node_comment_statistics} table to find n number of nodes that
* have the most recent comments. This table is indexed on
* last_comment_timestamp, thus making it a fast query.
* 2. Load the information from the comments table based on the nids found
* in step 1.
*
* (optional) The maximum number of comments to find.
* @return
* An array of comment objects each containing a nid,
* subject, cid, and timestamp, or an empty array if there are no recent
* comments visible to the current user.
*/
function comment_get_recent($number = 10) {
// Step 1: Select a $number of nodes which have new comments,
// and are visible to the current user.
Dries Buytaert
committed
$nids = db_query_range("SELECT nc.nid FROM {node_comment_statistics} nc WHERE nc.comment_count > 0 ORDER BY nc.last_comment_timestamp DESC", 0, $number)->fetchCol();
$comments = array();
if (!empty($nids)) {
// Step 2: From among the comments on the nodes selected in the first query,
// find the $number of most recent comments.
Dries Buytaert
committed
// Using Query Builder here for the IN-Statement.
Angie Byron
committed
$query = db_select('comment', 'c');
$query->fields('c', array('nid', 'subject', 'cid', 'timestamp'));
$query->innerJoin('node', 'n', 'n.nid = c.nid');
$query->condition('c.nid', $nids, 'IN');
$query->condition('c.status', COMMENT_PUBLISHED);
$query->condition('n.status', 1);
$query->orderBy('c.cid', 'DESC');
$query->range(0, $number);
$comments = $query->execute()->fetchAll();
}
return $comments;
}
Gábor Hojtsy
committed
/**
* Calculate page number for first new comment.
*
* @param $num_comments
* Number of comments.
* @param $new_replies
* Number of new replies.
* @param $node
* The first new comment node.
* @return
* "page=X" if the page number is greater than zero; empty string otherwise.
Gábor Hojtsy
committed
*/
Dries Buytaert
committed
function comment_new_page_count($num_comments, $new_replies, $node) {
$comments_per_page = _comment_get_display_setting('comments_per_page', $node);
$mode = _comment_get_display_setting('mode', $node);
Gábor Hojtsy
committed
$pagenum = NULL;
$flat = in_array($mode, array(COMMENT_MODE_FLAT_COLLAPSED, COMMENT_MODE_FLAT_EXPANDED));
Dries Buytaert
committed
if ($num_comments <= $comments_per_page) {
// Only one page of comments.
Gábor Hojtsy
committed
$pageno = 0;
Dries Buytaert
committed
elseif ($flat) {
// Flat comments.
$count = $num_comments - $new_replies;
$pageno = $count / $comments_per_page;
}
Gábor Hojtsy
committed
else {
Dries Buytaert
committed
// Threaded comments.
// Find the first thread with a new comment.
Dries Buytaert
committed
$result = db_query_range('(SELECT thread
Dries Buytaert
committed
FROM {comment}
Dries Buytaert
committed
WHERE nid = :nid
AND status = 0
ORDER BY timestamp DESC)
Dries Buytaert
committed
ORDER BY SUBSTRING(thread, 1, (LENGTH(thread) - 1))', array(':nid' => $node->nid), 0, $new_replies)
->fetchField();
$thread = substr($result, 0, -1);
Dries Buytaert
committed
$count = db_query('SELECT COUNT(*) FROM {comment} WHERE nid = :nid AND status = 0 AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < :thread', array(
Dries Buytaert
committed
':nid' => $node->nid,
Dries Buytaert
committed
':thread' => $thread))
->fetchField();
Gábor Hojtsy
committed
$pageno = $count / $comments_per_page;
}
Gábor Hojtsy
committed
if ($pageno >= 1) {
$pagenum = "page=" . intval($pageno);
Gábor Hojtsy
committed
}
Gábor Hojtsy
committed
return $pagenum;
}
* Returns a formatted list of recent comments to be displayed in the comment block.
* @return
* The comment list HTML.
* @ingroup themeable
*/
function theme_comment_block() {
$items = array();
Dries Buytaert
committed
$number = variable_get('comment_block_count', 10);
foreach (comment_get_recent($number) as $comment) {
Dries Buytaert
committed
$items[] = l($comment->subject, 'node/' . $comment->nid, array('fragment' => 'comment-' . $comment->cid)) . '<br />' . t('@time ago', array('@time' => format_interval(REQUEST_TIME - $comment->timestamp)));
Dries Buytaert
committed
if ($items) {
return theme('item_list', $items);
}
* An implementation of hook_node_view().
function comment_node_view($node, $teaser) {
if ($node->comment) {
Neil Drumm
committed
if ($teaser) {
// Main page: display the number of comments that have been posted.
if (user_access('access comments')) {
if (!empty($node->comment_count)) {
Dries Buytaert
committed
$links['comment_comments'] = array(
Dries Buytaert
committed
'title' => format_plural($node->comment_count, '1 comment', '@count comments'),
'href' => "node/$node->nid",
'attributes' => array('title' => t('Jump to the first comment of this posting.')),
'fragment' => 'comments'
Dries Buytaert
committed
);
$new = comment_num_new($node->nid);
Dries Buytaert
committed
$links['comment_new_comments'] = array(
'title' => format_plural($new, '1 new comment', '@count new comments'),
'href' => "node/$node->nid",
Dries Buytaert
committed
'query' => comment_new_page_count($node->comment_count, $new, $node),
'attributes' => array('title' => t('Jump to the first new comment of this posting.')),
'fragment' => 'new'
Dries Buytaert
committed
);
if ($node->comment == COMMENT_NODE_READ_WRITE) {
Dries Buytaert
committed
$links['comment_add'] = array(
'title' => t('Add new comment'),
'href' => "comment/reply/$node->nid",
'attributes' => array('title' => t('Add a new comment to this page.')),
'fragment' => 'comment-form'
Dries Buytaert
committed
);
Dries Buytaert
committed
$links['comment_forbidden']['title'] = theme('comment_post_forbidden', $node);
// 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.
Dries Buytaert
committed
if ($node->comment == COMMENT_NODE_READ_WRITE) {
if (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
Dries Buytaert
committed
$links['comment_add'] = array(
Steven Wittens
committed
'title' => t('Add new comment'),
'href' => "comment/reply/$node->nid",
'attributes' => array('title' => t('Share your thoughts and opinions related to this posting.')),
'fragment' => 'comment-form'
Dries Buytaert
committed
);
Dries Buytaert
committed
}
Dries Buytaert
committed
$links['comment_forbidden']['title'] = theme('comment_post_forbidden', $node);
if (isset($links['comment_forbidden'])) {
$links['comment_forbidden']['html'] = TRUE;
}
$node->content['links']['comment'] = array(
'#type' => 'node_links',
'#value' => $links,
);
// Append the list of comments to $node->content for node detail pages.
Dries Buytaert
committed
if ($node->comment && (bool)menu_get_object() && $node->build_mode != NODE_BUILD_PREVIEW) {
$node->content['comments'] = array(
'#markup' => comment_render($node),
Dries Buytaert
committed
'#sorted' => TRUE,
);
}
/**
Angie Byron
committed
* Implementation of hook_form_FORM_ID_alter().
*/
Angie Byron
committed
function comment_form_node_type_form_alter(&$form, $form_state) {
if (isset($form['identity']['type'])) {
Dries Buytaert
committed
$form['comment'] = array(
'#type' => 'fieldset',
'#title' => t('Comment settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
Dries Buytaert
committed
);
$form['comment']['comment'] = array(
Neil Drumm
committed
'#type' => 'radios',
'#title' => t('Default comment setting'),
'#default_value' => variable_get('comment_' . $form['#node_type']->type, COMMENT_NODE_READ_WRITE),
Neil Drumm
committed
'#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.'),
);
Dries Buytaert
committed
$form['comment']['comment_default_mode'] = array(
'#type' => 'radios',
'#title' => t('Default display mode'),
'#default_value' => variable_get('comment_default_mode_' . $form['#node_type']->type, COMMENT_MODE_THREADED_EXPANDED),
Dries Buytaert
committed
'#options' => _comment_get_modes(),
'#description' => t('Expanded views display the body of the comment. Threaded views keep replies together.'),
Dries Buytaert
committed
);
$form['comment']['comment_default_per_page'] = array(
'#type' => 'select',
'#title' => t('Comments per page'),
'#default_value' => variable_get('comment_default_per_page_' . $form['#node_type']->type, 50),
Dries Buytaert
committed
'#options' => _comment_per_page(),
'#description' => t('Additional comments will be displayed on separate pages.'),
Dries Buytaert
committed
);
$form['comment']['comment_anonymous'] = array(
'#type' => 'radios',
'#title' => t('Anonymous commenting'),
'#default_value' => variable_get('comment_anonymous_' . $form['#node_type']->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT),
Dries Buytaert
committed
'#options' => array(
COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'),
COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'),
COMMENT_ANONYMOUS_MUST_CONTACT => t('Anonymous posters must leave their contact information')),
'#description' => t('This option is enabled when anonymous users have permission to post comments on the <a href="@url">permissions page</a>.', array('@url' => url('admin/user/permissions', array('fragment' => 'module-comment')))),
Dries Buytaert
committed
);
Gábor Hojtsy
committed
if (!user_access('post comments', drupal_anonymous_user())) {
Dries Buytaert
committed
$form['comment']['comment_anonymous']['#disabled'] = TRUE;
}
Dries Buytaert
committed
$form['comment']['comment_subject_field'] = array(
'#type' => 'radios',
'#title' => t('Comment subject field'),
'#default_value' => variable_get('comment_subject_field_' . $form['#node_type']->type, 1),
Dries Buytaert
committed
'#options' => array(t('Disabled'), t('Enabled')),
'#description' => t('Can users provide a unique subject for their comments?'),
);
$form['comment']['comment_preview'] = array(
'#type' => 'radios',
'#title' => t('Preview comment'),
'#default_value' => variable_get('comment_preview_' . $form['#node_type']->type, COMMENT_PREVIEW_REQUIRED),
Dries Buytaert
committed
'#options' => array(t('Optional'), t('Required')),
'#description' => t("Forces a user to look at their comment by clicking on a 'Preview' button before they can actually add the comment"),
);
$form['comment']['comment_form_location'] = array(
'#type' => 'radios',
'#title' => t('Location of comment submission form'),
'#default_value' => variable_get('comment_form_location_' . $form['#node_type']->type, COMMENT_FORM_SEPARATE_PAGE),
Dries Buytaert
committed
'#options' => array(t('Display on separate page'), t('Display below post or comments')),
);
Neil Drumm
committed
}
Angie Byron
committed
}
/**
* Implementation of hook_form_alter().
*/
function comment_form_alter(&$form, $form_state, $form_id) {
if (!empty($form['#node_edit_form'])) {
Dries Buytaert
committed
$node = $form['#node'];
$form['comment_settings'] = array(
'#type' => 'fieldset',
'#access' => user_access('administer comments'),
'#title' => t('Comment settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#weight' => 30,
);
$form['comment_settings']['comment'] = array(
'#type' => 'radios',
'#parents' => array('comment'),
'#default_value' => $node->comment,
'#options' => array(t('Disabled'), t('Read only'), t('Read/Write')),
);
Dries Buytaert
committed
}
}
* Implementation of hook_node_load().
function comment_node_load($nodes, $types) {
$comments_enabled = array();
// Check if comments are enabled for each node. If comments are disabled,
// assign values without hitting the database.
foreach ($nodes as $node) {
// Store whether comments are enabled for this node.
if ($node->comment != COMMENT_NODE_DISABLED) {
$comments_enabled[] = $node->nid;
}
else {
$node->last_comment_timestamp = $node->created;
$node->last_comment_name = '';
$node->comment_count = 0;
}
}
// For nodes with comments enabled, fetch information from the database.
if (!empty($comments_enabled)) {
Dries Buytaert
committed
$result = db_query('SELECT nid, last_comment_timestamp, last_comment_name, comment_count FROM {node_comment_statistics} WHERE nid IN(:comments_enabled)', array(':comments_enabled' => $comments_enabled));
foreach ($result as $record) {
$nodes[$record->nid]->last_comment_timestamp = $record->last_comment_timestamp;
$nodes[$record->nid]->last_comment_name = $record->last_comment_name;
$nodes[$record->nid]->comment_count = $record->comment_count;
}
Dries Buytaert
committed
}
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implementation of hook_node_prepare().
Dries Buytaert
committed
*/
function comment_node_prepare($node) {
Dries Buytaert
committed
if (!isset($node->comment)) {
$node->comment = variable_get("comment_$node->type", COMMENT_NODE_READ_WRITE);
}
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implementation of hook_node_insert().
Dries Buytaert
committed
*/
function comment_node_insert($node) {
Dries Buytaert
committed
db_insert('node_comment_statistics')
->fields(array(
'nid' => $node->nid,
'last_comment_timestamp' => $node->changed,
'last_comment_name' => NULL,
'last_comment_uid' => $node->uid,
'comment_count' => 0 ))
->execute();
Dries Buytaert
committed
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implementation of hook_node_delete().
Dries Buytaert
committed
*/
function comment_node_delete($node) {
Dries Buytaert
committed
db_delete('comment')
Dries Buytaert
committed
->condition('nid', $node->nid)
->execute();
db_delete('node_comment_statistics')
->condition('nid', $node->nid)
->execute();
Dries Buytaert
committed
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implementation of hook_node_update_index().
Dries Buytaert
committed
*/
function comment_node_update_index($node) {
Dries Buytaert
committed
$text = '';
Dries Buytaert
committed
$comments = db_query('SELECT subject, comment, format FROM {comment} WHERE nid = :nid AND status = :status', array(':nid' => $node->nid, ':status' => COMMENT_PUBLISHED));
Dries Buytaert
committed
foreach ($comments as $comment) {
$text .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, FALSE);
Dries Buytaert
committed
}
return $text;
}
Dries Buytaert
committed
/**
* Implementation of hook_update_index().
*/
function comment_update_index() {
// Store the maximum possible comments per thread (used for ranking by reply count)
variable_set('node_cron_comments_scale', 1.0 / max(1, db_query('SELECT MAX(comment_count) FROM {node_comment_statistics}')->fetchField()));
}
Dries Buytaert
committed
/**
* Implementation of hook_node_search_result().
Dries Buytaert
committed
*/
function comment_node_search_result($node) {
Dries Buytaert
committed
$comments = db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = :nid', array('nid' => $node->nid))->fetchField();
Dries Buytaert
committed
return format_plural($comments, '1 comment', '@count comments');
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implementation of hook_node_rss_item().
Dries Buytaert
committed
*/
function comment_node_rss_item($node) {
Dries Buytaert
committed
if ($node->comment != COMMENT_NODE_DISABLED) {
return array(array('key' => 'comments', 'value' => url('node/' . $node->nid, array('fragment' => 'comments', 'absolute' => TRUE))));
}
else {
return array();
Angie Byron
committed
* Implementation of hook_user_cancel().
function comment_user_cancel($edit, $account, $method) {
Angie Byron
committed
switch ($method) {
case 'user_cancel_block_unpublish':
db_update('comment')->fields(array('status' => 0))->condition('uid', $account->uid)->execute();
db_update('node_comment_statistics')->fields(array('last_comment_uid' => 0))->condition('last_comment_uid', $account->uid)->execute();
break;
case 'user_cancel_reassign':
db_update('comment')->fields(array('uid' => 0))->condition('uid', $account->uid)->execute();
db_update('node_comment_statistics')->fields(array('last_comment_uid' => 0))->condition('last_comment_uid', $account->uid)->execute();
break;
case 'user_cancel_delete':
module_load_include('inc', 'comment', 'comment.admin');
$comments = db_select('comment', 'c')->fields('c', array('cid'))->condition('uid', $account->uid)->execute()->fetchCol();
foreach ($comments as $cid) {
$comment = comment_load($cid);
// Delete the comment and its replies.
_comment_delete_thread($comment);
_comment_update_node_statistics($comment->nid);
}
break;
}
/**
* 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 to their posts.
*
* @param $op
* The operation that is to be performed on the comment. Only 'edit' is recognized now.
* @param $comment
* The comment object.
* @return
* TRUE if the current user has acces to the comment, FALSE otherwise.
Dries Buytaert
committed
return ($user->uid && $user->uid == $comment->uid && comment_num_replies($comment->cid) == 0) || user_access('administer comments');
/**
* A simple helper function.
*
* @return
* The 0th and the 1st path components joined by a slash.
*/
return arg(0) . '/' . arg(1);
Dries Buytaert
committed
/**
* 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
Dries Buytaert
committed
* is not saved, FALSE is returned.
*/
function comment_save($edit) {
$node = node_load($edit['nid']);
if (user_access('post comments') && (user_access('administer comments') || $node->comment == COMMENT_NODE_READ_WRITE)) {
Gábor Hojtsy
committed
$edit += array(
'mail' => '',
'homepage' => '',
'name' => '',
'status' => user_access('post comments without approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED,
);
if ($edit['cid']) {
Dries Buytaert
committed
// Update the comment in the database.
Dries Buytaert
committed
db_update('comment')
Dries Buytaert
committed
->fields(array(
'status' => $edit['status'],
'timestamp' => $edit['timestamp'],
'subject' => $edit['subject'],
'comment' => $edit['comment'],
'format' => $edit['comment_format'],
'uid' => $edit['uid'],
'name' => $edit['name'],
'mail' => $edit['mail'],
'homepage' => $edit['homepage']
))
->condition('cid', $edit['cid'])
->execute();
// Allow modules to respond to the updating of a comment.
comment_invoke_comment($edit, 'update');
watchdog('content', 'Comment: updated %subject.', array('%subject' => $edit['subject']), WATCHDOG_NOTICE, l(t('view'), 'node/' . $edit['nid'], array('fragment' => 'comment-' . $edit['cid'])));
// Add the comment to database. This next section builds the thread field.
// Also see the documentation for comment_render().
if ($edit['pid'] == 0) {
// This is a comment with no parent comment (depth 0): we start
// by retrieving the maximum thread level.
Dries Buytaert
committed
$max = db_query('SELECT MAX(thread) FROM {comment} WHERE nid = :nid', array(':nid' => $edit['nid']))->fetchField();
// Strip the "/" from the end of the thread.
$max = rtrim($max, '/');
// Finally, build the thread field for this new comment.
$thread = int2vancode(vancode2int($max) + 1) . '/';
// This is a comment with a parent comment, so increase
// the part of the thread value at the proper depth.
Dries Buytaert
committed
$parent = comment_load($edit['pid']);
// Strip the "/" from the end of the parent thread.
$parent->thread = (string) rtrim((string) $parent->thread, '/');
// Get the max value in *this* thread.
Dries Buytaert
committed
$max = db_query("SELECT MAX(thread) FROM {comment} WHERE thread LIKE :thread AND nid = :nid", array(
Dries Buytaert
committed
':thread' => $parent->thread .'.%',
Dries Buytaert
committed
':nid' => $edit['nid']))
->fetchField();
if ($max == '') {
// First child of this parent.
$thread = $parent->thread . '.' . int2vancode(0) . '/';
// Strip the "/" at the end of the thread.
$max = rtrim($max, '/');
// Get the value at the correct depth.
$parts = explode('.', $max);
$parent_depth = count(explode('.', $parent->thread));
// Finally, build the thread field for this new comment.
$thread = $parent->thread . '.' . int2vancode(vancode2int($last) + 1) . '/';
if (empty($edit['timestamp'])) {
Dries Buytaert
committed
$edit['timestamp'] = REQUEST_TIME;
}
Dries Buytaert
committed
if ($edit['uid'] === $user->uid && isset($user->name)) { // '===' Need to modify anonymous users as well.
Gábor Hojtsy
committed
Dries Buytaert
committed
$edit['cid'] = db_insert('comment')
Dries Buytaert
committed
->fields(array(
'nid' => $edit['nid'],
'pid' => empty($edit['pid']) ? 0 : $edit['pid'],
Dries Buytaert
committed
'uid' => $edit['uid'],
Dries Buytaert
committed
'subject' => $edit['subject'],
'comment' => $edit['comment'],
'format' => $edit['comment_format'],
'hostname' => ip_address(),
'timestamp' => $edit['timestamp'],
'status' => $edit['status'],
'thread' => $thread,
'name' => $edit['name'],
'mail' => $edit['mail'],
'homepage' => $edit['homepage']
))
->execute();
// Tell the other modules a new comment has been submitted.
comment_invoke_comment($edit, 'insert');
// Add an entry to the watchdog log.
watchdog('content', 'Comment: added %subject.', array('%subject' => $edit['subject']), WATCHDOG_NOTICE, l(t('view'), 'node/' . $edit['nid'], array('fragment' => 'comment-' . $edit['cid'])));
_comment_update_node_statistics($edit['nid']);
// Clear the cache so an anonymous user can see his comment being added.
Gábor Hojtsy
committed
if ($edit['status'] == COMMENT_NOT_PUBLISHED) {
if (!user_access('administer comments')) {
Dries Buytaert
committed
drupal_set_message(t('Your comment has been queued for review by site administrators and will be published after approval.'));
}
Gábor Hojtsy
committed
else {
drupal_set_message(t('Your comment has been posted.'));
Gábor Hojtsy
committed
comment_invoke_comment($edit, 'publish');
Gábor Hojtsy
committed
}
Dries Buytaert
committed
return $edit['cid'];
Dries Buytaert
committed
return FALSE;
Gábor Hojtsy
committed
watchdog('content', 'Comment: unauthorized comment submitted or comment submitted to a closed post %subject.', array('%subject' => $edit['subject']), WATCHDOG_WARNING);
drupal_set_message(t('Comment: unauthorized comment submitted or comment submitted to a closed post %subject.', array('%subject' => $edit['subject'])), 'error');
Dries Buytaert
committed
return FALSE;
// An implementation of hook_link().
function comment_link($type, $object, $teaser) {
if ($type == 'comment') {
$links = comment_links($object, FALSE);
return $links;
}
}
/**
* Build command links for a comment (e.g.\ edit, reply, delete) with respect to the current user's access permissions.
*
* @param $comment
* The comment to which the links will be related.
* @param $return
* Not used.
* @return
* An associative array containing the links.
*/
// If viewing just this comment, link back to the node.
Dries Buytaert
committed
$links['comment_parent'] = array(
'title' => t('parent'),
'href' => comment_node_url(),
'fragment' => "comment-$comment->cid"
Dries Buytaert
committed
);
$node = node_load($comment->nid);
if ($node->comment == COMMENT_NODE_READ_WRITE) {
Dries Buytaert
committed
if (user_access('administer comments') && user_access('post comments')) {
Dries Buytaert
committed
$links['comment_delete'] = array(
'title' => t('delete'),
'href' => "comment/delete/$comment->cid"
Dries Buytaert
committed
);
$links['comment_edit'] = array(
'title' => t('edit'),
'href' => "comment/edit/$comment->cid"
Dries Buytaert
committed
);
$links['comment_reply'] = array(
'title' => t('reply'),
'href' => "comment/reply/$comment->nid/$comment->cid"
Dries Buytaert
committed
);
Dries Buytaert
committed
if ($comment->status == COMMENT_NOT_PUBLISHED) {
$links['comment_approve'] = array(
'title' => t('approve'),
'href' => "comment/approve/$comment->cid"
);
}
Dries Buytaert
committed
}
elseif (user_access('post comments')) {
if (comment_access('edit', $comment)) {
Dries Buytaert
committed
$links['comment_edit'] = array(
'title' => t('edit'),
'href' => "comment/edit/$comment->cid"
Dries Buytaert
committed
);
Dries Buytaert
committed
$links['comment_reply'] = array(
'title' => t('reply'),
'href' => "comment/reply/$comment->nid/$comment->cid"
Dries Buytaert
committed
);
Dries Buytaert
committed
$node = node_load($comment->nid);
$links['comment_forbidden']['title'] = theme('comment_post_forbidden', $node);
/**
* Renders comment(s).
*
* @param $node
* The node which comment(s) needs rendering.
* @param $cid
* Optional, if given, only one comment is rendered.
*
* To display threaded comments in the correct order we keep a 'thread' field
* and order by that value. This 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:
*