Make WordPress Core

Ticket #45800: 45800.diff

File 45800.diff, 6.8 KB (added by felipeelia, 6 years ago)
  • src/wp-includes/class-wp-comment-query.php

     
    379379                        $this->meta_query_clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this );
    380380                }
    381381
    382                 /*
    383                  * Only use the args defined in the query_var_defaults to compute the key,
    384                  * but ignore 'fields', which does not affect query results.
     382                /**
     383                 * Filters the comments array before the query takes place.
     384                 *
     385                 * Return a non-null value to bypass WordPress's default comment queries.
     386                 *
     387                 * @since x.x.x
     388                 *
     389                 * @param array|int|null   $results Return null to allow WP to run its normal queries.
     390                 *                                  Otherwise, return an array of comment data,
     391                 *                                  an array of int if `fields=ids` or
     392                 *                                  an int if `count=true` to short-circuit WP's comment query.
     393                 * @param WP_Comment_Query  $this   The WP_Comment_Query instance (passed by reference).
    385394                 */
    386                 $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
    387                 unset( $_args['fields'] );
     395                $this->comments = apply_filters_ref_array( 'comments_pre_query', array( null, &$this ) );
    388396
    389                 $key          = md5( serialize( $_args ) );
    390                 $last_changed = wp_cache_get_last_changed( 'comment' );
     397                $comment_ids = array();
    391398
    392                 $cache_key   = "get_comments:$key:$last_changed";
    393                 $cache_value = wp_cache_get( $cache_key, 'comment' );
    394                 if ( false === $cache_value ) {
    395                         $comment_ids = $this->get_comment_ids();
    396                         if ( $comment_ids ) {
    397                                 $this->set_found_comments();
     399                if ( null === $this->comments ) {
     400                        // $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
     401                        $_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
     402
     403                        // Ignore the $fields argument as the queried result will be the same regardless.
     404                        unset( $_args['fields'] );
     405
     406                        $key          = md5( serialize( $_args ) );
     407                        $last_changed = wp_cache_get_last_changed( 'comment' );
     408
     409                        $cache_key   = "get_comments:$key:$last_changed";
     410                        $cache_value = wp_cache_get( $cache_key, 'comment' );
     411                        if ( false === $cache_value ) {
     412                                $comment_ids = $this->get_comment_ids();
     413                                if ( $comment_ids ) {
     414                                        $this->set_found_comments();
     415                                }
     416
     417                                $cache_value = array(
     418                                        'comment_ids'    => $comment_ids,
     419                                        'found_comments' => $this->found_comments,
     420                                );
     421                                wp_cache_add( $cache_key, $cache_value, 'comment' );
     422                        } else {
     423                                $comment_ids          = $cache_value['comment_ids'];
     424                                $this->found_comments = $cache_value['found_comments'];
    398425                        }
    399 
    400                         $cache_value = array(
    401                                 'comment_ids'    => $comment_ids,
    402                                 'found_comments' => $this->found_comments,
    403                         );
    404                         wp_cache_add( $cache_key, $cache_value, 'comment' );
    405                 } else {
    406                         $comment_ids          = $cache_value['comment_ids'];
    407                         $this->found_comments = $cache_value['found_comments'];
    408426                }
    409427
    410428                if ( $this->found_comments && $this->query_vars['number'] ) {
     
    413431
    414432                // If querying for a count only, there's nothing more to do.
    415433                if ( $this->query_vars['count'] ) {
    416                         // $comment_ids is actually a count in this case.
    417                         return intval( $comment_ids );
     434                        if ( null === $this->comments ) {
     435                                // $comment_ids is actually a count in this case.
     436                                return intval( $comment_ids );
     437                        }
     438                        // The comments_pre_query callback should be smart enough to test it and return the right result.
     439                        return intval( $this->comments );
    418440                }
    419441
    420442                $comment_ids = array_map( 'intval', $comment_ids );
    421443
    422444                if ( 'ids' == $this->query_vars['fields'] ) {
    423                         $this->comments = $comment_ids;
     445                        if ( null === $this->comments ) {
     446                                $this->comments = $comment_ids;
     447                        }
    424448                        return $this->comments;
    425449                }
    426450
    427                 _prime_comment_caches( $comment_ids, $this->query_vars['update_comment_meta_cache'] );
     451                if ( null === $this->comments ) {
     452                        _prime_comment_caches( $comment_ids, $this->query_vars['update_comment_meta_cache'] );
    428453
    429                 // Fetch full comment objects from the primed cache.
    430                 $_comments = array();
    431                 foreach ( $comment_ids as $comment_id ) {
    432                         if ( $_comment = get_comment( $comment_id ) ) {
    433                                 $_comments[] = $_comment;
     454                        // Fetch full comment objects from the primed cache.
     455                        $_comments = array();
     456                        foreach ( $comment_ids as $comment_id ) {
     457                                if ( $_comment = get_comment( $comment_id ) ) {
     458                                        $_comments[] = $_comment;
     459                                }
    434460                        }
    435                 }
    436461
    437                 // Prime comment post caches.
    438                 if ( $this->query_vars['update_comment_post_cache'] ) {
    439                         $comment_post_ids = array();
    440                         foreach ( $_comments as $_comment ) {
    441                                 $comment_post_ids[] = $_comment->comment_post_ID;
     462                        // Prime comment post caches.
     463                        if ( $this->query_vars['update_comment_post_cache'] ) {
     464                                $comment_post_ids = array();
     465                                foreach ( $_comments as $_comment ) {
     466                                        $comment_post_ids[] = $_comment->comment_post_ID;
     467                                }
     468
     469                                _prime_post_caches( $comment_post_ids, false, false );
    442470                        }
    443 
    444                         _prime_post_caches( $comment_post_ids, false, false );
     471                } else {
     472                        $_comments = $this->comments;
    445473                }
    446474
    447475                /**
     
    457485                // Convert to WP_Comment instances
    458486                $comments = array_map( 'get_comment', $_comments );
    459487
    460                 if ( $this->query_vars['hierarchical'] ) {
    461                         $comments = $this->fill_descendants( $comments );
     488                if ( null === $this->comments ) {
     489                        if ( $this->query_vars['hierarchical'] ) {
     490                                $comments = $this->fill_descendants( $comments );
     491                        }
    462492                }
    463493
    464494                $this->comments = $comments;
  • tests/phpunit/tests/comment/query.php

     
    48824882
    48834883                $this->assertEqualSets( $c1, $found );
    48844884        }
     4885
     4886        /**
     4887         * @ticket 45800
     4888         */
     4889        public function test_comments_pre_query_filter_should_bypass_database_query() {
     4890                global $wpdb;
     4891
     4892                add_filter( 'comments_pre_query', array( __CLASS__, 'filter_comments_pre_query' ), 10, 2 );
     4893
     4894                $num_queries = $wpdb->num_queries;
     4895                $q           = new WP_Comment_Query(
     4896                        array(
     4897                                'fields' => 'ids',
     4898                        )
     4899                );
     4900
     4901                remove_filter( 'comments_pre_query', array( __CLASS__, 'filter_comments_pre_query' ), 10, 2 );
     4902
     4903                // Make sure no queries were executed.
     4904                $this->assertSame( $num_queries, $wpdb->num_queries );
     4905
     4906                // We manually inserted a non-existing comment ID and overrode the results with it.
     4907                $this->assertSame( array( 555 ), $q->comments );
     4908
     4909                // Make sure manually setting found_comments doesn't get overwritten.
     4910                $this->assertEquals( 1, $q->found_comments );
     4911        }
     4912
     4913        public static function filter_comments_pre_query( $comments, $query ) {
     4914                $query->found_comments = 1;
     4915
     4916                return array( 555 );
     4917        }
    48854918}