Skip to content

Commit c42230c

Browse files
committed
Role/Capability: Add support for passing a numerically-indexed array of capability names to the add_role() function and the WP_Roles::add_role() method.
Denying a capability at the point of creating the role is a relatively uncommon requirement, so this simplifies the syntax needed to grant a list of capabilities to the role. Props eclev91, johnbillion, flixos90, johnjamesjacoby, soulseekah Fixes #43421 git-svn-id: https://develop.svn.wordpress.org/trunk@60364 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 632a634 commit c42230c

File tree

3 files changed

+78
-11
lines changed

3 files changed

+78
-11
lines changed

src/wp-includes/capabilities.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,12 +1096,34 @@ function get_role( $role ) {
10961096
/**
10971097
* Adds a role, if it does not exist.
10981098
*
1099+
* The list of capabilities can be passed either as a numerically indexed array of capability names, or an
1100+
* associative array of boolean values keyed by the capability name. To explicitly deny the role a capability, set
1101+
* the value for that capability to false.
1102+
*
1103+
* Examples:
1104+
*
1105+
* // Add a role that can edit posts.
1106+
* add_role( 'custom_role', 'Custom Role', array(
1107+
* 'read',
1108+
* 'edit_posts',
1109+
* ) );
1110+
*
1111+
* Or, using an associative array:
1112+
*
1113+
* // Add a role that can edit posts but explicitly cannot not delete them.
1114+
* add_role( 'custom_role', 'Custom Role', array(
1115+
* 'read' => true,
1116+
* 'edit_posts' => true,
1117+
* 'delete_posts' => false,
1118+
* ) );
1119+
*
10991120
* @since 2.0.0
1121+
* @since x.y.z Support was added for a numerically indexed array of strings for the capabilities array.
11001122
*
1101-
* @param string $role Role name.
1102-
* @param string $display_name Display name for role.
1103-
* @param bool[] $capabilities List of capabilities keyed by the capability name,
1104-
* e.g. array( 'edit_posts' => true, 'delete_posts' => false ).
1123+
* @param string $role Role name.
1124+
* @param string $display_name Display name for role.
1125+
* @param array<string,bool>|array<int,string> $capabilities Capabilities to be added to the role.
1126+
* Default empty array.
11051127
* @return WP_Role|void WP_Role object, if the role is added.
11061128
*/
11071129
function add_role( $role, $display_name, $capabilities = array() ) {

src/wp-includes/class-wp-roles.php

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,23 +143,45 @@ public function reinit() {
143143
*
144144
* Updates the list of roles, if the role doesn't already exist.
145145
*
146-
* The capabilities are defined in the following format: `array( 'read' => true )`.
147-
* To explicitly deny the role a capability, set the value for that capability to false.
146+
* The list of capabilities can be passed either as a numerically indexed array of capability names, or an
147+
* associative array of boolean values keyed by the capability name. To explicitly deny the role a capability, set
148+
* the value for that capability to false.
149+
*
150+
* Examples:
151+
*
152+
* // Add a role that can edit posts.
153+
* wp_roles()->add_role( 'custom_role', 'Custom Role', array(
154+
* 'read',
155+
* 'edit_posts',
156+
* ) );
157+
*
158+
* Or, using an associative array:
159+
*
160+
* // Add a role that can edit posts but explicitly cannot not delete them.
161+
* wp_roles()->add_role( 'custom_role', 'Custom Role', array(
162+
* 'read' => true,
163+
* 'edit_posts' => true,
164+
* 'delete_posts' => false,
165+
* ) );
148166
*
149167
* @since 2.0.0
168+
* @since x.y.z Support was added for a numerically indexed array of strings for the capabilities array.
150169
*
151-
* @param string $role Role name.
152-
* @param string $display_name Role display name.
153-
* @param bool[] $capabilities Optional. List of capabilities keyed by the capability name,
154-
* e.g. `array( 'edit_posts' => true, 'delete_posts' => false )`.
155-
* Default empty array.
170+
* @param string $role Role name.
171+
* @param string $display_name Role display name.
172+
* @param array<string,bool>|array<int,string> $capabilities Capabilities to be added to the role.
173+
* Default empty array.
156174
* @return WP_Role|void WP_Role object, if the role is added.
157175
*/
158176
public function add_role( $role, $display_name, $capabilities = array() ) {
159177
if ( empty( $role ) || isset( $this->roles[ $role ] ) ) {
160178
return;
161179
}
162180

181+
if ( wp_is_numeric_array( $capabilities ) ) {
182+
$capabilities = array_fill_keys( $capabilities, true );
183+
}
184+
163185
$this->roles[ $role ] = array(
164186
'name' => $display_name,
165187
'capabilities' => $capabilities,

tests/phpunit/tests/user/capabilities.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,29 @@ public function test_add_role() {
992992
$this->assertFalse( $wp_roles->is_role( $role_name ) );
993993
}
994994

995+
/**
996+
* Test add_role with implied capabilities grant successfully grants capabilities.
997+
*
998+
* @ticket 43421
999+
*/
1000+
public function test_add_role_with_single_level_capabilities() {
1001+
$role_name = 'janitor';
1002+
add_role(
1003+
$role_name,
1004+
'Janitor',
1005+
array(
1006+
'foo',
1007+
)
1008+
);
1009+
$this->flush_roles();
1010+
1011+
// Assign a user to that role.
1012+
$id = self::factory()->user->create( array( 'role' => $role_name ) );
1013+
$user = new WP_User( $id );
1014+
1015+
$this->assertTrue( $user->has_cap( 'foo' ) );
1016+
}
1017+
9951018
/**
9961019
* Change the capabilities associated with a role and make sure the change
9971020
* is reflected in has_cap().

0 commit comments

Comments
 (0)