Developing with user roles and capabilities


In this tutorial, you will learn how to develop with the built-in WordPress Roles and Capabilities system. You will learn how the user roles and capabilities are set up, how to create and apply user roles, and how to add or remove capabilities from a user role.

Learning outcomes

  1. Explain the WordPress user roles and capabilities system
  2. Assign capabilities to an existing role
  3. Create a new User Role and assign capabilities to it

Comprehension questions

  1. What is the name of the option which stores the default user roles and capabilities in the database?
  2. What is the name of the method on the Role class that you can use to add capacities to a role?
  3. Which function can be used to create a new custom role, and assign capabilities to it?
  4. How should you register new roles or assign new capabilities?
View video transcript

Hey there, and welcome to Learn WordPress.

In this tutorial, you’ll be learning how to leverage the WordPress user roles and capabilities system. After a brief introduction to the default WordPress roles and capabilities, how they are created and managed and how to assign them to users, you will learn how to add capabilities to an existing role, and also how to create a new user role and add capabilities to it.

The WordPress user roles and capabilities system is a powerful tool for managing access to your site. It allows for user roles with specific capabilities, and you can then assign those roles to users. This allows you to create a hierarchy of users with some users having more access than others.

WordPress comes with several default user roles, namely administrator, editor, author, contributor and subscriber. There is one additional role but this is only available in multisite installations, and that’s the Super Admin role. Each of these roles has a default set of capabilities, which are the things that the user can do in a WordPress site. For example, the administrator role has the capability to activate plugins while the subscriber role does not.

When a new user is created in the WordPress dashboard, they are assigned the subscriber role by default. You can change this by assigning a different role. Once assigned to that role, the user will have the capabilities that are associated with that role.

You can read up on the full list of default user roles and capabilities in the official WordPress documentation.

The WordPress user roles and capabilities system is stored in the database during the WordPress installation process. The roles and capabilities are stored as a serialised array as site options in the options table in the user roles option. The prefix for this option will depend on the table prefix configured in WP config, or if this is a multisite installation.

By default on a single site installation this prefix will be wp_.

So the option will be wp_user_roles.

If you extract the value of the user roles option and unserialize the array, you will see that the array keys are the role names and the values are arrays of capabilities. Whenever an authenticated user is attempting to do something, this action is checked against the users role capabilities using the current_user_can function. If the user has the capability to perform the action, they will be allowed to do so. If they do not have the capability, they will be denied access.

If you take a look at line 270 of the wp-admin/includes/post.php file, you will see that the edit_post capability is checked before a post is edited or updated. If the user does not have the edit_post capability for this post, they will be informed that they do not have the required access to edit it.

Let’s say that you want to allow your editors to be able to do something that only admins can do, maybe install and update plugins. By default, the editor role does not have the activate_plugins or update_plugins capability. You can add this capability to the editor role by using the add_cap method of the WP_Role class. However, doing so will add this capability to the user roles stored in the database. So it’s recommended to run this on something like plugin activation using the register_activation_hook function.

The register_activation_hook requires the path of the file that contains the hook callback and the hook callback function name, you can then add the capabilities to the editor role by using the get_role function to get the role object and then using the add_cap method to add the capabilities.

So what that would look like is you could say editor, get role editor. So that’s the role that exists in the database. And then we could say editor add_cap and we want to allow the editor to activate plugins and we want to allow the editor to update plugins.

Adding this code to a plugin and activating the plugin will trigger the activation hook and will update the editor role with a new plugin capabilities.

Let us activate this plugin which will now add those capabilities to the editor role. Let’s create a new editor user, just give it some random details, gonna keep the passwords simple for testing purposes and make it an editor. And if we log out and log in as the editor user, we are able to install, activate and update plugins.

Note that because adding capabilities to a role is a permanent change, you should only do this when the plugin is activated and not on every page load. Additionally, if you want to remove a custom role, it’s a good idea to do so on plugin deactivation using the register_deactivation_hook function.

So let’s look at what that could look like. So the activation deactivation hook function and callback could look like that. And then we would say, get the role. And then we would remove capabilities by saying remove cap and the same capability. And copy paste the update plugins capability. And there’s our plugin deactivation.

