diff --git a/src/wp-includes/class-wp-user-query.php b/src/wp-includes/class-wp-user-query.php index 61fc3edbc8ef9..1ba30079a8561 100644 --- a/src/wp-includes/class-wp-user-query.php +++ b/src/wp-includes/class-wp-user-query.php @@ -1056,9 +1056,15 @@ protected function generate_cache_key( array $deprecated, $sql ) { // Replace wpdb placeholder in the SQL statement used by the cache key. $sql = $wpdb->remove_placeholder_escape( $sql ); + /* + * An array of fields is fetched as objects, anything else as a list of values. + * The SQL can be identical for both, so keep them in separate cache entries. + */ + $format = is_array( $this->query_vars['fields'] ) ? 'objects' : 'values'; + $key = md5( $sql ); - return "get_users:$key"; + return "get_users:$format:$key"; } /** diff --git a/tests/phpunit/tests/user/queryCache.php b/tests/phpunit/tests/user/queryCache.php index fb556bfa36b21..4738e704e3283 100644 --- a/tests/phpunit/tests/user/queryCache.php +++ b/tests/phpunit/tests/user/queryCache.php @@ -802,4 +802,59 @@ public function test_generate_cache_key_with_orderby_post_count_and_deprecated_w $this->assertNotEmpty( $query->get_results() ); } + + /** + * Tests that queries with the same SQL but a different `fields` format do not share a cache entry. + * + * @ticket 62003 + * + * @covers ::generate_cache_key + * + * @dataProvider data_query_cache_should_respect_fields_return_format + * + * @param string|string[] $first_fields The `fields` value used to prime the cache. + * @param string|string[] $second_fields The `fields` value read from the cache. + */ + public function test_query_cache_should_respect_fields_return_format( $first_fields, $second_fields ) { + new WP_User_Query( array( 'fields' => $first_fields ) ); + + $cached = new WP_User_Query( array( 'fields' => $second_fields ) ); + $uncached = new WP_User_Query( + array( + 'fields' => $second_fields, + 'cache_results' => false, + ) + ); + + $get_format = static function ( $result ) { + return is_object( $result ) ? get_class( $result ) : gettype( $result ); + }; + + $this->assertSame( + array_map( $get_format, $uncached->get_results() ), + array_map( $get_format, $cached->get_results() ), + 'Cached results should have the same format as uncached results.' + ); + $this->assertEquals( + $uncached->get_results(), + $cached->get_results(), + 'Cached results should match uncached results.' + ); + } + + /** + * Data provider. + * + * @return array[] + */ + public function data_query_cache_should_respect_fields_return_format() { + return array( + 'string then array' => array( 'ID', array( 'ID' ) ), + 'array then string' => array( array( 'ID' ), 'ID' ), + 'array then all' => array( array( 'ID' ), 'all' ), + 'all then array' => array( 'all', array( 'ID' ) ), + 'array then all_with_meta' => array( array( 'ID' ), 'all_with_meta' ), + 'array then string field' => array( array( 'user_email' ), 'user_email' ), + ); + } }