diff --git a/src/wp-includes/class-wp-roles.php b/src/wp-includes/class-wp-roles.php index b7558748db..a665191f4a 100644 --- a/src/wp-includes/class-wp-roles.php +++ b/src/wp-includes/class-wp-roles.php @@ -127,6 +127,15 @@ class WP_Roles { $this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] ); $this->role_names[$role] = $this->roles[$role]['name']; } + + /** + * After the roles have been initialized, allow plugins to add their own roles. + * + * @since 4.7.0 + * + * @param WP_Roles A reference to the WP_Roles object. + */ + do_action( 'wp_roles_init', $this ); } /** @@ -136,28 +145,12 @@ class WP_Roles { * after switching wpdb to a new site ID. * * @since 3.5.0 + * @deprecated 4.7.0 Use new WP_Roles() * @access public */ public function reinit() { - global $wpdb; - - // There is no need to reinit if using the wp_user_roles global. - if ( ! $this->use_db ) { - return; - } - - // Duplicated from _init() to avoid an extra function call. - $this->role_key = $wpdb->get_blog_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']; - } + __deprecated_function( __METHOD__, '4.7.0', 'new WP_Roles()' ); + $this->_init(); } /** diff --git a/src/wp-includes/ms-blogs.php b/src/wp-includes/ms-blogs.php index db3e4639c1..9188750386 100644 --- a/src/wp-includes/ms-blogs.php +++ b/src/wp-includes/ms-blogs.php @@ -766,7 +766,7 @@ function update_blog_option( $id, $option, $value, $deprecated = null ) { * @return true Always returns True. */ function switch_to_blog( $new_blog, $deprecated = null ) { - global $wpdb; + global $wpdb, $wp_roles; $blog_id = get_current_blog_id(); if ( empty( $new_blog ) ) { @@ -822,7 +822,7 @@ function switch_to_blog( $new_blog, $deprecated = null ) { } if ( did_action( 'init' ) ) { - wp_roles()->reinit(); + $wp_roles = new WP_Roles(); $current_user = wp_get_current_user(); $current_user->for_blog( $new_blog ); } @@ -850,7 +850,7 @@ function switch_to_blog( $new_blog, $deprecated = null ) { * @return bool True on success, false if we're already on the current blog */ function restore_current_blog() { - global $wpdb; + global $wpdb, $wp_roles; if ( empty( $GLOBALS['_wp_switched_stack'] ) ) { return false; @@ -896,7 +896,7 @@ function restore_current_blog() { } if ( did_action( 'init' ) ) { - wp_roles()->reinit(); + $wp_roles = new WP_Roles(); $current_user = wp_get_current_user(); $current_user->for_blog( $blog ); } diff --git a/tests/phpunit/tests/user/capabilities.php b/tests/phpunit/tests/user/capabilities.php index dfb34091ed..0948d88e75 100644 --- a/tests/phpunit/tests/user/capabilities.php +++ b/tests/phpunit/tests/user/capabilities.php @@ -41,8 +41,7 @@ class Tests_User_Capabilities extends WP_UnitTestCase { // this will flush everything and reload it from the db unset($GLOBALS['wp_user_roles']); global $wp_roles; - if ( is_object( $wp_roles ) ) - $wp_roles->_init(); + $wp_roles = new WP_Roles(); } function _meta_yes_you_can( $can, $key, $post_id, $user_id, $cap, $caps ) { @@ -1626,4 +1625,33 @@ class Tests_User_Capabilities extends WP_UnitTestCase { $this->assertFalse( current_user_can( 'do_not_allow' ), "Non-logged-in user should not have the do_not_allow capability" ); } + protected $_role_test_wp_roles_role; + /** + * @ticket 23016 + */ + public function test_wp_roles_init_action() { + $this->_role_test_wp_roles_init = array( + 'role' => 'test_wp_roles_init', + 'info' => array( + 'name' => 'Test WP Roles Init', + 'capabilities' => array( 'testing_magic' => true ), + ), + ); + add_action( 'wp_roles_init', array( $this, '_hook_wp_roles_init' ), 10, 1 ); + + $wp_roles = new WP_Roles(); + + remove_action( 'wp_roles_init', array( $this, '_hook_wp_roles_init' ) ); + + $expected = new WP_Role( $this->_role_test_wp_roles_init['role'], $this->_role_test_wp_roles_init['info']['capabilities'] ); + + $role = $wp_roles->get_role( $this->_role_test_wp_roles_init['role'] ); + + $this->assertEquals( $expected, $role ); + $this->assertContains( $this->_role_test_wp_roles_init['info']['name'], $wp_roles->role_names ); + } + + public function _hook_wp_roles_init( $wp_roles ) { + $wp_roles->add_role( $this->_role_test_wp_roles_init['role'], $this->_role_test_wp_roles_init['info']['name'], $this->_role_test_wp_roles_init['info']['capabilities'] ); + } } diff --git a/tests/phpunit/tests/user/multisite.php b/tests/phpunit/tests/user/multisite.php index 698c6ffcd6..f6856844df 100644 --- a/tests/phpunit/tests/user/multisite.php +++ b/tests/phpunit/tests/user/multisite.php @@ -396,6 +396,34 @@ class Tests_Multisite_User extends WP_UnitTestCase { $this->assertWPError( $result ); } + + /** + * @ticket 23016 + */ + public function test_wp_roles_global_is_reset() { + global $wp_roles; + $role = 'test_global_is_reset'; + $role_name = 'Test Global Is Reset'; + $blog_id = self::factory()->blog->create(); + + $wp_roles->add_role( $role, $role_name, array() ); + + $this->assertNotEmpty( $wp_roles->get_role( $role ) ); + + switch_to_blog( $blog_id ); + + $this->assertEmpty( $wp_roles->get_role( $role ) ); + + $wp_roles->add_role( $role, $role_name, array() ); + + $this->assertNotEmpty( $wp_roles->get_role( $role ) ); + + restore_current_blog(); + + $this->assertNotEmpty( $wp_roles->get_role( $role ) ); + + $wp_roles->remove_role( $role ); + } } endif ;