From 2223743189ead316e07b49aadbb6bc2bde1474d2 Mon Sep 17 00:00:00 2001 From: Christoph Daum Date: Thu, 5 Jun 2025 11:03:49 +0200 Subject: [PATCH] fix: Fixes the broken caching issue in get_blog_details() When get_blog_details() is called with $get_all=true first, the full result is cached. A subsequent call with $get_all=false incorrectly returns the full cached result instead of a short one. The "try the other cache" block now discards the full cache hit when short is requested, allowing WP_Site::get_instance() to build a clean short result without an extra DB query. Ref: https://core.trac.wordpress.org/ticket/63518#ticket --- src/wp-includes/ms-blogs.php | 5 ++- .../tests/multisite/getBlogDetails.php | 42 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/ms-blogs.php b/src/wp-includes/ms-blogs.php index de3874f224bc4..47d235b0bc796 100644 --- a/src/wp-includes/ms-blogs.php +++ b/src/wp-includes/ms-blogs.php @@ -209,7 +209,6 @@ function get_blog_details( $fields = null, $get_all = true ) { $details = wp_cache_get( $blog_id . 'short', 'blog-details' ); } else { $details = wp_cache_get( $blog_id, 'blog-details' ); - // If short was requested and full cache is set, we can return. if ( $details ) { if ( ! is_object( $details ) ) { if ( -1 === $details ) { @@ -220,7 +219,9 @@ function get_blog_details( $fields = null, $get_all = true ) { unset( $details ); } } else { - return $details; + // Full cache is set but short was requested. Discard so a clean + // short result is built from WP_Site::get_instance() below. + unset( $details ); } } } diff --git a/tests/phpunit/tests/multisite/getBlogDetails.php b/tests/phpunit/tests/multisite/getBlogDetails.php index 5a374d43dc69a..5feb66347ff8b 100644 --- a/tests/phpunit/tests/multisite/getBlogDetails.php +++ b/tests/phpunit/tests/multisite/getBlogDetails.php @@ -193,6 +193,48 @@ public function test_get_blog_details_iterate_over_result( $get_all ) { $this->assertSameSets( $this->get_fields( $get_all ), $result ); } + /** + * @ticket 63518 + */ + public function test_get_blog_details_get_all_true_then_false_returns_short() { + $site_id = self::$site_ids['wordpress.org/']; + + // Ensure a clean cache state. + wp_cache_delete( $site_id, 'blog-details' ); + wp_cache_delete( $site_id . 'short', 'blog-details' ); + + // Populate the full cache first. + $full = get_blog_details( $site_id, true ); + $this->assertSameSets( $this->get_fields( true ), array_keys( get_object_vars( $full ) ) ); + + // A subsequent short request must not return the full result. + $short = get_blog_details( $site_id, false ); + $this->assertSameSets( $this->get_fields( false ), array_keys( get_object_vars( $short ) ) ); + } + + /** + * @ticket 63518 + */ + public function test_get_blog_details_false_true_false_returns_correct_fields() { + $site_id = self::$site_ids['wordpress.org/']; + + // Ensure a clean cache state. + wp_cache_delete( $site_id, 'blog-details' ); + wp_cache_delete( $site_id . 'short', 'blog-details' ); + + // Short first. + $short1 = get_blog_details( $site_id, false ); + $this->assertSameSets( $this->get_fields( false ), array_keys( get_object_vars( $short1 ) ) ); + + // Full second. + $full = get_blog_details( $site_id, true ); + $this->assertSameSets( $this->get_fields( true ), array_keys( get_object_vars( $full ) ) ); + + // Short again — must still return short fields. + $short2 = get_blog_details( $site_id, false ); + $this->assertSameSets( $this->get_fields( false ), array_keys( get_object_vars( $short2 ) ) ); + } + public function data_get_all() { return array( array( false ),