Skip to content

Commit 530fe2e

Browse files
committed
Cache API: Introduce fallback for when the wp_cache_switch_to_blog() function is missing.
This commit protects against an edge-case where a persistent object-cache drop-in plugin not including its own `wp_cache_switch_to_blog()` function would cause non-persistent cache groups to go missing when switching between sites, and includes the following changes: * A new `wp_cache_switch_to_blog_fallback()` function in `ms-blogs.php` which abstracts duplicated code from `switch_to_blog()` and `restore_current_blog()` for easier unit testing * A new `wpCacheSwitchToBlogFallback.php` file with approximately 25 new unit tests * Conditionally declares `wp_cache_switch_to_blog()` in `cache-compat.php` only if it does not already exist, either via core's `cache.php` or a drop-in plugin With this change, WordPress no longer needs to check if the `wp_cache_switch_to_blog()` function exists (because it always will) so those checks have been removed. Props ethitter, jeremyfelt, johnjamesjacoby, markjaquith, nacin, ozgursar, r1k0. Fixes #23290. git-svn-id: https://develop.svn.wordpress.org/trunk@61760 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 68194d5 commit 530fe2e

3 files changed

Lines changed: 1042 additions & 94 deletions

File tree

src/wp-includes/cache-compat.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,34 @@ function wp_cache_set_multiple_salted( $data, $group, $salt, $expire = 0 ) {
312312
return wp_cache_set_multiple( $new_cache, $group, $expire );
313313
}
314314
endif;
315+
316+
if ( ! function_exists( 'wp_cache_switch_to_blog' ) ) :
317+
/**
318+
* Used when switch_to_blog() and restore_current_blog() are called, but
319+
* only when a persistent object cache drop-in plugin has omitted the
320+
* wp_cache_switch_to_blog() function that was introduced in 3.5.0.
321+
*
322+
* @link https://core.trac.wordpress.org/ticket/23290
323+
*
324+
* @since 7.0.0
325+
*
326+
* @global WP_Object_Cache $wp_object_cache Object cache global instance.
327+
*
328+
* @param int $blog_id Site ID.
329+
*/
330+
function wp_cache_switch_to_blog( $blog_id ) {
331+
global $wp_object_cache;
332+
333+
// Attempt to use the drop-in object cache method if it exists.
334+
if ( method_exists( $wp_object_cache, 'switch_to_blog' ) ) {
335+
$wp_object_cache->switch_to_blog( $blog_id );
336+
return;
337+
}
338+
339+
/*
340+
* Perform a fallback blog switch, which will reinitialize the caches
341+
* for the new blog ID.
342+
*/
343+
wp_cache_switch_to_blog_fallback( $blog_id );
344+
}
345+
endif;

src/wp-includes/ms-blogs.php

Lines changed: 73 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -535,53 +535,7 @@ function switch_to_blog( $new_blog_id, $deprecated = null ) {
535535
$GLOBALS['table_prefix'] = $wpdb->get_blog_prefix();
536536
$GLOBALS['blog_id'] = $new_blog_id;
537537

538-
if ( function_exists( 'wp_cache_switch_to_blog' ) ) {
539-
wp_cache_switch_to_blog( $new_blog_id );
540-
} else {
541-
global $wp_object_cache;
542-
543-
if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) ) {
544-
$global_groups = $wp_object_cache->global_groups;
545-
} else {
546-
$global_groups = false;
547-
}
548-
549-
wp_cache_init();
550-
551-
if ( function_exists( 'wp_cache_add_global_groups' ) ) {
552-
if ( is_array( $global_groups ) ) {
553-
wp_cache_add_global_groups( $global_groups );
554-
} else {
555-
wp_cache_add_global_groups(
556-
array(
557-
'blog-details',
558-
'blog-id-cache',
559-
'blog-lookup',
560-
'blog_meta',
561-
'global-posts',
562-
'image_editor',
563-
'networks',
564-
'network-queries',
565-
'sites',
566-
'site-details',
567-
'site-options',
568-
'site-queries',
569-
'site-transient',
570-
'theme_files',
571-
'rss',
572-
'users',
573-
'user-queries',
574-
'user_meta',
575-
'useremail',
576-
'userlogins',
577-
'userslugs',
578-
)
579-
);
580-
}
581-
582-
wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
583-
}
584-
}
538+
wp_cache_switch_to_blog( $new_blog_id );
585539