This is useful for two reasons. Firstly, you can add and remove capabilities when the plugin is activated and deactivated, which is useful when testing whether the capabilities you’ve set or what you need. Secondly, if the user deactivates your plugin, the capabilities will be removed cleaning up any changes your plugin has made.

Just as it is possible to assign existing capabilities to roles, you can also create your own custom roles and assign capabilities to them. This is useful if you want to create a role that has a specific set of capabilities and you don’t want to use an existing role. For example, let’s say you want to use a role which can only activate an update plugins, say an assistant to the administrator, you can create a new role using the add_role function and assign the activate_plugins and update_plugins capabilities to it.

So what that would look like in the code, let’s grab the activation hook registration and update the callback to custom role. Let’s create the function. And then we will use the role function which requires the role name. all lowercase a human readable string, which should be translated, but we won’t worry about that now. And then an array of capabilities, which are passed in as key value pairs the key being the capability being set and the value being true or false. That then we’ll set activate plugins to true and we will set update plugins to true.

Again, because the new role will be stored in the database, you should only run this code when the plug in is activated and not on every page load. Notice how the array of capabilities includes the read capability. This is because the read capability is required for a user attach to that role to be able to access the dashboard. Regardless of any other capabilities a user has, if they do not have the read capability, they will not be able to access the Dashboard menu in order to perform the specific task that they should be able to. You can also include a deactivation hook to remove the role when the plugin is deactivated, using the Remove role function.

So let’s just steal the deactivation code here. I’ll say remove custom role.

And then we can simply say remove role and pass in the role now.

Because it made some changes to the activation and deactivation hooks now would be a good idea to deactivate and then reactivate the plugin for the role functionality to be updated.

So in our plugins, let’s deactivate this plugin. And then let’s activate.

You can now create a new user with the assistant capability. Then switch users and notice how that all that user can do is manage plugins.

So we’re logged in as admin, go to the users, create a new user and give them the assistant capability And then fill in all the details of the most simple password for testing purposes and create the user and then log out and login as that user. And all we can really manage are the plugins.

For more information on developing user roles and capabilities, see the Roles and Capabilities section of the Plugin developer handbook at developer.wordpress.org.

Happy Coding

Introduction

Hey there, and welcome to Learn WordPress!

In this tutorial, you’ll be learning how to leverage the WordPress user roles and capabilities system.

After a brief introduction to the default WordPress roles and capabilities, how they are created and managed, and how to assign them to users, you will learn how to add capabilities to an existing role, and how to create a new user role and add capabilities to it.

WordPress User Roles and Capabilities

The WordPress user roles and capabilities system is a powerful tool for managing access to your site. It allows for user roles with specific capabilities, and you can then assign those roles to users. This allows you to create a hierarchy of users, with some users having more access than others.

WordPress comes with several default user roles, namely Administrator, Editor, Author, Contributor, and Subscriber.

There is also one additional role, but this is only available in multisite installations, and that’s the Super Admin role.

Each of these roles has a set of capabilities, which are the things that the user can do in a WordPress site. For example, the Administrator role has the capability to manage users, while the Subscriber role does not.

When a new user is created in the WordPress dashboard, they are assigned the Subscriber role by default. You can change this by assigning a different role. Once assigned to a role, the user will have the capabilities that are associated with that role.

You can read up on the full list of default user roles and capabilities in the official WordPress Documentation on Roles and Capabilities.

Roles and Capabilities under the hood

The WordPress user roles and capabilities system is stored in the database during the WordPress installation process. The roles and capabilities are stored as a serialized array as site options the options table, in the user_roles option. The prefix for this option will depend on the table prefix configured in wp-config.php, or if this is a multisite installation. By default, on a single site installation, the prefix will be wp_, so the option name will be wp_user_roles.

If you extract the value of the user_roles option, and unserialize the array, you will see that the array keys are the role names, and the values are arrays of capabilities.

Whenever an authenticated user is attempting to do something, this action is checked against the user’s role capabilities, using the current_user_can function. If the user has the capability to perform the action, they will be allowed to do so. If they do not have the capability, they will be denied access.

