Skip to content
Closed
4 changes: 4 additions & 0 deletions src/wp-includes/class-wp-metadata-lazyloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ public function __construct() {
'filter' => 'get_blog_metadata',
'callback' => array( $this, 'lazyload_meta_callback' ),
),
'user' => array(
'filter' => 'get_user_metadata',
'callback' => array( $this, 'lazyload_meta_callback' ),
),
);
}

Expand Down
3 changes: 2 additions & 1 deletion src/wp-includes/pluggable.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ function get_user_by( $field, $value ) {
function cache_users( $user_ids ) {
global $wpdb;

update_meta_cache( 'user', $user_ids );
$user_ids = array_unique( array_map( 'intval', $user_ids ), SORT_NUMERIC );
wp_lazyload_user_meta( $user_ids );

$clean = _get_non_cached_ids( $user_ids, 'users' );

Expand Down
15 changes: 15 additions & 0 deletions src/wp-includes/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,21 @@ function update_user_meta( $user_id, $meta_key, $meta_value, $prev_value = '' )
return update_metadata( 'user', $user_id, $meta_key, $meta_value, $prev_value );
}

/**
* Queue user meta for lazy-loading.
*
* @since 6.9.0
*
* @param int[] $user_ids List of user IDs.
*/
function wp_lazyload_user_meta( array $user_ids ) {
if ( empty( $user_ids ) ) {
return;
}
$lazyloader = wp_metadata_lazyloader();
$lazyloader->queue_objects( 'user', $user_ids );
}

/**
* Counts number of users who have each of the user roles.
*
Expand Down
1 change: 1 addition & 0 deletions tests/phpunit/includes/abstract-testcase.php
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ protected function reset_lazyload_queue() {
$lazyloader->reset_queue( 'term' );
$lazyloader->reset_queue( 'comment' );
$lazyloader->reset_queue( 'blog' );
$lazyloader->reset_queue( 'user' );
}

/**
Expand Down
22 changes: 22 additions & 0 deletions tests/phpunit/tests/post/updatePostAuthorCaches.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,28 @@ public function test_update_post_author_caches() {
$q->the_post();
}

$this->assertSame( 0, $action->get_call_count(), 'Ensure that user meta are not primed' );
}

/**
* @ticket 63021
*/
public function test_update_post_author_caches_force_load_meta() {
$action = new MockAction();
add_filter( 'update_user_metadata_cache', array( $action, 'filter' ), 10, 2 );

$q = new WP_Query(
array(
'post_type' => 'post',
'posts_per_page' => self::$post_author_count,
)
);

while ( $q->have_posts() ) {
$q->the_post();
get_the_author_meta(); // Force loading of author meta.
}

$args = $action->get_args();
$last_args = end( $args );

Expand Down
7 changes: 3 additions & 4 deletions tests/phpunit/tests/query/cacheResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -1982,11 +1982,10 @@ public function test_author_cache_warmed_by_the_loop( $fields ) {
$query_1->the_post();
$num_loop_queries = get_num_queries() - $start_loop_queries;
/*
* Two expected queries:
* 1: User meta data,
* 2: User data.
* One expected query:
* 1: User data.
*/
$this->assertSame( 2, $num_loop_queries, 'Unexpected number of queries while initializing the loop.' );
$this->assertSame( 1, $num_loop_queries, 'Unexpected number of queries while initializing the loop.' );

$start_author_queries = get_num_queries();
get_user_by( 'ID', self::$author_id );
Expand Down
8 changes: 4 additions & 4 deletions tests/phpunit/tests/query/thePost.php
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,10 @@ public function test_the_loop_primes_the_author_cache( $fields, $expected_querie
*/
public function data_the_loop_fields() {
return array(
'all fields' => array( 'all', 2 ),
'all fields (empty fields)' => array( '', 2 ),
'post IDs' => array( 'ids', 4 ),
'post ids and parent' => array( 'id=>parent', 4 ),
'all fields' => array( 'all', 1 ),
'all fields (empty fields)' => array( '', 1 ),
'post IDs' => array( 'ids', 3 ),
'post ids and parent' => array( 'id=>parent', 3 ),
);
}

Expand Down
70 changes: 70 additions & 0 deletions tests/phpunit/tests/user/lazyLoadMeta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

/**
* @group user
* @covers ::wp_lazyload_user_meta
*/
class Tests_User_Lazy_Load_Meta extends WP_UnitTestCase {

/**
* @ticket 63021
*/
public function test_lazy_load_meta() {
$user_ids = self::factory()->user->create_many( 3 );
// Clear any existing cache.
wp_cache_delete_multiple( $user_ids, 'user_meta' );
wp_lazyload_user_meta( $user_ids );
$filter = new MockAction();
add_filter( 'update_user_metadata_cache', array( $filter, 'filter' ), 10, 2 );
get_user_meta( $user_ids[0] );

$args = $filter->get_args();
$first = reset( $args );
$load_user_ids = end( $first );
$this->assertSameSets( $user_ids, $load_user_ids, 'Ensure all user IDs are loaded in a single batch' );
}

/**
* @ticket 63021
*/
public function test_lazy_load_meta_sets() {
$user_ids1 = self::factory()->user->create_many( 3 );
$user_ids2 = self::factory()->user->create_many( 3 );
$user_ids = array_merge( $user_ids1, $user_ids2 );
// Clear any existing cache.
wp_cache_delete_multiple( $user_ids, 'user_meta' );
wp_lazyload_user_meta( $user_ids );
$filter = new MockAction();
add_filter( 'update_user_metadata_cache', array( $filter, 'filter' ), 10, 2 );
get_user_meta( $user_ids[0] );

$args = $filter->get_args();
$first = reset( $args );
$load_user_ids = end( $first );
$this->assertSameSets( $user_ids, $load_user_ids, 'Ensure all user IDs are loaded in a single batch' );
}

/**
* @ticket 63021
*/
public function test_lazy_load_meta_not_in_queue() {
$user_ids1 = self::factory()->user->create_many( 3 );
$user_ids2 = self::factory()->user->create_many( 3 );
$user_ids = array_merge( $user_ids1, $user_ids2 );
$new_user_id = self::factory()->user->create();
wp_lazyload_user_meta( $user_ids );
// Add a user not in the lazy load queue.
$user_ids[] = $new_user_id;
// Clear any existing cache including the new user not in the queue.
wp_cache_delete_multiple( $user_ids, 'user_meta' );

$filter = new MockAction();
add_filter( 'update_user_metadata_cache', array( $filter, 'filter' ), 10, 2 );
get_user_meta( $new_user_id );

$args = $filter->get_args();
$first = reset( $args );
$load_user_ids = end( $first );
$this->assertSameSets( $user_ids, $load_user_ids, 'Ensure all user IDs are loaded, including the one not in the queue' );
}
}
Loading