Make WordPress Core


Ignore:
Timestamp:
02/12/2025 09:48:04 PM (19 months ago)
Author:
spacedmonkey
Message:

Users: Add caching to count_user_posts function

Introduced caching for the count_user_posts function to reduce redundant database queries. This ensures better performance by storing and reusing query results when possible. Additionally, sanitized and sorted the $post_type array to avoid invalid queries.

Props spacedmonkey, peterwilsoncc, mamaduka, flixos90, johnjamesjacoby, swissspidy, dilip2615, johnregan3, wpgurudev, desrosj, milindmore22, Krstarica, dilipom13.
Fixes #39242.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/user/countUserPosts.php

    r54402 r59817  
    9090                $this->assertSame( '4', count_user_posts( self::$user_id, array( 'foo', 'post' ) ) );
    9191        }
     92
     93        /**
     94         * Post count be correct after reassigning posts to another user.
     95         *
     96         * @ticket 39242
     97         */
     98        public function test_reassigning_users_posts_modifies_count() {
     99                // Create new user.
     100                $new_user_id = self::factory()->user->create(
     101                        array(
     102                                'role' => 'author',
     103                        )
     104                );
     105
     106                // Prior to reassigning posts.
     107                $this->assertSame( '4', count_user_posts( self::$user_id ), 'Original user is expected to have a count of four posts prior to reassignment.' );
     108                $this->assertSame( '0', count_user_posts( $new_user_id ), 'New user is expected to have a count of zero posts prior to reassignment.' );
     109
     110                // Delete the original user, reassigning their posts to the new user.
     111                wp_delete_user( self::$user_id, $new_user_id );
     112
     113                // After reassigning posts.
     114                $this->assertSame( '0', count_user_posts( self::$user_id ), 'Original user is expected to have a count of zero posts following reassignment.' );
     115                $this->assertSame( '4', count_user_posts( $new_user_id ), 'New user is expected to have a count of four posts following reassignment.' );
     116        }
     117
     118        /**
     119         * Post count be correct after deleting user without reassigning posts.
     120         *
     121         * @ticket 39242
     122         */
     123        public function test_post_count_retained_after_deleting_user_without_reassigning_posts() {
     124                $this->assertSame( '4', count_user_posts( self::$user_id ), 'User is expected to have a count of four posts prior to deletion.' );
     125
     126                // Delete the original user without reassigning their posts.
     127                wp_delete_user( self::$user_id );
     128
     129                $this->assertSame( '0', count_user_posts( self::$user_id ), 'User is expected to have a count of zero posts following deletion.' );
     130        }
     131
     132        /**
     133         * Post count should work for users that don't exist but have posts assigned.
     134         *
     135         * @ticket 39242
     136         */
     137        public function test_count_user_posts_for_non_existent_user() {
     138                $next_user_id = self::$user_id + 1;
     139
     140                // Assign post to next user.
     141                self::factory()->post->create(
     142                        array(
     143                                'post_author' => $next_user_id,
     144                                'post_type'   => 'post',
     145                        )
     146                );
     147
     148                $next_user_post_count = count_user_posts( $next_user_id );
     149                $this->assertSame( '1', $next_user_post_count, 'Non-existent user is expected to have count of one post.' );
     150        }
     151
     152        /**
     153         * Cached user count value should be accurate after user is created.
     154         *
     155         * @ticket 39242
     156         */
     157        public function test_count_user_posts_for_user_created_after_being_assigned_posts() {
     158                global $wpdb;
     159                $next_user_id = (int) $wpdb->get_var( "SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '$wpdb->users'" );
     160
     161                // Assign post to next user.
     162                self::factory()->post->create(
     163                        array(
     164                                'post_author' => $next_user_id,
     165                                'post_type'   => 'post',
     166                        )
     167                );
     168
     169                // Cache the user count.
     170                count_user_posts( $next_user_id );
     171
     172                // Create user.
     173                $real_next_user_id = self::factory()->user->create(
     174                        array(
     175                                'role' => 'author',
     176                        )
     177                );
     178
     179                $this->assertSame( $next_user_id, $real_next_user_id, 'User ID should match calculated value' );
     180                $this->assertSame( '1', count_user_posts( $next_user_id ), 'User is expected to have count of one post.' );
     181        }
     182
     183        /**
     184         * User count cache should be hit regardless of post type order.
     185         *
     186         * @ticket 39242
     187         */
     188        public function test_cache_should_be_hit_regardless_of_post_type_order() {
     189                // Prime Cache.
     190                count_user_posts( self::$user_id, array( 'wptests_pt', 'post' ) );
     191
     192                $query_num_start = get_num_queries();
     193                count_user_posts( self::$user_id, array( 'post', 'wptests_pt' ) );
     194                $total_queries = get_num_queries() - $query_num_start;
     195
     196                $this->assertSame( 0, $total_queries, 'Cache should be hit regardless of post type order.' );
     197        }
     198
     199        /**
     200         * User count cache should be hit for string and array of post types.
     201         *
     202         * @ticket 39242
     203         */
     204        public function test_cache_should_be_hit_for_string_and_array_equivalent_queries() {
     205                // Prime Cache.
     206                count_user_posts( self::$user_id, 'post' );
     207
     208                $query_num_start = get_num_queries();
     209                count_user_posts( self::$user_id, array( 'post' ) );
     210                $total_queries = get_num_queries() - $query_num_start;
     211
     212                $this->assertSame( 0, $total_queries, 'Cache should be hit for string and array equivalent post types.' );
     213        }
     214
     215        /**
     216         * User count cache should be hit for array duplicates and equivalent queries.
     217         *
     218         * @ticket 39242
     219        */
     220        public function test_cache_should_be_hit_for_and_array_duplicates_equivalent_queries() {
     221                // Prime Cache
     222                count_user_posts( self::$user_id, array( 'post', 'post', 'post' ) );
     223
     224                $query_num_start = get_num_queries();
     225                count_user_posts( self::$user_id, array( 'post' ) );
     226                $total_queries = get_num_queries() - $query_num_start;
     227
     228                $this->assertSame( 0, $total_queries, 'Cache is expected to be hit for equivalent queries with duplicate post types' );
     229        }
    92230}
Note: See TracChangeset for help on using the changeset viewer.