diff --git a/wp-includes/cache.php b/wp-includes/cache.php index 4353687328..ca1dae64e0 100644 --- a/wp-includes/cache.php +++ b/wp-includes/cache.php @@ -149,8 +149,9 @@ function wp_cache_set($key, $data, $flag = '', $expire = 0) { * @param string|array $groups A group or an array of groups to add */ function wp_cache_add_global_groups( $groups ) { - // Default cache doesn't persist so nothing to do here. - return; + global $wp_object_cache; + + return $wp_object_cache->add_global_groups($groups); } /** @@ -165,6 +166,20 @@ function wp_cache_add_non_persistent_groups( $groups ) { return; } +/** + * Reset internal cache keys and structures. If the cache backend uses global blog or site IDs as part of its cache keys, + * this function instructs the backend to reset those keys and perform any cleanup since blog or site IDs have changed since cache init. + * + * @since 2.6.0 + * + * @param string|array $groups A group or an array of groups to add + */ +function wp_cache_reset() { + global $wp_object_cache; + + return $wp_object_cache->reset(); +} + /** * WordPress Object Cache * @@ -219,6 +234,15 @@ class WP_Object_Cache { */ var $cache_misses = 0; + /** + * List of global groups + * + * @var array + * @access protected + * @since 3.0.0 + */ + var $global_groups = array(); + /** * Adds data to the cache if it doesn't already exist. * @@ -234,8 +258,8 @@ class WP_Object_Cache { * @param int $expire When to expire the cache contents * @return bool False if cache ID and group already exists, true on success */ - function add($id, $data, $group = 'default', $expire = '') { - if (empty ($group)) + function add( $id, $data, $group = 'default', $expire = '' ) { + if ( empty ($group) ) $group = 'default'; if (false !== $this->get($id, $group)) @@ -244,6 +268,20 @@ class WP_Object_Cache { return $this->set($id, $data, $group, $expire); } + /** + * Sets the list of global groups. + * + * @since 3.0.0 + * + * @param array $groups List of groups that are global. + */ + function add_global_groups( $groups ) { + $groups = (array) $groups; + + $this->global_groups = array_merge($this->global_groups, $groups); + $this->global_groups = array_unique($this->global_groups); + } + /** * Remove the contents of the cache ID in the group * @@ -308,10 +346,10 @@ class WP_Object_Cache { * contents on success */ function get($id, $group = 'default') { - if (empty ($group)) + if ( empty ($group) ) $group = 'default'; - if (isset ($this->cache[$group][$id])) { + if ( isset ($this->cache[$group][$id]) ) { $this->cache_hits += 1; if ( is_object($this->cache[$group][$id]) ) return wp_clone($this->cache[$group][$id]); @@ -343,12 +381,25 @@ class WP_Object_Cache { if (empty ($group)) $group = 'default'; - if (false === $this->get($id, $group)) + if ( false === $this->get($id, $group) ) return false; return $this->set($id, $data, $group, $expire); } + /** + * Reset keys + * + * @since 3.0.0 + */ + function reset() { + // Clear out non-global caches since the blog ID has changed. + foreach ( array_keys($this->cache) as $group ) { + if ( !in_array($group, $this->global_groups) ) + unset($this->cache[$group]); + } + } + /** * Sets the data contents into the cache * @@ -370,10 +421,10 @@ class WP_Object_Cache { * @return bool Always returns true */ function set($id, $data, $group = 'default', $expire = '') { - if (empty ($group)) + if ( empty ($group) ) $group = 'default'; - if (NULL === $data) + if ( NULL === $data ) $data = ''; if ( is_object($data) ) @@ -381,7 +432,7 @@ class WP_Object_Cache { $this->cache[$group][$id] = $data; - if(isset($this->non_existent_objects[$group][$id])) + if ( isset($this->non_existent_objects[$group][$id]) ) unset ($this->non_existent_objects[$group][$id]); return true; diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 1ebfcd69ff..6aee150c6e 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -437,6 +437,29 @@ function wp_load_alloptions() { return $alloptions; } +function wp_load_core_site_options( $site_id = null ) { + global $wpdb, $_wp_using_ext_object_cache; + + if ( !is_multisite() || $_wp_using_ext_object_cache || defined( 'WP_INSTALLING' ) ) + return; + + if ( empty($site_id) ) + $site_id = $wpdb->siteid; + + $core_options = array('site_name', 'siteurl', 'active_sitewide_plugins', '_site_transient_timeout_theme_roots', '_site_transient_theme_roots', 'site_admins', 'dashboard_blog'); + + $core_options_in = "'" . implode("', '", $core_options) . "'"; + $options = $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->sitemeta WHERE meta_key IN ($core_options_in) AND site_id = %d", $site_id) ); + + foreach ( $options as $option ) { + $key = $option->meta_key; + $cache_key = "{$site_id}:$key"; + $option->meta_value = maybe_unserialize( $option->meta_value ); + + wp_cache_set( $cache_key, $option->meta_value, 'site-options' ); + } +} + /** * Update the value of an option that was already added. * @@ -3320,19 +3343,20 @@ function get_site_option( $key, $default = false, $use_cache = true ) { if ( !is_multisite() ) { $value = get_option($key, $default); } else { - $cache_key = "{$wpdb->siteid}:$key"; + $cache_key = "$wpdb->siteid:$key"; + if ( $use_cache ) + $value = wp_cache_get($cache_key, 'site-options'); - if ( $use_cache == true && $value = wp_cache_get($cache_key, 'site-options') ) - return $value; + if ( false === $value ) { + $value = $wpdb->get_var( $wpdb->prepare("SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $key, $wpdb->siteid) ); - $value = $wpdb->get_var( $wpdb->prepare("SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $key, $wpdb->siteid) ); + if ( is_null($value) ) + $value = $default; - if ( is_null($value) ) - $value = $default; + $value = maybe_unserialize( $value ); - $value = maybe_unserialize( $value ); - - wp_cache_set( $cache_key, $value, 'site-options' ); + wp_cache_set( $cache_key, $value, 'site-options' ); + } } return apply_filters( 'site_option_' . $key, $value ); diff --git a/wp-includes/load.php b/wp-includes/load.php index fb5a249120..0640fde78c 100644 --- a/wp-includes/load.php +++ b/wp-includes/load.php @@ -318,7 +318,8 @@ function wp_set_wpdb_vars() { * @since 3.0.0 */ function wp_start_object_cache() { - if ( ! function_exists( 'wp_cache_init' ) ) { + $first_init = false; + if ( ! function_exists( 'wp_cache_init' ) ) { global $_wp_using_ext_object_cache; if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) { require_once ( WP_CONTENT_DIR . '/object-cache.php' ); @@ -327,9 +328,17 @@ function wp_start_object_cache() { require_once ( ABSPATH . WPINC . '/cache.php' ); $_wp_using_ext_object_cache = false; } + $first_init = true; } - wp_cache_init(); + // If cache supports reset, reset instead of init if already initialized. + // Reset signals to the cache that global IDs have changed and it may need to update keys + // and cleanup caches. + if ( !$first_init && function_exists('wp_cache_reset') ) + wp_cache_reset(); + else + wp_cache_init(); + if ( function_exists( 'wp_cache_add_global_groups' ) ) { wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss' ) ); wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) ); diff --git a/wp-includes/ms-load.php b/wp-includes/ms-load.php index bd042a076b..77ba711b28 100644 --- a/wp-includes/ms-load.php +++ b/wp-includes/ms-load.php @@ -75,11 +75,14 @@ function ms_site_check() { */ function get_current_site_name( $current_site ) { global $wpdb; - $current_site->site_name = wp_cache_get( $current_site->id . ':current_site_name', "site-options" ); + $current_site->site_name = wp_cache_get( $current_site->id . ':current_site_name', 'site-options' ); if ( ! $current_site->site_name ) { - $current_site->site_name = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE site_id = %d AND meta_key = 'site_name'", $current_site->id ) ); - if ( ! $current_site->site_name ) - $current_site->site_name = ucfirst( $current_site->domain ); + $current_site->site_name = wp_cache_get( $current_site->id . ':site_name', 'site-options' ); + if ( ! $current_site->site_name ) { + $current_site->site_name = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE site_id = %d AND meta_key = 'site_name'", $current_site->id ) ); + if ( ! $current_site->site_name ) + $current_site->site_name = ucfirst( $current_site->domain ); + } wp_cache_set( $current_site->id . ':current_site_name', $current_site->site_name, 'site-options' ); } return $current_site; @@ -107,6 +110,8 @@ function wpmu_current_site() { else $current_site->cookie_domain = $current_site->domain; + wp_load_core_site_options($current_site->id); + return $current_site; } @@ -116,6 +121,7 @@ function wpmu_current_site() { $sites = $wpdb->get_results( "SELECT * FROM $wpdb->site" ); // usually only one site if ( 1 == count( $sites ) ) { + wp_load_core_site_options($current_site->id); $current_site = $sites[0]; $path = $current_site->path; $current_site->blog_id = $wpdb->get_var( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE domain = %s AND path = %s", $current_site->domain, $current_site->path ) );