User Role Generator

Generate a custom WordPress user role: cloned capabilities, the ones you add or take away, a version guard so changes re-apply, and the cleanup on deactivation.

Live output

Enable JavaScript to customise; default output below.

Stored in the database and used in every capability check. Renaming it later strands every user who has it.

WordPress translates role names on output through translate_user_role(), so store it in English.

Live preview user-role.php
<?php
/**
 * The "my_plugin_manager" role.
 */

/**
 * Registers the role, and re-applies it whenever the version changes.
 *
 * Roles are stored in the database, not in code, so editing this file does
 * nothing on a site that already has the role. The version option is what
 * makes a change take effect.
 */
function my_plugin_register_role() {
	$version = '1.0.0';

	if ( get_option( 'my_plugin_role_version' ) === $version ) {
		return;
	}

	remove_role( 'my_plugin_manager' );

	$source = get_role( 'editor' );
	$caps   = $source ? $source->capabilities : array( 'read' => true );

	$grant = array(
		'edit_theme_options',
	);

	foreach ( $grant as $cap ) {
		$caps[ $cap ] = true;
	}

	add_role( 'my_plugin_manager', 'Content Manager', $caps );

	// Administrators do not inherit custom capabilities. Without this they
	// cannot reach anything your own checks guard.
	$administrator = get_role( 'administrator' );

	if ( $administrator ) {
		foreach ( $grant as $cap ) {
			$administrator->add_cap( $cap );
		}
	}

	update_option( 'my_plugin_role_version', $version );
}
add_action( 'init', 'my_plugin_register_role' );

Output is valid and updates as you type.

Pick a role to copy, add the capabilities you need and take off the ones you do not, and the generator writes the registration, the version guard that makes later edits take effect, and the cleanup.

How to use

  1. Choose the role key first. It is stored against every user who gets the role, so renaming it later strands all of them.
  2. Start from the closest core role. Editor minus a few capabilities is almost always less work than building a set from scratch.
  3. Add your own capabilities with a prefix, such as acme_approve_copy. That is what your current_user_can() checks should test, not the role name.
  4. Leave the administrator grant on when you add custom capabilities. Administrators do not inherit them, which is how people lock themselves out of their own settings page.
  5. Bump the role version whenever you change the capability list. Nothing else makes an existing site pick the change up.

Example

A role copied from Editor that can approve copy but cannot delete anything published:

function acme_copy_register_role() {
	$version = '1.2.0';

	if ( get_option( 'acme_copy_role_version' ) === $version ) {
		return;
	}

	remove_role( 'acme_copy_editor' );

	$source = get_role( 'editor' );
	$caps   = $source ? $source->capabilities : array( 'read' => true );

	$caps['acme_approve_copy'] = true;

	unset( $caps['delete_published_posts'] );

	add_role( 'acme_copy_editor', 'Copy Editor', $caps );

	update_option( 'acme_copy_role_version', $version );
}
add_action( 'init', 'acme_copy_register_role' );

The option read is the whole cost on a normal request, which is why init is the safer hook here even though activation looks tidier.

Pitfalls

  • Roles live in the wp_user_roles option, not in your code. Editing the capability list and uploading it changes nothing on a site that already registered the role.
  • add_role() returns null and does nothing when the role already exists. Without the remove-then-add above, your second version never applies.
  • Administrators do not get custom capabilities for free. A screen guarded by acme_approve_copy is invisible to the site owner until you grant it.
  • Capabilities are not roles. Check current_user_can( 'edit_shop_orders' ), never current_user_can( 'acme_shop_helper' ), or a site that renames roles breaks.
  • remove_role() does not touch users. They keep the role name and simply have no capabilities until something registers it again.
  • Registering on activation only means an update that changes the list is never applied, because activation does not run again.
  • Multisite super admins pass every capability check, so a broken capability set can look fine to you and be broken for everyone else.
  • Copying Administrator hands out manage_options, edit_users and plugin installation. It is rarely the role you meant to build.

Compatibility

add_role(), remove_role(), get_role() and WP_Role::add_cap() have been stable since WordPress 3.0, and the capability names used here are core ones. The generated code targets PHP 7.0 and up, and the tool runs entirely in your browser.

Frequently asked questions

Why did my capability change not apply?
The role already exists in the database. Bump the role version so the generated code removes and re-adds it.
Should I register on init or activation?
init with the version guard, unless the role is trivial. It costs one option read and survives updates, which activation does not.
What happens to users when I remove the role?
They keep the role name and lose every capability it carried. Reassign them to another role before removing it if they still need access.
Do I need to grant custom capabilities to administrators?
Yes, unless you also check manage_options. Core only gives administrators the capabilities core knows about.
How do I map capabilities to a custom post type?
Set capability_type and map_meta_cap on the post type, then add the resulting names here. Those names are what core will check.

From the people who built this tool

WP Adminify

The WordPress admin, rebuilt: a dashboard worth looking at, menu and column control, a real file manager and the login page your client sees.

See WP Adminify Free version on WordPress.org

Weekly drops

New tools, when there are new tools

One email when something worth using ships. No schedule to fill, so no filler.

Your address goes nowhere else, and one click unsubscribes.