Role & Capability Generator
Build a custom role and its capability map, with a versioned migration and a cleanup routine that reassigns users before removing it.
The role
shop_editor starts from author and ends with 10 capabilities, including 2 custom. Version 1 is re-applied on admin_init when it changes.
Capabilities
10 granted
Reading and dashboard
Posts
Pages and media
Site management
Also grant to existing roles
administrator
Versioned migration
Re-applies the map on admin_init whenever the version number changes.
Cleanup routine
Reassigns affected users, then removes the role and its option.
<?php // Generated with WP CodeKit — powered by GrowQuest (https://growquest.io). /** * Plugin Name: Shop Editor * Description: Adds the shop_editor role and its capabilities. * Version: 1.0.1 * Requires PHP: 7.4 * Text Domain: acme */ defined( 'ABSPATH' ) || exit; /** * The capability map for this role. * * @return array */ function acme_role_caps() { return array( 'read' => true, 'level_0' => true, 'edit_posts' => true, 'delete_posts' => true, 'publish_posts' => true, 'upload_files' => true, 'edit_published_posts' => true, 'delete_published_posts' => true, 'edit_briefs' => true, 'publish_briefs' => true, ); } /** * Create or update the role. * * add_role() does nothing when the role exists, so changing the map above * has no effect on a site that already ran this. Bumping the version does. */ function acme_install_roles() { $role = get_role( 'shop_editor' ); if ( ! $role ) { add_role( 'shop_editor', _x( 'Shop Editor', 'user role', 'acme' ), acme_role_caps() ); } else { foreach ( acme_role_caps() as $cap => $grant ) { $role->add_cap( $cap, (bool) $grant ); } } $extra_roles = array( 'administrator' ); foreach ( $extra_roles as $slug ) { $other = get_role( $slug ); if ( ! $other ) { continue; } foreach ( array( 'edit_briefs', 'publish_briefs' ) as $cap ) { $other->add_cap( $cap ); } } update_option( 'acme_roles_version', 1 ); } /** * Re-apply the map whenever the version changes. */ function acme_maybe_install_roles() { if ( (int) get_option( 'acme_roles_version', 0 ) === 1 ) { return; } acme_install_roles(); } add_action( 'admin_init', 'acme_maybe_install_roles' ); register_activation_hook( __FILE__, 'acme_install_roles' ); /** * Remove the role, moving anyone who had it somewhere safe first. * * remove_role() on its own leaves those users with no role at all. */ function acme_remove_roles() { $users = get_users( array( 'role' => 'shop_editor', 'fields' => 'ID' ) ); foreach ( $users as $user_id ) { $user = new WP_User( $user_id ); $user->remove_role( 'shop_editor' ); if ( ! $user->roles ) { $user->add_role( 'subscriber' ); } } remove_role( 'shop_editor' ); foreach ( array( 'administrator' ) as $slug ) { $other = get_role( $slug ); if ( ! $other ) { continue; } foreach ( array( 'edit_briefs', 'publish_briefs' ) as $cap ) { $other->remove_cap( $cap ); } } delete_option( 'acme_roles_version' ); } // Call acme_remove_roles() from uninstall.php — not on deactivation, // or a plugin update would strip everyone's access.