586540
/** This filter is documented in wp-includes/ms-blogs.php */
587541
do_action( 'switch_blog', $new_blog_id, $prev_blog_id, 'switch' );
@@ -630,53 +584,7 @@ function restore_current_blog() {
630584
$GLOBALS['blog_id'] = $new_blog_id;
631585
$GLOBALS['table_prefix'] = $wpdb->get_blog_prefix();
632586

633-
if ( function_exists( 'wp_cache_switch_to_blog' ) ) {
634-
wp_cache_switch_to_blog( $new_blog_id );
635-
} else {
636-
global $wp_object_cache;
637-
638-
if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) ) {
639-
$global_groups = $wp_object_cache->global_groups;
640-
} else {
641-
$global_groups = false;
642-
}
643-
644-
wp_cache_init();
645-
646-
if ( function_exists( 'wp_cache_add_global_groups' ) ) {
647-
if ( is_array( $global_groups ) ) {
648-
wp_cache_add_global_groups( $global_groups );
649-
} else {
650-
wp_cache_add_global_groups(
651-
array(
652-
'blog-details',
653-
'blog-id-cache',
654-
'blog-lookup',
655-
'blog_meta',
656-
'global-posts',
657-
'image_editor',
658-
'networks',
659-
'network-queries',
660-
'sites',
661-
'site-details',
662-
'site-options',
663-
'site-queries',
664-
'site-transient',
665-
'theme_files',
666-
'rss',
667-
'users',
668-
'user-queries',
669-
'user_meta',
670-
'useremail',
671-
'userlogins',
672-
'userslugs',
673-
)
674-
);
675-
}
676-
677-
wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
678-
}
679-
}
587+
wp_cache_switch_to_blog( $new_blog_id );
680588

681589
/** This filter is documented in wp-includes/ms-blogs.php */
682590
do_action( 'switch_blog', $new_blog_id, $prev_blog_id, 'restore' );
@@ -687,6 +595,77 @@ function restore_current_blog() {
687595
return true;
688596
}
689597

598+
/**
599+
* Fallback logic for switching cache context when an object cache drop-in lacks
600+
* a switch_to_blog() method.
601+
*
602+
* Reinitializes the cache and restores global/non-persistent groups.
603+
*
604+
* Used by the wp_cache_switch_to_blog() compatibility function, abstracted only
605+
* to allow for unit testing outside of the drop-in plugin inclusion circus.
606+
*
607+
* @since 7.0.0
608+
*
609+
* @global WP_Object_Cache $wp_object_cache Object cache global instance.
610+
*/
611+
function wp_cache_switch_to_blog_fallback() {
612+
global $wp_object_cache;
613+
614+
$global_groups = false;
615+
$non_persistent_groups = false;
616+
617+
if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) ) {
618+
$global_groups = array_keys( $wp_object_cache->global_groups );
619+
$all_groups = array_fill_keys( array_keys( $wp_object_cache->cache ), true );
620+
$non_persistent_groups = array_keys( array_diff_key( $all_groups, $wp_object_cache->global_groups ) );
621+
}
622+
623+
wp_cache_init();
624+
625+
if ( function_exists( 'wp_cache_add_global_groups' ) ) {
626+
if ( ! is_array( $global_groups ) || empty( $global_groups ) ) {
627+
$global_groups = array(
628+
'blog-details',
629+
'blog-id-cache',
630+
'blog-lookup',
631+
'blog_meta',
632+
'global-posts',
633+
'image_editor',
634+
'networks',
635+
'network-queries',
636+
'sites',
637+
'site-details',
638+
'site-options',
639+
'site-queries',
640+
'site-transient',
641+
'theme_files',
642+
'translation_files',
643+
'rss',
644+
'users',
645+
'user-queries',
646+
'user_meta',
647+
'useremail',
648+
'userlogins',
649+
'userslugs',
650+
);
651+
}
652+
653+
wp_cache_add_global_groups( $global_groups );
654+
}
655+
656+
if ( function_exists( 'wp_cache_add_non_persistent_groups' ) ) {
657+
if ( ! is_array( $non_persistent_groups ) || empty( $non_persistent_groups ) ) {
658+
$non_persistent_groups = array(
659+
'counts',
660+
'plugins',
661+
'theme_json',
662+
);
663+
}
664+
665+
wp_cache_add_non_persistent_groups( $non_persistent_groups );
666+
}
667+
}
668+
690669
/**
691670
* Switches the initialized roles and current user capabilities to another site.
692671
*

0 commit comments

Comments
 (0)