mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-06-28 22:30:04 +00:00
Force comment pagination on single posts.
Previously, the 'page_comments' toggle allowed users to disable comment pagination. This toggle was only superficial, however. Even with 'page_comments' turned on, `comments_template()` loaded all of a post's comments into memory, and passed them to `wp_list_comments()` and `Walker_Comment`, the latter of which produced markup for only the current page of comments. In other words, it was possible to enable 'page_comments', thereby showing only a subset of a post's comments on a given page, but all comments continued to be loaded in the background. This technique scaled poorly. Posts with hundreds or thousands of comments would load slowly, or not at all, even when the 'comments_per_page' setting was set to a reasonable number. Recent changesets have addressed this problem through more efficient tree- walking, better descendant caching, and more selective queries for top-level post comments. The current changeset completes the project by addressing the root issue: that loading a post causes all of its comments to be loaded too. Here's the breakdown: * Comment pagination is now forced. Setting 'page_comments' to false leads to evil things when you have many comments. If you want to avoid pagination, set 'comments_per_page' to something high. * The 'page_comments' setting has been expunged from options-discussion.php, and from places in the codebase where it was referenced. For plugins relying on 'page_comments', we now force the value to `true` with a `pre_option` filter. * `comments_template()` now queries for an appropriately small number of comments. Usually, this means the `comments_per_page` value. * To preserve the current (odd) behavior for comment pagination links, some unholy hacks have been inserted into `comments_template()`. The ugliness is insulated in this function for backward compatibility and to minimize collateral damage. A side-effect is that, for certain settings of 'default_comments_page', up to 2x the value of `comments_per_page` might be fetched at a time. * In support of these changes, a `$format` parameter has been added to `WP_Comment::get_children()`. This param allows you to request a flattened array of comment children, suitable for feeding into `Walker_Comment`. * `WP_Query` loops are now informed about total available comment counts and comment pages by the `WP_Comment_Query` (`found_comments`, `max_num_pages`), instead of by `Walker_Comment`. Aside from radical performance improvements in the case of a post with many comments, this changeset fixes a bug that caused the first page of comments to be partial (`found_comments` % `comments_per_page`), rather than the last, as you'd expect. Props boonebgorges, wonderboymusic. Fixes #8071. git-svn-id: https://develop.svn.wordpress.org/trunk@34561 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -683,7 +683,7 @@ function get_comment_link( $comment = null, $args = array() ) {
|
||||
$defaults = array( 'type' => 'all', 'page' => '', 'per_page' => '', 'max_depth' => '' );
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
if ( '' === $args['per_page'] && get_option('page_comments') )
|
||||
if ( '' === $args['per_page'] )
|
||||
$args['per_page'] = get_option('comments_per_page');
|
||||
|
||||
if ( empty($args['per_page']) ) {
|
||||
@@ -1214,10 +1214,11 @@ function comments_template( $file = '/comments.php', $separate_comments = false
|
||||
$comment_author_url = esc_url($commenter['comment_author_url']);
|
||||
|
||||
$comment_args = array(
|
||||
'order' => 'ASC',
|
||||
'orderby' => 'comment_date_gmt',
|
||||
'status' => 'approve',
|
||||
'post_id' => $post->ID,
|
||||
'hierarchical' => 'threaded',
|
||||
'no_found_rows' => false,
|
||||
'update_comment_meta_cache' => false, // We lazy-load comment meta for performance.
|
||||
);
|
||||
|
||||
@@ -1227,7 +1228,87 @@ function comments_template( $file = '/comments.php', $separate_comments = false
|
||||
$comment_args['include_unapproved'] = array( $comment_author_email );
|
||||
}
|
||||
|
||||
$comments = get_comments( $comment_args );
|
||||
$per_page = (int) get_query_var( 'comments_per_page' );
|
||||
if ( 0 === $per_page ) {
|
||||
$per_page = (int) get_option( 'comments_per_page' );
|
||||
}
|
||||
|
||||
$flip_comment_order = $trim_comments_on_page = false;
|
||||
if ( $post->comment_count > $per_page ) {
|
||||
$comment_args['number'] = $per_page;
|
||||
|
||||
/*
|
||||
* For legacy reasons, higher page numbers always mean more recent comments, regardless of sort order.
|
||||
* Since we don't have full pagination info until after the query, we use some tricks to get the
|
||||
* right comments for the current page.
|
||||
*
|
||||
* Abandon all hope, ye who enter here!
|
||||
*/
|
||||
$page = (int) get_query_var( 'cpage' );
|
||||
if ( 'newest' === get_option( 'default_comments_page' ) ) {
|
||||
if ( $page ) {
|
||||
$comment_args['order'] = 'ASC';
|
||||
|
||||
/*
|
||||
* We don't have enough data (namely, the total number of comments) to calculate an
|
||||
* exact offset. We'll fetch too many comments, and trim them as needed
|
||||
* after the query.
|
||||
*/
|
||||
$offset = ( $page - 2 ) * $per_page;
|
||||
if ( 0 > $offset ) {
|
||||
// `WP_Comment_Query` doesn't support negative offsets.
|
||||
$comment_args['offset'] = 0;
|
||||
} else {
|
||||
$comment_args['offset'] = $offset;
|
||||
}
|
||||
|
||||
// Fetch double the number of comments we need.
|
||||
$comment_args['number'] += $per_page;
|
||||
$trim_comments_on_page = true;
|
||||
} else {
|
||||
$comment_args['order'] = 'DESC';
|
||||
$comment_args['offset'] = 0;
|
||||
$flip_comment_order = true;
|
||||
}
|
||||
} else {
|
||||
$comment_args['order'] = 'ASC';
|
||||
if ( $page ) {
|
||||
$comment_args['offset'] = ( $page - 1 ) * $per_page;
|
||||
} else {
|
||||
$comment_args['offset'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$comment_query = new WP_Comment_Query( $comment_args );
|
||||
$_comments = $comment_query->comments;
|
||||
|
||||
// Delightful pagination quirk #1: first page of results sometimes needs reordering.
|
||||
if ( $flip_comment_order ) {
|
||||
$_comments = array_reverse( $_comments );
|
||||
}
|
||||
|
||||
// Delightful pagination quirk #2: reverse chronological order requires page shifting.
|
||||
if ( $trim_comments_on_page ) {
|
||||
// Correct the value of max_num_pages, which is wrong because we manipulated the per_page 'number'.
|
||||
$comment_query->max_num_pages = ceil( $comment_query->found_comments / $per_page );
|
||||
|
||||
// Identify the number of comments that should appear on page 1.
|
||||
$page_1_count = $comment_query->found_comments - ( ( $comment_query->max_num_pages - 1 ) * $per_page );
|
||||
|
||||
// Use that value to shift the matched comments.
|
||||
if ( 1 === $page ) {
|
||||
$_comments = array_slice( $_comments, 0, $page_1_count );
|
||||
} else {
|
||||
$_comments = array_slice( $_comments, $page_1_count, $per_page );
|
||||
}
|
||||
}
|
||||
|
||||
// Trees must be flattened before they're passed to the walker.
|
||||
$comments_flat = array();
|
||||
foreach ( $_comments as $_comment ) {
|
||||
$comments_flat = array_merge( $comments_flat, array( $_comment ), $_comment->get_children( 'flat' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the comments array.
|
||||
@@ -1237,9 +1318,10 @@ function comments_template( $file = '/comments.php', $separate_comments = false
|
||||
* @param array $comments Array of comments supplied to the comments template.
|
||||
* @param int $post_ID Post ID.
|
||||
*/
|
||||
$wp_query->comments = apply_filters( 'comments_array', $comments, $post->ID );
|
||||
$wp_query->comments = apply_filters( 'comments_array', $comments_flat, $post->ID );
|
||||
$comments = &$wp_query->comments;
|
||||
$wp_query->comment_count = count($wp_query->comments);
|
||||
$wp_query->max_num_comment_pages = $comment_query->max_num_pages;
|
||||
|
||||
if ( $separate_comments ) {
|
||||
$wp_query->comments_by_type = separate_comments($comments);
|
||||
@@ -1249,7 +1331,7 @@ function comments_template( $file = '/comments.php', $separate_comments = false
|
||||
}
|
||||
|
||||
$overridden_cpage = false;
|
||||
if ( '' == get_query_var('cpage') && get_option('page_comments') ) {
|
||||
if ( '' == get_query_var('cpage') ) {
|
||||
set_query_var( 'cpage', 'newest' == get_option('default_comments_page') ? get_comment_pages_count() : 1 );
|
||||
$overridden_cpage = true;
|
||||
}
|
||||
@@ -1825,9 +1907,14 @@ function wp_list_comments( $args = array(), $comments = null ) {
|
||||
} else {
|
||||
$_comments = $wp_query->comments;
|
||||
}
|
||||
|
||||
// Pagination is already handled by `WP_Comment_Query`, so we tell Walker not to bother.
|
||||
if ( 1 < $wp_query->max_num_comment_pages ) {
|
||||
$r['page'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( '' === $r['per_page'] && get_option('page_comments') )
|
||||
if ( '' === $r['per_page'] )
|
||||
$r['per_page'] = get_query_var('comments_per_page');
|
||||
|
||||
if ( empty($r['per_page']) ) {
|
||||
@@ -1866,7 +1953,6 @@ function wp_list_comments( $args = array(), $comments = null ) {
|
||||
}
|
||||
|
||||
$output = $walker->paged_walk( $_comments, $r['max_depth'], $r['page'], $r['per_page'], $r );
|
||||
$wp_query->max_num_comment_pages = $walker->max_pages;
|
||||
|
||||
$in_comment_loop = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user