From 4ba54c210415341065d1b95f0a7e694aee9694ab Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 10 Sep 2019 18:41:03 +0000 Subject: [PATCH] Comments: add a new `comments_pre_query` filter to short circuit WP_Comment_Query 'get_comments' queries. Return a non-null value to bypass WordPress's default comment queries. Props felipeelia, spacedmonkey. Fixes #45800. git-svn-id: https://develop.svn.wordpress.org/trunk@46086 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-comment-query.php | 24 +++++++++++++++++ tests/phpunit/tests/comment/query.php | 31 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/wp-includes/class-wp-comment-query.php b/src/wp-includes/class-wp-comment-query.php index eba9ddf54e..28ac6082e3 100644 --- a/src/wp-includes/class-wp-comment-query.php +++ b/src/wp-includes/class-wp-comment-query.php @@ -379,6 +379,30 @@ class WP_Comment_Query { $this->meta_query_clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this ); } + $comment_data = null; + + /** + * Filter the comments data before the query takes place. + * + * Return a non-null value to bypass WordPress's default comment queries. + * + * The expected return type from this filter depends on the value passed in the request query_vars: + * When $this->query_vars['count'] is set, the filter should return the comment count as an int. + * When `'ids' == $this->query_vars['fields']`, the filter should return an array of comment ids. + * Otherwise the filter should return an array of WP_Comment objects. + * + * @since 5.3.0 + * + * @param array|int|null $comment_data Return an array of comment data to short-circuit WP's comment query, + * or null to allow WP to run its normal queries. + * @param WP_Comment_Query $this The WP_Comment_Query instance, passed by reference. + */ + $comment_data = apply_filters_ref_array( 'comments_pre_query', array( $comment_data, &$this ) ); + + if ( null !== $comment_data ) { + return $comment_data; + } + /* * Only use the args defined in the query_var_defaults to compute the key, * but ignore 'fields', which does not affect query results. diff --git a/tests/phpunit/tests/comment/query.php b/tests/phpunit/tests/comment/query.php index 9966f2d1bd..372fa475c4 100644 --- a/tests/phpunit/tests/comment/query.php +++ b/tests/phpunit/tests/comment/query.php @@ -4882,4 +4882,35 @@ class Tests_Comment_Query extends WP_UnitTestCase { $this->assertEqualSets( $c1, $found ); } + + /** + * @ticket 45800 + */ + public function test_comments_pre_query_filter_should_bypass_database_query() { + global $wpdb; + + add_filter( 'comments_pre_query', array( __CLASS__, 'filter_comments_pre_query' ), 10, 2 ); + + $num_queries = $wpdb->num_queries; + + $q = new WP_Comment_Query(); + $results = $q->query( array() ); + + remove_filter( 'comments_pre_query', array( __CLASS__, 'filter_comments_pre_query' ), 10, 2 ); + + // Make sure no queries were executed. + $this->assertSame( $num_queries, $wpdb->num_queries ); + + // We manually inserted a non-existing site and overrode the results with it. + $this->assertSame( array( 555 ), $results ); + + // Make sure manually setting total_users doesn't get overwritten. + $this->assertEquals( 1, $q->found_comments ); + } + + public static function filter_comments_pre_query( $comments, $query ) { + $query->found_comments = 1; + + return array( 555 ); + } }