Drupal: sequentially number comments across pages

In comment.tpl.php
the variable $id
contains the comment sequence number, but only for the current page. Each page will start at 1.
In order to properly sequentially number the comments across multiple pages, you need to multiply the number of comments per page by the current page number, plus the comment ID. (The first page is 0.)
Just as I was thinking about this, I found a little gem on the Drupal site. I placed the following in my comment.tpl.php
:
<?php
$page = $_GET['page'];
if (!$page) {
$page = 0;
}
$comments_per_page =
_comment_get_display_setting('comments_per_page');
$comment_index = ( $page * $comments_per_page ) + $id;
print l('#' . $comment_index, 'node/' . $comment->nid , array(), null, 'comment-' . $comment->cid, false, true);
?>
The number of comments per page is defined in the comment settings (content/comment/settings) and that value is stored in the variable
table as comment_default_per_page
. You can retrieve that value with variable_get('comment_default_per_page', 30)
or _comment_get_display_setting('comments_per_page')
. Then it is simply a matter of multiplying that value with the current page number — retrieved with $_GET['page']
— and offsetting that by the current comment ID $id
.
I turned the whole thing into a link with the l()
function.
Now the comments are properly numbered across subsequent pages.
Code for Drupal 5.x
A much cleaner solution is to move this code to template.php
to keep the comment template clean.
In Drupal 5.x add this to the function _phptemplate_variables()
in template.php
:
<?php
function _phptemplate_variables($hook, $vars) {
//Calculate true comment index
if ($hook == 'comment') {
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 0;
$comments_per_page =
_comment_get_display_setting('comments_per_page');
$comment_index_nbr = ( $page * $comments_per_page ) + $vars['id'];
$vars['comment_index'] = l(
'#' . $comment_index_nbr, 'node/' . $vars['comment']->cid,
array(), null, 'comment-' . $vars['comment']->cid, false, true
);
}
return $vars;
}
?>
You can then add <?php print $comment_index; ?>
to the comment.tpl.php
template file.
Code for Drupal 6.x and 7.x
Add the following to the function phptemplate_preprocess_comment()
in template.php
. Please note that the function _comment_get_display_setting()
expects an additional parameter in Drupal 6/7.
In Drupal 6 the l()
function changed significantly (what a joy changing all nodes that use it).
<?php
function phptemplate_preprocess_comment(&$vars) {
// Calculate the true comment index
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 0;
$comments_per_page =
_comment_get_display_setting('comments_per_page', $vars['node']);
$index = ( $page * $comments_per_page ) + $vars['id'];
$vars['comment_index'] = l(
'#' . $index, 'node/' . $vars['comment']->nid,
array(
'fragment'=>'comment-' . $vars['comment']->cid,
'attributes' => array(
'title' => t("Link to this comment")
),
)
);
return $vars;
}
?>
Again, you can use <?php print $comment_index; ?>
in the comment template file to display this index number.
Comments
In D7 this works for me...
<?php
/* Preprocess comments */
function stomper_preprocess_comment(&$vars) {
// set a comment id...
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 0;
$comments_per_page = variable_get('comment_default_per_page_' . $vars['node']->type, 50);
$vars['index'] = ( $page * $comments_per_page ) + $vars['id'];
...
}
?>
Your code is pretty much the same, with these differences:
variable_get()
to retrieve the comments per page value. In essence, the function_comment_get_display_setting()
calls the same function.<?php
// Page number
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 0;
// Retrieve comments per page for current node type
$comments_per_page = variable_get('comment_default_per_page_' .
$vars['node']->type, 1);
// Calculate true comment index
$index = $page * $comments_per_page + $vars['id'];
// Return comment index as a link to the current comment
$vars['comment_index_test'] = l(
'#' . $index, 'node/' . $vars['comment']->nid,
array(
'fragment'=>'comment-' . $vars['comment']->cid,
'attributes' => array(
'title' => t("Permanent link to this comment")
),
)
);
?>
Good to know it still works in Drupal 7. I haven't taken the plunge yet as there are still several modules without Drupal 7 equivalent.
Thanks for your feedback!
Awesome!! Works great. Thanks for sharing.
You're welcome!
in drupal 7.15. The follow errors show up:
Notice: Undefined variable: comment_index 在 include() (line 30 in .......p/templates/comment.tpl.php).
Could you help me to fix it ?
I'll test it tomorrow on my test machine.
Rename the function to
MYTHEME_preprocess_comment()
instead.it still doesn't work for me... I have added the function MYTHEME_preprocess_comment(&$variables) { }
into my template.php..
Replace the MYTHEME with the name of your theme. For example, if you're using Garland name the function
garland_preprocess_comment()
Hi Planken
It's bit chilly weather in Sundre ))
Thanks for the very good article, I'm surprised there is no such standard variable as comment id with the link.
I've tried it on my Drupal 7.20 with Professional theme (http://drupal.org/project/professional_theme), but doesn't seem to work.
Could you please help?
I took the function from your article for D7, renamed it to professional_theme_preprocess_comment() and put it inside sites/all/themes/professional_theme/template.php
I've put into comment.tpl.php
I get error message:
Notice: Undefined variable: comment_index in include() (line 73 of /..../sites/all/themes/professional_theme/templates/comment.tpl.php).
Not sure what the standard is but I used
$vars
for the function, but some themes use$variables
, could that be an issue? I'll have to test this tonight on a fresh Drupal 7 installation.Hi mate
I've tried this. Now page stops loading somewhere near comments, without any obvious error message. At least it means Drupal calls this function professional_theme_preprocess_comment(). It happens even without printing $comment_index in the comment.tpl.php
What's the best way to debug the function? E.g. print some test output\variables...
Sorry for the newbie questions, they should not be in this thread...
I hope this is in a test environment?
First of all, temporarily revert back to a fresh copy of theme you are using and see if the page loads properly. If it does, the problem is with any code that was added or modified. If the pages still don't load, revert back to a built-inl theme without any changes you may have made.
Once the page loads, you could add the code for the comment numbering in the preprocess function and see if it works even without printing the variable in he template. Then you could add back any changes to the preprocess function.
I know I had this snippet added to a fresh Drupal 7 installation so I know it works. But sometimes added modules or themes can interfere with code changes so if things still aren't working you may have to look at modules you may have added that interact with the comments.
(Note: there is an issue with comments spanning multiple pages. I have solved that on this site with an ugly work-around that I should have added to this post. I will do that as soon as I have time.)
I just downloaded
professional_theme
and realized from the comment template (that seems to be taken from the Bartik theme) thatcomment.tpl.php
has a variable called$permalink
created by Drupal 7's functioncomment_permalink()
(incomment.module
) that seems to do exactly this. It seems that there would be no need for additional code intemplate.php
.I have had a long day, so maye I am not seeing this clearly now.
<?php
/**
* Redirects comment links to the correct page depending on comment settings.
*
* Since comments are paged there is no way to guarantee which page a comment
* appears on. Comment paging and threading settings may be changed at any time.
* With threaded comments, an individual comment may move between pages as
* comments can be added either before or after it in the overall discussion.
* Therefore we use a central routing function for comment links, which
* calculates the page number based on current comment settings and returns
* the full comment view with the pager set dynamically.
*
* @param $cid
* A comment identifier.
* @return
* The comment listing set to the page on which the comment appears.
*/
function comment_permalink($cid) {
if (($comment = comment_load($cid)) && ($node = node_load($comment->nid))) {
// Find the current display page for this comment.
$page = comment_get_display_page($comment->cid, $node->type);
// Set $_GET['q'] and $_GET['page'] ourselves so that the node callback
// behaves as it would when visiting the page directly.
$_GET['q'] = 'node/' . $node->nid;
$_GET['page'] = $page;
// Return the node view, this will show the correct comment in context.
return menu_execute_active_handler('node/' . $node->nid, FALSE);
}
drupal_not_found();
}
?>
Your code work great.
But in my theme, _comment_get_display_setting() is not working (cause the comments area gone and lost all the css style)
variable_get() did the trick