Assigning multiple or additional capabilities to specific users or how to create additional roles like bbpress roles?

In WordPress is pretty simple create custom roles and also assign specific capabilities to specific user roles (no matter if from core or custom).

In my plugins I often create an user role that has all the capabilities required by my plugin, and then I attach some of thos capabilities to existing roles.

I’ll give you an example, that I think will help you facing this issues.

Assuming you create a plugin that needs 3 capabilities:

  • ‘do_foo’
  • ‘do_bar’
  • ‘do_baz’

You can create a custom role that has all three capabilities, and then

  • assign all 3 categories to administrators
  • assign ‘do_bar’ and ‘do_baz’ to editors, authors and constributors
  • assign only ‘do_baz’ to subscribers

Following simple function does all previous things:

function my_plugin_custom_caps()
{
  $caps = array('do_foo' => true, 'do_bar' => true, 'do_baz' => true);
  // First of all create the new user role, add all custom caps + 'read'
  add_role( 'myrole', 'My Role', array_merge( $caps, array( 'read' => true ) ) );
  // Set specific caps to specific roles.
  // 1. prepare the roles array
  $all_roles = array('administrator', 'editor', 'author', 'constributor', 'subscriber');
  // 2. get WP_Roles object to do the work
  $roles_obj = new WP_Roles();
  // 3. Loop roles and assign caps
  foreach ( $all_roles as $role ) {
    // 4. cycle the caps and assign them one by one using some logic to assign right caps
    foreach ( $assign as $cap ) {
       if( $role === 'subscriber' && $cap !== 'do_baz' ) continue;
       if( $role !== 'administrator' && $cap === 'do_foo' ) continue;
       $roles_obj->add_cap( $role, $cap );
    }
  }
}

Once WordPress saves capabilities on database, is a good idea perform this task on plugin activation, so it runs only once:

register_activation_hook( __FILE__, 'my_plugin_custom_caps' );

Also is a good habit remove added capabilities and custom roles when plugin is deactivated, so you can create a my_plugin_custom_caps_undo function and use it with register_deactivation_hook.

That function would be almost identical to my_plugin_custom_caps(), but remove_role is used instead of add_role and remove_cap instead of add_cap:

function my_custom_caps_undo() {
  remove_role( 'myrole' );
  $caps = array('do_foo' => true, 'do_bar' => true, 'do_baz' => true );
  $all_roles = array('administrator', 'editor', 'author', 'constributor', 'subscriber');
  $roles_obj = new WP_Roles();
  foreach ( $all_roles as $role ) {
    foreach ( $caps as $cap ) {
      if( $role === 'subscriber' && $cap !== 'do_baz' ) continue;
      if( $role !== 'administrator' && $cap === 'do_foo' ) continue;
      $roles_obj->remove_cap( $role, $cap );
    }
  }
}

register_deactivation_hook( __FILE__, 'my_custom_caps_undo' );