diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index e79f460fc5..a9ed269d72 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -3192,12 +3192,17 @@ class WP_Query { } elseif ( 'id=>parent' === $q['fields'] ) { _prime_post_parent_id_caches( $post_ids ); - /** @var int[] */ - $post_parents = wp_cache_get_multiple( $post_ids, 'post_parent' ); + $post_parent_cache_keys = array(); + foreach ( $post_ids as $post_id ) { + $post_parent_cache_keys[] = 'post_parent:' . (string) $post_id; + } - foreach ( $post_parents as $id => $post_parent ) { + /** @var int[] */ + $post_parents = wp_cache_get_multiple( $post_parent_cache_keys, 'posts' ); + + foreach ( $post_parents as $cache_key => $post_parent ) { $obj = new stdClass(); - $obj->ID = (int) $id; + $obj->ID = (int) str_replace( 'post_parent:', '', $cache_key ); $obj->post_parent = (int) $post_parent; $this->posts[] = $obj; @@ -3245,8 +3250,9 @@ class WP_Query { $this->set_found_posts( $q, $limits ); /** @var int[] */ - $post_parents = array(); - $post_ids = array(); + $post_parents = array(); + $post_ids = array(); + $post_parents_cache = array(); foreach ( $this->posts as $key => $post ) { $this->posts[ $key ]->ID = (int) $post->ID; @@ -3254,9 +3260,11 @@ class WP_Query { $post_parents[ (int) $post->ID ] = (int) $post->post_parent; $post_ids[] = (int) $post->ID; + + $post_parents_cache[ 'post_parent:' . (string) $post->ID ] = (int) $post->post_parent; } // Prime post parent caches, so that on second run, there is not another database query. - wp_cache_add_multiple( $post_parents, 'post_parent' ); + wp_cache_add_multiple( $post_parents_cache, 'posts' ); if ( $q['cache_results'] && $id_query_is_cacheable ) { $cache_value = array( diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index c3910d2b3a..edad5218fa 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -7270,8 +7270,8 @@ function clean_post_cache( $post ) { } wp_cache_delete( $post->ID, 'posts' ); + wp_cache_delete( 'post_parent:' . (string) $post->ID, 'posts' ); wp_cache_delete( $post->ID, 'post_meta' ); - wp_cache_delete( $post->ID, 'post_parent' ); clean_object_term_cache( $post->ID, $post->post_type ); @@ -7817,17 +7817,37 @@ function _prime_post_caches( $ids, $update_term_cache = true, $update_meta_cache function _prime_post_parent_id_caches( array $ids ) { global $wpdb; - $non_cached_ids = _get_non_cached_ids( $ids, 'post_parent' ); + $ids = array_filter( $ids, '_validate_cache_id' ); + $ids = array_unique( array_map( 'intval', $ids ), SORT_NUMERIC ); + + if ( empty( $ids ) ) { + return; + } + + $cache_keys = array(); + foreach ( $ids as $id ) { + $cache_keys[ $id ] = 'post_parent:' . (string) $id; + } + + $cached_data = wp_cache_get_multiple( array_values( $cache_keys ), 'posts' ); + + $non_cached_ids = array(); + foreach ( $cache_keys as $id => $cache_key ) { + if ( false === $cached_data[ $cache_key ] ) { + $non_cached_ids[] = $id; + } + } + if ( ! empty( $non_cached_ids ) ) { $fresh_posts = $wpdb->get_results( sprintf( "SELECT $wpdb->posts.ID, $wpdb->posts.post_parent FROM $wpdb->posts WHERE ID IN (%s)", implode( ',', $non_cached_ids ) ) ); if ( $fresh_posts ) { $post_parent_data = array(); foreach ( $fresh_posts as $fresh_post ) { - $post_parent_data[ (int) $fresh_post->ID ] = (int) $fresh_post->post_parent; + $post_parent_data[ 'post_parent:' . (string) $fresh_post->ID ] = (int) $fresh_post->post_parent; } - wp_cache_add_multiple( $post_parent_data, 'post_parent' ); + wp_cache_add_multiple( $post_parent_data, 'posts' ); } } } diff --git a/tests/phpunit/tests/post/primePostParentsCaches.php b/tests/phpunit/tests/post/primePostParentsCaches.php index 6365688c22..1379aa4afb 100644 --- a/tests/phpunit/tests/post/primePostParentsCaches.php +++ b/tests/phpunit/tests/post/primePostParentsCaches.php @@ -42,7 +42,7 @@ class Tests_Post_PrimePostParentIdCaches extends WP_UnitTestCase { $num_queries = get_num_queries() - $before_num_queries; $this->assertSame( 1, $num_queries, 'Unexpected number of queries.' ); - $this->assertSameSets( array( 0 ), wp_cache_get_multiple( array( $post_id ), 'post_parent' ), 'Array of parent ids' ); + $this->assertSameSets( array( 0 ), wp_cache_get_multiple( array( "post_parent:{$post_id}" ), 'posts' ), 'Array of parent ids' ); } /** @@ -53,8 +53,15 @@ class Tests_Post_PrimePostParentIdCaches extends WP_UnitTestCase { _prime_post_parent_id_caches( self::$posts ); $num_queries = get_num_queries() - $before_num_queries; + $cache_keys = array_map( + function ( $post_id ) { + return "post_parent:{$post_id}"; + }, + self::$posts + ); + $this->assertSame( 1, $num_queries, 'Unexpected number of queries.' ); - $this->assertSameSets( array( 0, 0, 0 ), wp_cache_get_multiple( self::$posts, 'post_parent' ), 'Array of parent ids' ); + $this->assertSameSets( array( 0, 0, 0 ), wp_cache_get_multiple( $cache_keys, 'posts' ), 'Array of parent ids' ); } /** @@ -84,7 +91,7 @@ class Tests_Post_PrimePostParentIdCaches extends WP_UnitTestCase { $num_queries = get_num_queries() - $before_num_queries; $this->assertSame( 1, $num_queries, 'Unexpected number of queries on first run' ); - $this->assertSameSets( array( self::$posts[0] ), wp_cache_get_multiple( array( $page_id ), 'post_parent' ), 'Array of parent ids with post 0 as parent' ); + $this->assertSameSets( array( self::$posts[0] ), wp_cache_get_multiple( array( "post_parent:{$page_id}" ), 'posts' ), 'Array of parent ids with post 0 as parent' ); wp_update_post( array( @@ -98,7 +105,7 @@ class Tests_Post_PrimePostParentIdCaches extends WP_UnitTestCase { $num_queries = get_num_queries() - $before_num_queries; $this->assertSame( 1, $num_queries, 'Unexpected number of queries on second run' ); - $this->assertSameSets( array( self::$posts[1] ), wp_cache_get_multiple( array( $page_id ), 'post_parent' ), 'Array of parent ids with post 1 as parent' ); + $this->assertSameSets( array( self::$posts[1] ), wp_cache_get_multiple( array( "post_parent:{$page_id}" ), 'posts' ), 'Array of parent ids with post 1 as parent' ); } /** @@ -121,11 +128,11 @@ class Tests_Post_PrimePostParentIdCaches extends WP_UnitTestCase { $num_queries = get_num_queries() - $before_num_queries; $this->assertSame( 1, $num_queries, 'Unexpected number of queries on first run' ); - $this->assertSameSets( array( $parent_page_id ), wp_cache_get_multiple( array( $page_id ), 'post_parent' ), 'Array of parent ids with post 0 as parent' ); + $this->assertSameSets( array( $parent_page_id ), wp_cache_get_multiple( array( "post_parent:{$page_id}" ), 'posts' ), 'Array of parent ids with post 0 as parent' ); wp_delete_post( $parent_page_id, true ); $this->assertSame( 1, $num_queries, 'Unexpected number of queries on second run' ); - $this->assertSameSets( array( false ), wp_cache_get_multiple( array( $page_id ), 'post_parent' ), 'Array of parent ids with false values' ); + $this->assertSameSets( array( false ), wp_cache_get_multiple( array( "post_parent:{$page_id}" ), 'posts' ), 'Array of parent ids with false values' ); } } diff --git a/tests/phpunit/tests/query/cacheResults.php b/tests/phpunit/tests/query/cacheResults.php index 3e2d405850..dace2e313b 100644 --- a/tests/phpunit/tests/query/cacheResults.php +++ b/tests/phpunit/tests/query/cacheResults.php @@ -738,8 +738,15 @@ class Test_Query_CacheResults extends WP_UnitTestCase { $query1 = new WP_Query(); $query1->query( $args ); - $post_ids = wp_list_pluck( $query1->posts, 'ID' ); - wp_cache_delete_multiple( $post_ids, 'post_parent' ); + $post_ids = wp_list_pluck( $query1->posts, 'ID' ); + $cache_keys = array_map( + function ( $post_id ) { + return "post_parent:{$post_id}"; + }, + $post_ids + ); + + wp_cache_delete_multiple( $cache_keys, 'posts' ); $queries_before = get_num_queries(); $query2 = new WP_Query();