Take a look at line 270 of the wp-admin/includes/post.php file. Here you will see that the edit_post capability is checked before a post is edited/update. If the user does not have the edit_post capability for this post, they will be informed that they do not have the required access to edit it.

Assign capabilities to an existing role

Let’s say that you want to allow your editors to be able to do something that only admins can do, maybe install and update plugins. By default, the Editor role does not have the activate_plugins or update_plugins capability.

[Create editor user]

You can add this capability to the Editor role by using the add_cap method of the WP_Role class.

However, doing so will add this capability to the user_roles stored in the database, so it’s recommend to run this on something like plugin activation using the register_activation_hook function.

register_activation_hook( __FILE__, 'wp_learn_add_custom_caps' );
function wp_learn_add_custom_caps() {
    // do something
}

The register_activation_hook requires the path to the file that contains the hook callback, and the hook callback function name.

Then you can add the capabilities to the Editor role by using the get_role function to get the role object, and then using the add_cap method to add the capabilities.

register_activation_hook( __FILE__, 'wp_learn_add_custom_caps' );
function wp_learn_add_custom_caps() {
    // gets the author role
    $role = get_role( 'editor' );
    $role->add_cap( 'activate_plugins' );
    $role->add_cap( 'update_plugins' );
}
  1. First, you should hook into the register_activation_hook action, so that the code is only executed when the WP dashboard is loaded.
  2. Then, you get the role object by using the get_role function. The get_role function takes the role name as a parameter, and returns the role object.
  3. Finally, you use the role’s add_cap method to add the activate_plugins and update_plugins capabilities to the role object.

Adding this code to a plugin, and activating the plugin, triggering the activation hook, will update the Editor role with the new plugin capabilities.

If you switch to an editor user, you will see that the editor user can now update plugins.

[Show how editor can active plugins]

Note that because adding capabilities to a role is a permanent change, you should only do this when the plugin is activated, and not on every page load. Also, if you want to remove a custom role, it’s a good idea to do so on plugin deactivation, using the register_deactivation_hook function.

register_deactivation_hook( __FILE__, 'wp_learn_remove_custom_caps' );
function wp_learn_remove_custom_caps() {
    $role = get_role( 'editor' );
    $role->remove_cap( 'activate_plugins' );
    $role->remove_cap( 'update_plugins' );
}

This is useful for two reasons. Firstly, you can add and remove the capabilities when the plugin is activated and deactivated, which is useful when testing whether the capabilities you’ve set are what you need. Secondly, if the user deactivates your plugin, the capabilities will be removed, cleaning up the changes your plugin has made.

Create a new User Role and assign capabilities to it

Just as it is possible to assign existing capabilities to roles, you can also create your own custom roles, and assign capabilities to them. This is useful if you want to create a role that has a specific set of capabilities, and you don’t want to use an existing role.

For example, lets say you want a user role who can only activate and update plugins, say an assistant to the administrator. You can create a new role, using the add_role function, and assign the activate_plugins and update_plugins capabilities to it.

register_activation_hook( __FILE__, 'wp_learn_add_custom_role' );
function wp_learn_add_custom_role() {
    add_role(
        'assistant',
        'Assistant',
        array(
            'read'         => true,
            'activate_plugins'   => true,
            'update_plugins' => true,
        ),
    );
}

Again, because the new role will be stored in the database, you should only run this code when the plugin is activated, and not on every page load.

Notice how the array of capabilities includes the read capability. This is because the read capability is required for a user to be able to access the dashboard. Regardless of any other capabilities a user has, if they do not have the read capability, they will not be able to access the dashboard menu, in order to perform a specific task they should be able to.

You can also include a deactivation hook to remove the role when the plugin is deactivated, using the remove_role function.

register_deactivation_hook( __FILE__, 'wp_learn_remove_custom_role' );
function wp_learn_remove_custom_role() {
    remove_role( 'assistant' );
}

Create a new user, with the Assistant capability. Then switch users, and notice how all that user can do is manage plugins

Summary

For more information on developing user roles and capabilities, see the Roles and Capabilities section of the Plugin developer handbook on developer.wordpress.org.

Happy coding.

Workshop Details