Index: modules/tracker/tracker.module =================================================================== RCS file: /cvs/drupal/drupal/modules/tracker/tracker.module,v retrieving revision 1.143.2.2 diff -u -r1.143.2.2 tracker.module --- modules/tracker/tracker.module 26 Jul 2007 19:16:50 -0000 1.143.2.2 +++ modules/tracker/tracker.module 27 Jul 2007 13:51:30 -0000 @@ -101,7 +101,7 @@ if ($new = comment_num_new($node->nid)) { $comments .= '
'; - $comments .= l(format_plural($new, '1 new', '@count new'), "node/$node->nid", NULL, NULL, 'new'); + $comments .= l(format_plural($new, '1 new', '@count new'), "node/$node->nid", NULL, comment_page_new_query($node->nid), 'new'); } } Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.375.2.5 diff -u -r1.375.2.5 forum.module --- modules/forum/forum.module 31 May 2007 05:58:17 -0000 1.375.2.5 +++ modules/forum/forum.module 27 Jul 2007 13:51:30 -0000 @@ -1001,7 +1001,7 @@ $rows[] = array( array('data' => theme('forum_icon', $topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky), 'class' => 'icon'), array('data' => l($topic->title, "node/$topic->nid"), 'class' => 'topic'), - array('data' => $topic->num_comments . ($topic->new_replies ? '
'. l(format_plural($topic->new_replies, '1 new', '@count new'), "node/$topic->nid", NULL, NULL, 'new') : ''), 'class' => 'replies'), + array('data' => $topic->num_comments . ($topic->new_replies ? '
'. l(format_plural($topic->new_replies, '1 new', '@count new'), "node/$topic->nid", NULL, comment_page_new_query($topic->nid), 'new') : ''), 'class' => 'replies'), array('data' => _forum_format($topic), 'class' => 'created'), array('data' => _forum_format(isset($topic->last_reply) ? $topic->last_reply : NULL), 'class' => 'last-reply') ); Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.520.2.6 diff -u -r1.520.2.6 comment.module --- modules/comment/comment.module 26 Jul 2007 19:16:45 -0000 1.520.2.6 +++ modules/comment/comment.module 27 Jul 2007 13:51:25 -0000 @@ -249,19 +249,22 @@ // Select the $number nodes (visible to the current user) with the most // recent comments. This is efficient due to the index on // last_comment_timestamp. - $result = db_query_range(db_rewrite_sql("SELECT nc.nid FROM {node_comment_statistics} nc WHERE nc.comment_count > 0 ORDER BY nc.last_comment_timestamp DESC", 'nc'), 0, $number); + $result = db_query_range(db_rewrite_sql("SELECT nc.nid, nc.comment_count FROM {node_comment_statistics} nc WHERE nc.comment_count > 0 ORDER BY nc.last_comment_timestamp DESC", 'nc'), 0, $number); $nids = array(); + $comment_counts = array(); while ($row = db_fetch_object($result)) { $nids[] = $row->nid; + $comment_counts[$row->nid] = $row->comment_count; } $comments = array(); if (!empty($nids)) { // From among the comments on the nodes selected in the first query, // find the $number most recent comments. - $result = db_query_range('SELECT c.nid, c.subject, c.cid, c.timestamp FROM {comments} c INNER JOIN {node} n ON n.nid = c.nid WHERE c.nid IN ('. implode(',', $nids) .') AND n.status = 1 AND c.status = %d ORDER BY c.timestamp DESC', COMMENT_PUBLISHED, 0, $number); + $result = db_query_range('SELECT c.nid, c.subject, c.cid, c.timestamp, c.thread FROM {comments} c INNER JOIN {node} n ON n.nid = c.nid WHERE c.nid IN ('. implode(',', $nids) .') AND n.status = 1 AND c.status = %d ORDER BY c.timestamp DESC', COMMENT_PUBLISHED, 0, $number); while ($comment = db_fetch_object($result)) { + $comment->comment_count = $comment_counts[$comment->nid]; $comments[] = $comment; } } @@ -278,7 +281,7 @@ function theme_comment_block() { $items = array(); foreach (comment_get_recent() as $comment) { - $items[] = l($comment->subject, 'node/'. $comment->nid, NULL, NULL, 'comment-'. $comment->cid) .'
'. t('@time ago', array('@time' => format_interval(time() - $comment->timestamp))); + $items[] = l($comment->subject, 'node/'. $comment->nid, NULL, comment_page_query($comment), 'comment-'. $comment->cid) .'
'. t('@time ago', array('@time' => format_interval(time() - $comment->timestamp))); } if ($items) { return theme('item_list', $items); @@ -313,6 +316,7 @@ $links['comment_new_comments'] = array( 'title' => format_plural($new, '1 new comment', '@count new comments'), 'href' => "node/$node->nid", + 'query' => comment_page_new_query($node->nid), 'attributes' => array('title' => t('Jump to the first new comment of this posting.')), 'fragment' => 'new' ); @@ -1321,13 +1325,22 @@ return db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $cid)); } -function comment_num_all($nid) { +/** + * get number of comments for specified node + */ +function comment_num_all($nid, $include_not_published = FALSE) { static $cache; - - if (!isset($cache[$nid])) { - $cache[$nid] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid)); + $key = $include_not_published ? 'published_unpublished' : 'published'; + + if (!isset($cache[$nid][$key])) { + if ($include_not_published || user_access('administer comments')) { + $cache[$nid] = db_fetch_array(db_query('SELECT COUNT(*) AS published_unpublished, ncs.comment_count AS published FROM {comments} c INNER JOIN {node_comment_statistics} ncs ON ncs.nid = c.nid WHERE c.nid = %d GROUP BY c.nid, ncs.comment_count', $nid)); + } + else { + $cache[$nid][$key] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid)); + } } - return $cache[$nid]; + return $cache[$nid][$key]; } function comment_num_replies($pid) { @@ -1348,25 +1361,7 @@ * 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); - } - $timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT); - - // Use the timestamp to retrieve the number of new comments. - $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)); - - return $result; - } - else { - return 0; - } - + return _comment_new_comments($nid, 'num', $timestamp); } function comment_validate($edit) { @@ -1672,7 +1667,8 @@ function comment_form_submit($form_id, $form_values) { $form_values = _comment_form_submit($form_values); if ($cid = comment_save($form_values)) { - return array('node/'. $form_values['nid'], NULL, "comment-$cid"); + $comment = db_fetch_object(db_query('SELECT c.cid, c.nid, c.timestamp, c.thread, ncs.comment_count FROM {comments} c INNER JOIN {node_comment_statistics} ncs ON ncs.nid = c.nid WHERE cid = %d', $cid)); + return array('node/'. $form_values['nid'], comment_page_query($comment), "comment-$cid"); } } @@ -1939,6 +1935,130 @@ } /** + * Return an URL query string that points to the page the comment is on. + * Used in links to comments (e.g. 'recent comments' block). + * + * @param $comment + * A comment object. + * Required fields: 'nid', 'timestamp', 'thread' + * Optional field: 'comment_count' (to save a db query get this field by + * doing a JOIN of the node_comment_statistics on the comments table) + */ +function comment_page_query($comment) { + $page = _comment_page($comment); + return $page ? "page=$page" : NULL; +} + +/** + * Return an URL query string that points to the page the node's first new + * comment is on. Used in links to new comments ('# new' links). + * + * @param $nid + * A node ID. + */ +function comment_page_new_query($nid) { + $comments_per_page = _comment_get_display_setting('comments_per_page'); + $comments_num = comment_num_all($nid, user_access('administer comments')); + if ($comments_num <= $comments_per_page) { + // one page of comments only + return NULL; + } + else { + // get the node's first new comment + $cid = _comment_new_comments($nid, 'first'); + $comment = db_fetch_object(db_query('SELECT nid, timestamp, thread FROM {comments} WHERE cid = %d', $cid)); + return comment_page_query($comment); + } +} + +/** + * Return the page a comment is on + */ +function _comment_page($comment) { + $comments_per_page = _comment_get_display_setting('comments_per_page'); + if (user_access('administer comments')) { + // For users with 'administer comments' permission + // we have to count published and unpublished comments. + $comments_num = comment_num_all($comment->nid, TRUE); + } + else { + $comments_num = isset($comment->comment_count) ? $comment->comment_count : comment_num_all($comment->nid); + } + if ($comments_num <= $comments_per_page) { + // one page of comments only + return 0; + } + else { + // Build the database query that retrieves the comment's position + // This follows the same sheme as in comment_render(). + // See comments there for an explanation. + $query = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d'; + $query_args = array($comment->nid); + + if (!user_access('administer comments')) { + $query .= ' AND status = %d'; + $query_args[] = COMMENT_PUBLISHED; + } + + $mode = _comment_get_display_setting('mode'); + $order = _comment_get_display_setting('sort'); + if ($order == COMMENT_ORDER_NEWEST_FIRST) { + if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) { + $query .= ' AND timestamp > %d'; + $query_args[] = $comment->timestamp; + } + else { + $query .= " AND thread > '%s'"; + $query_args[] = $comment->thread; + } + } + else if ($order == COMMENT_ORDER_OLDEST_FIRST) { + if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) { + $query .= ' AND timestamp < %d'; + $query_args[] = $comment->timestamp; + } + else { + $query .= " AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < '%s'"; + $query_args[] = substr($comment->thread, 0, -1); + } + } + + $count = db_result(db_query($query, $query_args)); + return floor($count / $comments_per_page); + } +} + +/** + * Return the specified node's number of new comments ($key = 'num') + * or the first new comment ($key = 'first') for the current user + */ +function _comment_new_comments($nid, $key, $timestamp = 0) { + global $user; + static $cache = array(); + + if ($user->uid) { + if (!isset($cache[$nid])) { + // Retrieve the timestamp at which the current user last viewed the + // specified node. + if (!$timestamp) { + $timestamp = node_last_viewed($nid); + } + $timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT); + + // Use the timestamp to retrieve the number of new comments + // and the first new comment + $result = db_query('SELECT COUNT(cid) AS num, MIN(cid) AS first FROM {comments} WHERE nid = %d AND timestamp > %d AND status = %d', $nid, $timestamp, COMMENT_PUBLISHED); + $cache[$nid] = db_fetch_array($result); + } + return $cache[$nid][$key]; + } + else { + return NULL; + } + +} + +/** * Updates the comment statistics for a given node. This should be called any * time a comment is added, deleted, or updated. *