WordPress.org

Make WordPress Core

Ticket #11334: 11334.4.diff

File 11334.4.diff, 10.7 KB (added by boonebgorges, 5 years ago)
  • src/wp-includes/comment.php

    diff --git src/wp-includes/comment.php src/wp-includes/comment.php
    index f0c71af..8515210 100644
    function get_comment_pages_count( $comments = null, $per_page = null, $threaded 
    14581458 *
    14591459 * @since 2.7.0
    14601460 *
    1461  * @param int $comment_ID Comment ID.
    1462  * @param array $args Optional args.
     1461 * @param int   $comment_ID Comment ID.
     1462 * @param array $args {
     1463 *      Array of optional arguments.
     1464 *      @type string     $type      Limit pagination to comments matching a given type. Accepts 'comment', 'trackback',
     1465 *                                  'pingback', 'pings' (trackbacks and pingbacks), or 'all'. Default is 'all'.
     1466 *      @type int        $per_page  Per-page count to use when calculating pagination. Defaults to the value of the
     1467 *                                  'comments_per_page' option.
     1468 *      @type int|string $max_depth If greater than 1, comment page will be determined for the top-level parent of
     1469 *                                  `$comment_ID`. Defaults to the value of the 'thread_comments_depth' option.
     1470 * }
    14631471 * @return int|null Comment page number or null on error.
    14641472 */
    14651473function get_page_of_comment( $comment_ID, $args = array() ) {
    function get_page_of_comment( $comment_ID, $args = array() ) { 
    14911499        if ( $args['max_depth'] > 1 && 0 != $comment->comment_parent )
    14921500                return get_page_of_comment( $comment->comment_parent, $args );
    14931501
    1494         $allowedtypes = array(
    1495                 'comment' => '',
    1496                 'pingback' => 'pingback',
    1497                 'trackback' => 'trackback',
    1498         );
     1502        $older_comment_counts = wp_cache_get( $comment_ID, 'comment_pages' );
     1503
     1504        if ( ! is_array( $older_comment_counts ) ) {
     1505                $older_comment_counts = array();
     1506        }
     1507
     1508        $comment_type = $args['type'];
     1509        if ( isset( $older_comment_counts[ $comment_type ] ) ) {
     1510                $older_comment_count = (int) $older_comment_counts[ $comment_type ];
     1511        } else {
     1512                switch ( $comment_type ) {
     1513                        case 'comment' :
     1514                                $comment_type_where = " AND comment_type = 'comment'";
     1515                                break;
     1516
     1517                        case 'pingback' :
     1518                                $comment_type_where = " AND comment_type = 'pingback'";
     1519                                break;
     1520
     1521                        case 'trackback' :
     1522                                $comment_type_where = " AND comment_type = 'trackback'";
     1523                                break;
     1524
     1525                        case 'pings' :
     1526                                $comment_type_where = " AND comment_type IN ( 'pingback', 'trackback' )";
     1527                                break;
     1528
     1529                        case 'all' :
     1530                        default :
     1531                                $comment_type_where = '';
     1532                                break;
     1533                }
    14991534
    1500         $comtypewhere = ( 'all' != $args['type'] && isset($allowedtypes[$args['type']]) ) ? " AND comment_type = '" . $allowedtypes[$args['type']] . "'" : '';
     1535                // Count comments older than this one.
     1536                $older_comment_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = 0 AND comment_approved = '1' AND comment_date_gmt < '%s'" . $comment_type_where, $comment->comment_post_ID, $comment->comment_date_gmt ) );
    15011537
    1502         // Count comments older than this one
    1503         $oldercoms = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = 0 AND comment_approved = '1' AND comment_date_gmt < '%s'" . $comtypewhere, $comment->comment_post_ID, $comment->comment_date_gmt ) );
     1538                $older_comment_counts[ $comment_type ] = (int) $older_comment_count;
     1539                wp_cache_add( $comment_ID, $older_comment_counts, 'comment_pages' );
     1540        }
    15041541
    15051542        // No older comments? Then it's page #1.
    1506         if ( 0 == $oldercoms )
     1543        if ( 0 == $older_comment_count ) {
    15071544                return 1;
     1545        }
    15081546
    15091547        // Divide comments older than this one by comments per page to get this comment's page number
    1510         return ceil( ( $oldercoms + 1 ) / $args['per_page'] );
     1548        return intval( ceil( ( $older_comment_count + 1 ) / $args['per_page'] ) );
    15111549}
    15121550
    15131551/**
    function update_comment_cache($comments) { 
    29162954                wp_cache_add($comment->comment_ID, $comment, 'comment');
    29172955}
    29182956
     2957/**
     2958 * Clears the cache used by `get_page_of_comment()`.
     2959 *
     2960 * Changes in comment status can affect pagination for all other comments on the post, so we clear caches for all
     2961 * of the post's comments.
     2962 *
     2963 * @since 4.2.0
     2964 *
     2965 * @param string $new_status New comment status.
     2966 * @param string $old_status Old comment status.
     2967 * @param object $comment    Comment object.
     2968 */
     2969function wp_clean_page_of_comment_cache( $new_status, $old_status, $comment ) {
     2970        $post_comments = get_comments( array(
     2971                'fields' => 'ids',
     2972                'status' => 'all',
     2973                'post_id' => $comment->comment_post_ID,
     2974        ) );
     2975
     2976        // If a comment has just been deleted, it won't show up in the query.
     2977        if ( ! in_array( $comment->comment_ID, $post_comments ) ) {
     2978                $post_comments[] = $comment->comment_ID;
     2979        }
     2980
     2981        foreach ( $post_comments as $post_comment ) {
     2982                wp_cache_delete( $post_comment, 'comment_pages' );
     2983        }
     2984}
     2985
    29192986//
    29202987// Internal
    29212988//
  • src/wp-includes/default-filters.php

    diff --git src/wp-includes/default-filters.php src/wp-includes/default-filters.php
    index c28594f..f293846 100644
    add_action( 'post_updated', 'wp_save_post_revision', 
    255255add_action( 'publish_post',               '_publish_post_hook',                       5, 1 );
    256256add_action( 'transition_post_status',     '_transition_post_status',                  5, 3 );
    257257add_action( 'transition_post_status',     '_update_term_count_on_transition_post_status', 10, 3 );
     258add_action( 'transition_comment_status',  'wp_clean_page_of_comment_cache',          10, 3 );
    258259add_action( 'comment_form',               'wp_comment_form_unfiltered_html_nonce'          );
    259260add_action( 'wp_scheduled_delete',        'wp_scheduled_delete'                            );
    260261add_action( 'wp_scheduled_auto_draft_delete', 'wp_delete_auto_drafts'                      );
  • tests/phpunit/tests/comment/getPageOfComment.php

    diff --git tests/phpunit/tests/comment/getPageOfComment.php tests/phpunit/tests/comment/getPageOfComment.php
    index 5e03a16..09ab649 100644
    class Tests_Comment_GetPageOfComment extends WP_UnitTestCase { 
    3838                $this->assertEquals( 1, get_page_of_comment( $comment_first[0], array( 'per_page' =>  3 ) ) );
    3939                $this->assertEquals( 1, get_page_of_comment( $comment_first[0], array( 'per_page' => 10 ) ) );
    4040        }
     41
     42        public function test_type_pings() {
     43                $p = $this->factory->post->create();
     44                $now = time();
     45
     46                $trackbacks = array();
     47                for ( $i = 0; $i <= 3; $i++ ) {
     48                        $trackbacks[ $i ] = $this->factory->comment->create( array( 'comment_post_ID' => $p, 'comment_type' => 'trackback', 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now ) ) );
     49                        $now -= 10 * $i;
     50                }
     51
     52                $pingbacks = array();
     53                for ( $i = 0; $i <= 6; $i++ ) {
     54                        $pingbacks[ $i ] = $this->factory->comment->create( array( 'comment_post_ID' => $p, 'comment_type' => 'pingback', 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now ) ) );
     55                        $now -= 10 * $i;
     56                }
     57
     58                $this->assertEquals( 2, get_page_of_comment( $trackbacks[0], array( 'per_page' => 2, 'type' => 'trackback' ) ) );
     59                $this->assertEquals( 3, get_page_of_comment( $pingbacks[0], array( 'per_page' => 2, 'type' => 'pingback' ) ) );
     60                $this->assertEquals( 5, get_page_of_comment( $trackbacks[0], array( 'per_page' => 2, 'type' => 'pings' ) ) );
     61        }
     62
     63        /**
     64         * @ticket 11334
     65         */
     66        public function test_subsequent_calls_should_hit_cache() {
     67                global $wpdb;
     68
     69                $p = $this->factory->post->create();
     70                $c = $this->factory->comment->create( array( 'comment_post_ID' => $p ) );
     71
     72                // Prime cache.
     73                $page_1 = get_page_of_comment( $c, array( 'per_page' => 3 ) );
     74
     75                $num_queries = $wpdb->num_queries;
     76                $page_2 = get_page_of_comment( $c, array( 'per_page' => 3 ) );
     77
     78                $this->assertSame( $page_1, $page_2 );
     79                $this->assertSame( $num_queries, $wpdb->num_queries );
     80        }
     81
     82        /**
     83         * @ticket 11334
     84         */
     85        public function test_cache_hits_should_be_sensitive_to_comment_type() {
     86                global $wpdb;
     87
     88                $p = $this->factory->post->create();
     89                $comment = $this->factory->comment->create( array( 'comment_post_ID' => $p, 'comment_type' => 'comment' ) );
     90
     91                $now = time();
     92                $trackbacks = array();
     93                for ( $i = 0; $i <= 5; $i++ ) {
     94                        $trackbacks[ $i ] = $this->factory->comment->create( array( 'comment_post_ID' => $p, 'comment_type' => 'trackback', 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - ( 10 * $i ) ) ) );
     95                }
     96
     97                // Prime cache for trackbacks.
     98                $page_trackbacks = get_page_of_comment( $trackbacks[1], array( 'per_page' => 3, 'type' => 'trackback' ) );
     99                $this->assertEquals( 2, $page_trackbacks );
     100
     101                $num_queries = $wpdb->num_queries;
     102                $page_comments = get_page_of_comment( $comment, array( 'per_page' => 3, 'type' => 'comment' ) );
     103                $this->assertEquals( 1, $page_comments );
     104
     105                $this->assertNotEquals( $num_queries, $wpdb->num_queries );
     106        }
     107
     108        /**
     109         * @ticket 11334
     110         */
     111        public function test_cache_should_be_invalidated_when_comment_is_approved() {
     112                $p = $this->factory->post->create();
     113                $c = $this->factory->comment->create( array( 'comment_post_ID' => $p, 'comment_approved' => 0 ) );
     114
     115                // Prime cache.
     116                $page_1 = get_page_of_comment( $c, array( 'per_page' => 3 ) );
     117
     118                // Approve comment.
     119                wp_set_comment_status( $c, 'approve' );
     120
     121                $this->assertFalse( wp_cache_get( $c, 'comment_pages' ) );
     122        }
     123
     124        /**
     125         * @ticket 11334
     126         */
     127        public function test_cache_should_be_invalidated_when_comment_is_deleted() {
     128                $p = $this->factory->post->create();
     129                $c = $this->factory->comment->create( array( 'comment_post_ID' => $p ) );
     130
     131                // Prime cache.
     132                $page_1 = get_page_of_comment( $c, array( 'per_page' => 3 ) );
     133
     134                // Trash comment.
     135                wp_trash_comment( $c );
     136
     137                $this->assertFalse( wp_cache_get( $c, 'comment_pages' ) );
     138        }
     139
     140        /**
     141         * @ticket 11334
     142         */
     143        public function test_cache_should_be_invalidated_when_comment_is_spammed() {
     144                $p = $this->factory->post->create();
     145                $c = $this->factory->comment->create( array( 'comment_post_ID' => $p ) );
     146
     147                // Prime cache.
     148                $page_1 = get_page_of_comment( $c, array( 'per_page' => 3 ) );
     149
     150                // Spam comment.
     151                wp_spam_comment( $c );
     152
     153                $this->assertFalse( wp_cache_get( $c, 'comment_pages' ) );
     154        }
     155
     156        /**
     157         * @ticket 11334
     158         */
     159        public function test_cache_should_be_invalidated_when_older_comment_is_published() {
     160                $now = time();
     161
     162                $p = $this->factory->post->create();
     163                $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $p, 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now ) ) );
     164                $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $p, 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 20 ) ) );
     165                $c3 = $this->factory->comment->create( array( 'comment_post_ID' => $p, 'comment_approved' => 0, 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 30 ) ) );
     166
     167                $this->assertEquals( 1, get_page_of_comment( $c1, array( 'per_page' => 2 ) ) );
     168
     169                wp_set_comment_status( $c3, '1' );
     170
     171                $this->assertEquals( 2, get_page_of_comment( $c1, array( 'per_page' => 2 ) ) );
     172        }
    41173}