In a plugin, i create a dedicated user role along with some capabilities. These capabilities also need to be assigned to other roles, such as editor
and admin
.
As the addition of roles and capabilities involves database writes, these operations are commonly considered “expensive” and recommended to be performed only in the plugin activation hook. In my case, there is no activation hook, as the plugin needs to be loaded as mu-plugin. Therefore, i want to check if the admin and editor roles already have my custom capabilities, before attempting to add them.
How can i check if a specific role has a specific capability? Or, alternatively: Is it even less “expensive” to make the check? Or should i just make the call to add_cap()
from the init
hook without prior checks?
#Update:
Wow, I feel like such a buffoon… haha. WP_Role::has_cap
I can’t (role) my eyes hard enough.
$caps = array( 'cap_1', 'cap_2', 'cap_3' );
$roles = array( 'administrator', 'editor' );
foreach( $roles as $role ) {
if( $role_object = get_role( $role ) ) {
foreach( $caps as $cap ) {
if( !$role_object->has_cap( $cap ) ) {
$role_object->add_cap( $cap );
}
}
}
}
#Disregard this nonesense:
I apologize, my other answer was per user not per role.
What you can do is check to see if the role has the capability using get_role()
You can see that get_role( 'administrator' )
will return an Object that has an array of capabilities in it.
$administrator = get_role( 'administrator' );
// Make sure role object was retrieved
if( $administrator ){
//See if it's got our capability or not
if( !in_array( 'my-custom-cap', $administrator->capabilities ) ){
// Wasn't there, so add it here
$administrator->add_cap( 'my-custom-cap' );
}
}
If for some reason you don’t want to run the $role
object comparison each time, you can define it once and then set a flag in the database with update_option()
and check it with get_option()
if( get_option( 'manually_set_add_cap_admin' ) != true ){
$administrator = get_role( 'administrator' );
// Make sure role object was retrieved
if( $administrator ){
//See if it's got our capability or not
if( !in_array( 'my-custom-cap', $administrator->capabilities ) ){
// Wasn't there, so add it here
$administrator->add_cap( 'my-custom-cap' );
update_option( 'manually_set_add_cap_admin', true );
}
}
}
Here’s a bit more lengthy solution that will loop through any roles you add, and give them all the appropriate capabilities. After the loops are completed, it will set a flag that’s checked, so there won’t be any WP_Role object fetching after it’s ran the first time.
// Define flag as a variable to prevent typos, in update/get_option
// or it will constantly run (I know from experience...)
$flag = 'manually_added_my_custom_caps';
if( !get_option( $flag ) ){
// Our flag option wasn't set, that means this code hasn't run yet.
$roles = array( 'administrator', 'editor' );
$capabilities = array( 'custom-cap-1', 'custom-cap-2' );
// Loop through each role
foreach( $roles as $role ){
// Make sure we got a WP_Role object back
if( $role_object = get_role( $role ) ){
// Loop through our custom capabilities
foreach( $capabilities as $cap ){
// Our option flag wasn't set, but let's confirm
// that the role doesn't have the cap
if( !in_array( $cap, $role_object->capabilities ) ){
// Confirmed not there, add it here
$role_object->add_cap( $cap );
}
}
}
}
// Our function ran, it should have set all caps to all the roles
// so now our code will skip this entirely next time
update_option( $flag, true );
}