Justin Tadlock

Custom capabilities in plugins and themes

I can probably list a million reasons I think my recent Members plugin is neat. Not only have I deployed it on about five of my own blogs in the last few days, I’ve also started integrating it with some of my other plugins and themes.

One of the features I feel that’s lacking in most plugins and themes is the ability to define custom capabilities to access certain content. This is one of the reasons I’ve developed this plugin.

If you’re a plugin or theme developer and add admin menus, this tutorial should be helpful. What I’ll be showing you is a way to give users of your plugin smarter control over its settings.

Adding an admin menu page the normal way

There are several functions for adding admin menus, which all work basically the same way. I’ll use add_submenu_page() as an example since it’s fairly common.

When adding a page, you’ll use the function like this:

add_submenu_page( $parent_page, $page_title, $menu_title, $capability, $file, $function );

What we’ll be focusing on here is the $capability variable. Typically, this is hardcoded, but we need to be able to change this. So, when writing that code, you should replace $capability with a filter hook:

add_submenu_page( $parent_page, $page_title, $menu_title, apply_filters( 'plugin_name_capability', $capability ), $file, $function );

plugin_name_capability should be something unique to your plugin. Just leave $capability as whatever capability you would normally use. It can now be changed.

Making this change does two important things:

  1. Allows users to change the capability if they want to with a filter.
  2. Allows you to integrate your plugin with the Members plugin.

You can stop reading here and will have done your part in making your plugin more flexible. However, you can offer integration with my Members plugin, which will make it even easier for users to use.

Integrating your plugin/theme with the Members plugin

Here’s where the real neat stuff comes into play. You can run a check to see if the Members plugin is installed. If the plugin is indeed installed, you can create a custom capability just for your plugin’s settings page.

Let’s assume that filter hook was something like this:

apply_filters( 'plugin_name_capability', 'manage_options' );

People without the Members plugin would need the manage_options capability to change the settings for your plugin. To me, that doesn’t sound like a great solution, and it definitely doesn’t offer the site owner much flexibility.

If the Members plugin is installed, we’ll change that capability to something like edit_my_plugin_settings (change to something unique):

if ( function_exists( 'members_plugin_init' ) )
    add_filter( 'plugin_name_capability', 'plugin_name_unique_capability' );

function plugin_name_unique_capability( $cap ) {
    return 'edit_my_plugin_settings';
}

Now, only users of a role with the edit_my_plugin_settings capability will be able to access that plugin’s page.

Adding the capability to the role edit page

You can offer even more integration with the Members plugin if you like. You can add a checkbox to the Edit Role page that allows users to easily select this capability rather than typing it in.

if ( function_exists( 'members_get_capabilities' ) )
    add_filter( 'members_get_capabilities', 'plugin_name_extra_caps' );

function plugin_name_extra_caps( $caps ) {
    $caps[] = 'edit_my_plugin_settings';
    return $caps;
}

Why is all this important?

Imagine running a site with 20 different writers, publishers, administrators, and so on. Some people of that site need specific access to certain things but no access to other things.

For example, a friend and I are both running this site with all these people. The friend doesn’t need access to the WordPress options, but he does need access to your plugin’s options. Those should be controlled by two separate capabilities rather than one.

I created Members to allow site owners to have as much flexibility as possible. But, the plugin itself can only do so much on its own. As developers in the WordPress community, we can make WordPress infinitely flexible by working together, and I’m definitely trying to make it as easy as possible to integrate other plugins with my own.