From d28687551563453b06b4042c4bcc9b7ecffd37c4 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 9 Aug 2012 16:28:15 +0000 Subject: [PATCH] switch_to_blog() and restore_current_blog() housekeeping. wp-includes/admin-bar.php: * Replace get_admin_url() and get_home_url() with admin_url() and home_url() and place them inside a switch/restore. Likewise replace current_user_can_for_blog() with current_user_can(). This avoids doing multiple switch restores. wp-includes/ms-blogs.php: * Deprecate the $validate argument to switch_to_blog(). This avoids a not very necessary call to get_blog_details(), possibly saving a few queries. * Use $_wp_switched and $_wp_switched_stack instead of $switched and $switched_stack to make it less likely these globals will be stomped. * Use GLOBALS to access blog_id and other globals. I've preferred this style lately since it makes it obvious a global is being used and avoids global blog_id being stomped by a local variable. * Lose some is_object() checks. wp_get_current_user() always returns an object, for example. * Call the new WP_Roles::reinit() method. wp-includes/class-wp-xmlrpc-server.php: * Replace current_user_can_for_blog() with current_user_can() and move it inside the switch/restore pair. This eliminates a switch/restore. wp-includes/capabilities.php: * Use array_keys() instead of $role => $data since $data is unused. I *think* this is a bit faster. * Introduce WP_Roles::reinit(). This reinitializes WP_Roles and is used after switch_to_blog() has already update the blog ID in the wpdb object. If a global roles array is being used instead of the db, reinit is skipped. * current_user_can_for_blog() now does a switch/restore. It didn't before meaning it could be reinitializing the user with the wrong role information for the current blog. wp-includes/ms-settings.php: * Define $_wp_switched_stack and $_wp_switched. This way switch_to_blog() and restore_current_blog() can rely on it being set. wp-settings.php: * Instantiate the WP_Roles global. This was it is always defined during init. To remove the WP_Roles checks from WP_Role and WP_User this would probably have to move before plugins are loaded, which might not be a good thing. wp-includes/functions.php: * Update wp_upload_dir() to reference _wp_switched. git-svn-id: http://core.svn.wordpress.org/trunk@21485 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/admin-bar.php | 18 ++-- wp-includes/capabilities.php | 49 ++++++++--- wp-includes/class-wp-xmlrpc-server.php | 5 +- wp-includes/functions.php | 6 +- wp-includes/ms-blogs.php | 114 +++++++++++-------------- wp-includes/ms-settings.php | 2 + wp-settings.php | 7 ++ 7 files changed, 113 insertions(+), 88 deletions(-) diff --git a/wp-includes/admin-bar.php b/wp-includes/admin-bar.php index 4bc0302623..31122fe8cf 100644 --- a/wp-includes/admin-bar.php +++ b/wp-includes/admin-bar.php @@ -344,8 +344,8 @@ function wp_admin_bar_my_sites_menu( $wp_admin_bar ) { $blue_wp_logo_url = includes_url('images/wpmini-blue.png'); foreach ( (array) $wp_admin_bar->user->blogs as $blog ) { - // @todo Replace with some favicon lookup. - //$blavatar = 'Blavatar'; + switch_to_blog( $blog->userblog_id ); + $blavatar = '' . esc_attr__( 'Blavatar' ) . ''; $blogname = empty( $blog->blogname ) ? $blog->domain : $blog->blogname; @@ -355,28 +355,28 @@ function wp_admin_bar_my_sites_menu( $wp_admin_bar ) { 'parent' => 'my-sites-list', 'id' => $menu_id, 'title' => $blavatar . $blogname, - 'href' => get_admin_url( $blog->userblog_id ), + 'href' => admin_url(), ) ); $wp_admin_bar->add_menu( array( 'parent' => $menu_id, 'id' => $menu_id . '-d', 'title' => __( 'Dashboard' ), - 'href' => get_admin_url( $blog->userblog_id ), + 'href' => admin_url(), ) ); - if ( current_user_can_for_blog( $blog->userblog_id, 'edit_posts' ) ) { + if ( current_user_can( 'edit_posts' ) ) { $wp_admin_bar->add_menu( array( 'parent' => $menu_id, 'id' => $menu_id . '-n', 'title' => __( 'New Post' ), - 'href' => get_admin_url( $blog->userblog_id, 'post-new.php' ), + 'href' => admin_url( 'post-new.php' ), ) ); $wp_admin_bar->add_menu( array( 'parent' => $menu_id, 'id' => $menu_id . '-c', 'title' => __( 'Manage Comments' ), - 'href' => get_admin_url( $blog->userblog_id, 'edit-comments.php' ), + 'href' => admin_url( 'edit-comments.php' ), ) ); } @@ -384,8 +384,10 @@ function wp_admin_bar_my_sites_menu( $wp_admin_bar ) { 'parent' => $menu_id, 'id' => $menu_id . '-v', 'title' => __( 'Visit Site' ), - 'href' => get_home_url( $blog->userblog_id, '/' ), + 'href' => home_url( '/' ), ) ); + + restore_current_blog(); } } diff --git a/wp-includes/capabilities.php b/wp-includes/capabilities.php index 4687d4f18b..585ab28312 100644 --- a/wp-includes/capabilities.php +++ b/wp-includes/capabilities.php @@ -108,7 +108,37 @@ class WP_Roles { $this->role_objects = array(); $this->role_names = array(); - foreach ( (array) $this->roles as $role => $data ) { + foreach ( array_keys( $this->roles ) as $role ) { + $this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] ); + $this->role_names[$role] = $this->roles[$role]['name']; + } + } + + /** + * Reinitialize the object + * + * Recreates the role objects. This is typically called only by switch_to_blog() + * after switching wpdb to a new blog ID. + * + * @since 3.5.0 + * @access public + */ + function reinit() { + // There is no need to reinit if using the wp_user_roles global. + if ( ! $this->use_db ) + return; + + global $wpdb, $wp_user_roles; + + // Duplicated from _init() to avoid an extra function call. + $this->role_key = $wpdb->prefix . 'user_roles'; + $this->roles = get_option( $this->role_key ); + if ( empty( $this->roles ) ) + return; + + $this->role_objects = array(); + $this->role_names = array(); + foreach ( array_keys( $this->roles ) as $role ) { $this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] ); $this->role_names[$role] = $this->roles[$role]['name']; } @@ -233,8 +263,7 @@ class WP_Roles { * @param string $role Role name to look up. * @return bool */ - function is_role( $role ) - { + function is_role( $role ) { return isset( $this->role_names[$role] ); } } @@ -1231,21 +1260,21 @@ function current_user_can( $capability ) { * @return bool */ function current_user_can_for_blog( $blog_id, $capability ) { + switch_to_blog( $blog_id ); + $current_user = wp_get_current_user(); if ( empty( $current_user ) ) return false; - // Create new object to avoid stomping the global current_user. - $user = new WP_User( $current_user->ID ); - - // Set the blog id. @todo add blog id arg to WP_User constructor? - $user->for_blog( $blog_id ); - $args = array_slice( func_get_args(), 2 ); $args = array_merge( array( $capability ), $args ); - return call_user_func_array( array( &$user, 'has_cap' ), $args ); + $can = call_user_func_array( array( $current_user, 'has_cap' ), $args ); + + restore_current_blog(); + + return $can; } /** diff --git a/wp-includes/class-wp-xmlrpc-server.php b/wp-includes/class-wp-xmlrpc-server.php index 8965572029..e1b71483b8 100644 --- a/wp-includes/class-wp-xmlrpc-server.php +++ b/wp-includes/class-wp-xmlrpc-server.php @@ -473,9 +473,11 @@ class wp_xmlrpc_server extends IXR_Server { continue; $blog_id = $blog->userblog_id; - $is_admin = current_user_can_for_blog( $blog_id, 'manage_options' ); switch_to_blog( $blog_id ); + + $is_admin = current_user_can( 'manage_options' ); + $struct[] = array( 'isAdmin' => $is_admin, 'url' => home_url( '/' ), @@ -483,6 +485,7 @@ class wp_xmlrpc_server extends IXR_Server { 'blogName' => get_option( 'blogname' ), 'xmlrpc' => site_url( 'xmlrpc.php' ) ); + restore_current_blog(); } diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 4ee94f9ca0..222e23b219 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -1432,7 +1432,7 @@ function get_temp_dir() { * @return array See above for description. */ function wp_upload_dir( $time = null ) { - global $switched; + global $_wp_switched; $siteurl = get_option( 'siteurl' ); $upload_path = get_option( 'upload_path' ); $upload_path = trim($upload_path); @@ -1456,12 +1456,12 @@ function wp_upload_dir( $time = null ) { $url = trailingslashit( $siteurl ) . $upload_path; } - if ( defined('UPLOADS') && !$main_override && ( !isset( $switched ) || $switched === false ) ) { + if ( defined('UPLOADS') && ! $main_override && ! $_wp_switched ) { $dir = ABSPATH . UPLOADS; $url = trailingslashit( $siteurl ) . UPLOADS; } - if ( is_multisite() && !$main_override && ( !isset( $switched ) || $switched === false ) ) { + if ( is_multisite() && ! $main_override && ! $_wp_switched ) { if ( defined( 'BLOGUPLOADDIR' ) ) $dir = untrailingslashit(BLOGUPLOADDIR); $url = str_replace( UPLOADS, 'files', $url ); diff --git a/wp-includes/ms-blogs.php b/wp-includes/ms-blogs.php index 7f4ff6d8ba..79f5c30d84 100644 --- a/wp-includes/ms-blogs.php +++ b/wp-includes/ms-blogs.php @@ -446,72 +446,61 @@ function update_blog_option( $id, $option, $value, $deprecated = null ) { * @since MU * * @param int $new_blog The id of the blog you want to switch to. Default: current blog - * @param bool $validate Whether to check if $new_blog exists before proceeding + * @param bool $deprecated Depecreated argument * @return bool True on success, False if the validation failed */ -function switch_to_blog( $new_blog, $validate = false ) { - global $wpdb, $table_prefix, $blog_id, $switched, $switched_stack, $wp_roles, $wp_object_cache; +function switch_to_blog( $new_blog, $deprecated = null ) { + global $wpdb, $wp_roles; - if ( empty($new_blog) ) - $new_blog = $blog_id; + if ( empty( $new_blog ) ) + $new_blog = $GLOBALS['blog_id']; - if ( $validate && ! get_blog_details( $new_blog ) ) - return false; - - if ( empty($switched_stack) ) - $switched_stack = array(); - - $switched_stack[] = $blog_id; + $GLOBALS['_wp_switched_stack'][] = $GLOBALS['blog_id']; /* If we're switching to the same blog id that we're on, * set the right vars, do the associated actions, but skip * the extra unnecessary work */ - if ( $blog_id == $new_blog ) { - do_action( 'switch_blog', $blog_id, $blog_id ); - $switched = true; + if ( $new_blog == $GLOBALS['blog_id'] ) { + do_action( 'switch_blog', $new_blog, $new_blog ); + $GLOBALS['_wp_switched'] = true; return true; } - $wpdb->set_blog_id($new_blog); - $table_prefix = $wpdb->prefix; - $prev_blog_id = $blog_id; - $blog_id = $new_blog; + $wpdb->set_blog_id( $new_blog ); + $GLOBALS['table_prefix'] = $wpdb->prefix; + $prev_blog_id = $GLOBALS['blog_id']; + $GLOBALS['blog_id'] = $new_blog; - if ( is_object( $wp_roles ) ) { - $wpdb->suppress_errors(); - if ( method_exists( $wp_roles ,'_init' ) ) - $wp_roles->_init(); - elseif ( method_exists( $wp_roles, '__construct' ) ) - $wp_roles->__construct(); - $wpdb->suppress_errors( false ); - } - - if ( did_action('init') ) { + if ( did_action( 'init' ) ) { + $wp_roles->reinit(); $current_user = wp_get_current_user(); - if ( is_object( $current_user ) ) - $current_user->for_blog( $blog_id ); + $current_user->for_blog( $new_blog ); } if ( function_exists( 'wp_cache_switch_to_blog' ) ) { - wp_cache_switch_to_blog( $blog_id ); + wp_cache_switch_to_blog( $new_blog ); } else { + global $wp_object_cache; + if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) ) $global_groups = $wp_object_cache->global_groups; else $global_groups = false; wp_cache_init(); - if ( function_exists('wp_cache_add_global_groups') ) { + + if ( function_exists( 'wp_cache_add_global_groups' ) ) { if ( is_array( $global_groups ) ) wp_cache_add_global_groups( $global_groups ); else wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts' ) ); - wp_cache_add_non_persistent_groups(array( 'comment', 'counts', 'plugins' )); + wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) ); } } - do_action('switch_blog', $blog_id, $prev_blog_id); - $switched = true; + do_action( 'switch_blog', $new_blog, $prev_blog_id ); + $GLOBALS['_wp_switched'] = true; + return true; } @@ -524,64 +513,57 @@ function switch_to_blog( $new_blog, $validate = false ) { * @return bool True on success, False if we're already on the current blog */ function restore_current_blog() { - global $table_prefix, $wpdb, $blog_id, $switched, $switched_stack, $wp_roles, $wp_object_cache; + global $wpdb, $wp_roles; - if ( !$switched ) + if ( ! $GLOBALS['_wp_switched'] ) return false; - if ( !is_array( $switched_stack ) ) - return false; + $blog = array_pop( $GLOBALS['_wp_switched_stack'] ); - $blog = array_pop( $switched_stack ); - if ( $blog_id == $blog ) { + if ( $GLOBALS['blog_id'] == $blog ) { do_action( 'switch_blog', $blog, $blog ); - /* If we still have items in the switched stack, consider ourselves still 'switched' */ - $switched = ( is_array( $switched_stack ) && count( $switched_stack ) > 0 ); + // If we still have items in the switched stack, consider ourselves still 'switched' + $GLOBALS['_wp_switched'] = ! empty( $GLOBALS['_wp_switched_stack'] ); return true; } - $wpdb->set_blog_id($blog); - $prev_blog_id = $blog_id; - $blog_id = $blog; - $table_prefix = $wpdb->prefix; + $wpdb->set_blog_id( $blog ); + $prev_blog_id = $GLOBALS['blog_id']; + $GLOBALS['blog_id'] = $blog; + $GLOBALS['table_prefix'] = $wpdb->prefix; - if ( is_object( $wp_roles ) ) { - $wpdb->suppress_errors(); - if ( method_exists( $wp_roles ,'_init' ) ) - $wp_roles->_init(); - elseif ( method_exists( $wp_roles, '__construct' ) ) - $wp_roles->__construct(); - $wpdb->suppress_errors( false ); - } - - if ( did_action('init') ) { + if ( did_action( 'init' ) ) { + $wp_roles->reinit(); $current_user = wp_get_current_user(); - if ( is_object( $current_user ) ) - $current_user->for_blog( $blog_id ); + $current_user->for_blog( $blog ); } if ( function_exists( 'wp_cache_switch_to_blog' ) ) { - wp_cache_switch_to_blog( $blog_id ); + wp_cache_switch_to_blog( $blog ); } else { + global $wp_object_cache; + if ( is_object( $wp_object_cache ) && isset( $wp_object_cache->global_groups ) ) $global_groups = $wp_object_cache->global_groups; else $global_groups = false; wp_cache_init(); - if ( function_exists('wp_cache_add_global_groups') ) { + + if ( function_exists( 'wp_cache_add_global_groups' ) ) { if ( is_array( $global_groups ) ) wp_cache_add_global_groups( $global_groups ); else wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts' ) ); - wp_cache_add_non_persistent_groups(array( 'comment', 'counts', 'plugins' )); + wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) ); } } - do_action('switch_blog', $blog_id, $prev_blog_id); + do_action( 'switch_blog', $blog, $prev_blog_id ); + + // If we still have items in the switched stack, consider ourselves still 'switched' + $GLOBALS['_wp_switched'] = ! empty( $GLOBALS['_wp_switched_stack'] ); - /* If we still have items in the switched stack, consider ourselves still 'switched' */ - $switched = ( is_array( $switched_stack ) && count( $switched_stack ) > 0 ); return true; } diff --git a/wp-includes/ms-settings.php b/wp-includes/ms-settings.php index 5dd460e301..fe5350079a 100644 --- a/wp-includes/ms-settings.php +++ b/wp-includes/ms-settings.php @@ -126,6 +126,8 @@ if ( !isset( $current_site ) || !isset( $current_blog ) ) { $wpdb->set_prefix( $table_prefix, false ); // $table_prefix can be set in sunrise.php $wpdb->set_blog_id( $current_blog->blog_id, $current_blog->site_id ); $table_prefix = $wpdb->get_blog_prefix(); +$_wp_switched_stack = array(); +$_wp_switched = false; // need to init cache again after blog_id is set wp_start_object_cache(); diff --git a/wp-settings.php b/wp-settings.php index 1e5751fa5b..726e1b06b0 100644 --- a/wp-settings.php +++ b/wp-settings.php @@ -252,6 +252,13 @@ $wp = new WP(); */ $GLOBALS['wp_widget_factory'] = new WP_Widget_Factory(); +/** + * WordPress User Roles + * @global object $wp_roles + * @since 2.0.0 + */ +$GLOBALS['wp_roles'] = new WP_Roles(); + do_action( 'setup_theme' ); // Define the template related constants.