From 1d0c189f214183538054e647fddfc63b24500079 Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Thu, 31 Mar 2022 09:07:02 +0000 Subject: [PATCH] Comments: Improve performance of the `wp_count_comments` function. Improve performance of the `wp_count_comments` function by replacing a complex query with multiple calls to the `get_comments` function. Passing the `count` parameter to the `get_comments` function results in a simple count query that returns quickly. Using `get_comments` also means that query is cached and run through filters. Props FolioVision, markjaquith, nacin, ryan, coffee2code, wonderboymusic, ComputerGuru, jb510, SergeyBiryukov, Znuff, Rahe, uday17035, spacedmonkey, peterwilsoncc. Fixes #19901. git-svn-id: https://develop.svn.wordpress.org/trunk@53036 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/comment.php | 60 ++++++---------- .../phpunit/tests/comment/getCommentCount.php | 70 +++++++++++++++++++ 2 files changed, 90 insertions(+), 40 deletions(-) diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 6d83b762b7..50e0082283 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -383,21 +383,6 @@ function get_comment_count( $post_id = 0 ) { $post_id = (int) $post_id; - $where = ''; - if ( $post_id > 0 ) { - $where = $wpdb->prepare( 'WHERE comment_post_ID = %d', $post_id ); - } - - $totals = (array) $wpdb->get_results( - " - SELECT comment_approved, COUNT( * ) AS total - FROM {$wpdb->comments} - {$where} - GROUP BY comment_approved - ", - ARRAY_A - ); - $comment_count = array( 'approved' => 0, 'awaiting_moderation' => 0, @@ -408,32 +393,27 @@ function get_comment_count( $post_id = 0 ) { 'all' => 0, ); - foreach ( $totals as $row ) { - switch ( $row['comment_approved'] ) { - case 'trash': - $comment_count['trash'] = $row['total']; - break; - case 'post-trashed': - $comment_count['post-trashed'] = $row['total']; - break; - case 'spam': - $comment_count['spam'] = $row['total']; - $comment_count['total_comments'] += $row['total']; - break; - case '1': - $comment_count['approved'] = $row['total']; - $comment_count['total_comments'] += $row['total']; - $comment_count['all'] += $row['total']; - break; - case '0': - $comment_count['awaiting_moderation'] = $row['total']; - $comment_count['total_comments'] += $row['total']; - $comment_count['all'] += $row['total']; - break; - default: - break; - } + $args = array( + 'count' => true, + 'update_comment_meta_cache' => false, + ); + if ( $post_id > 0 ) { + $args['post_id'] = $post_id; } + $mapping = array( + 'approved' => 'approve', + 'awaiting_moderation' => 'hold', + 'spam' => 'spam', + 'trash' => 'trash', + 'post-trashed' => 'post-trashed', + ); + $comment_count = array(); + foreach ( $mapping as $key => $value ) { + $comment_count[ $key ] = get_comments( array_merge( $args, array( 'status' => $value ) ) ); + } + + $comment_count['all'] = $comment_count['approved'] + $comment_count['awaiting_moderation']; + $comment_count['total_comments'] = $comment_count['all'] + $comment_count['spam']; return array_map( 'intval', $comment_count ); } diff --git a/tests/phpunit/tests/comment/getCommentCount.php b/tests/phpunit/tests/comment/getCommentCount.php index 7b3ede5f35..7fe6b2aa31 100644 --- a/tests/phpunit/tests/comment/getCommentCount.php +++ b/tests/phpunit/tests/comment/getCommentCount.php @@ -11,6 +11,7 @@ class Tests_Get_Comment_Count extends WP_UnitTestCase { $this->assertSame( 0, $count['trash'] ); $this->assertSame( 0, $count['post-trashed'] ); $this->assertSame( 0, $count['total_comments'] ); + $this->assertSame( 0, $count['all'] ); } public function test_get_comment_count_approved() { @@ -97,4 +98,73 @@ class Tests_Get_Comment_Count extends WP_UnitTestCase { $this->assertSame( 1, $count['post-trashed'] ); $this->assertSame( 0, $count['total_comments'] ); } + + /** + * @ticket 19901 + * + * @covers ::get_comment_count + */ + public function test_get_comment_count_validate_cache_comment_deleted() { + + $comment_id = self::factory()->comment->create(); + + $count = get_comment_count(); + + $this->assertSame( 1, $count['total_comments'] ); + + wp_delete_comment( $comment_id, true ); + + $count = get_comment_count(); + + $this->assertSame( 0, $count['total_comments'] ); + } + + /** + * @ticket 19901 + * + * @covers ::get_comment_count + */ + public function test_get_comment_count_validate_cache_post_deleted() { + + $post_id = self::factory()->post->create(); + + $comment_id = self::factory()->comment->create( + array( + 'comment_post_ID' => $post_id, + ) + ); + + $count = get_comment_count( $post_id ); + + $this->assertSame( 1, $count['total_comments'] ); + + wp_delete_post( $post_id, true ); + + $count = get_comment_count( $post_id ); + + $this->assertSame( 0, $count['total_comments'] ); + } + + /** + * @ticket 19901 + * + * @covers ::get_comment_count + */ + public function test_get_comment_count_validate_cache_comment_status() { + $comment_id = self::factory()->comment->create(); + + $count = get_comment_count(); + + $this->assertSame( 1, $count['approved'] ); + $this->assertSame( 0, $count['trash'] ); + $this->assertSame( 1, $count['total_comments'] ); + + wp_set_comment_status( $comment_id, 'trash' ); + + $count = get_comment_count(); + + $this->assertSame( 0, $count['approved'] ); + $this->assertSame( 1, $count['trash'] ); + $this->assertSame( 0, $count['total_comments'] ); + } }