Make WordPress Core

Changeset 61760


Ignore:
Timestamp:
02/27/2026 07:57:26 PM (5 months ago)
Author:
johnjamesjacoby
Message:

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.

Location:
trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/cache-compat.php

    r60697 r61760  
    313313        }
    314314endif;
     315
     316if ( ! 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        }
     345endif;
  • trunk/src/wp-includes/ms-blogs.php

    r61649 r61760  
    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 */
     
    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 */
     
    686594
    687595        return true;
     596}
     597
     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 */
     611function 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        }
    688667}
    689668
Note: See TracChangeset for help on using the changeset viewer.