Creating a Custom Role with Specific Capabilities for a Custom Post Type in WordPress

In this article, I will guide you through creating a custom role in WordPress with specific capabilities to manage a custom post type.

1. Create a Custom Post Type with Custom Capabilities

To create a custom post type, you'll need to define the custom capabilities it requires. We'll include three important arguments: capability_type, map_meta_cap, and capabilities. Here's an example of creating a custom post type for books:

function youbou_register_cpt() {

    $labels = array(
        'name'                  => __( 'Book', 'youbou_textdomain' ),
        'singular_name'         => __( 'Books', 'youbou_textdomain' ),
        /**
         * Full list of available labels can be found here:
         * https://developer.wordpress.org/reference/functions/get_post_type_labels/
         */
    );

    $args = array(
        "label"                 => __( 'Books', 'youbou_textdomain' ),
        "labels"                => $labels,
        "description"           => "",
        "public"                => true,
        "has_archive"           => true,
        "show_in_menu"          => true,
        "capability_type"       => "youbou_book",
        "map_meta_cap"          => true,
        'capabilities'          => array(
			'read'                      => 'read',
			'edit_post'                 => 'edit_youbou_book',
			'edit_posts'                => 'edit_youbou_books',
			'edit_others_posts'         => 'edit_others_youbou_books',
			'publish_posts'             => 'publish_youbou_books',
			'read_post'                 => 'read_youbou_book',
			'read_private_posts'        => 'read_private_youbou_books',
			'delete_post'               => 'delete_youbou_book',
			'delete_posts'              => 'delete_youbou_books',
			'delete_private_posts'      => 'delete_private_youbou_books',
			'delete_published_posts'    => 'delete_published_youbou_books',
			'delete_others_posts'       => 'delete_others_youbou_books',
			'edit_private_posts'        => 'edit_private_youbou_books',
			'edit_published_posts'      => 'edit_published_youbou_books',
        )
        /**
         * Full list of available arguments can be found here:
         * https://developer.wordpress.org/reference/functions/register_post_type/#parameters
         */
    );

    register_post_type( 'youbou_book', $args );
}
add_action( 'init', 'youbou_register_cpt' );

2. Add a Custom Role

To add a custom role with the capabilities you defined for the custom post type, you can use the following code in your plugin's activation hook:

function youbou_active_plugin() {

    $custom_roles = array(
        'read'							=> true,
		'edit_youbou_book'				=> true,
		'edit_youbou_books' 			=> true,
		'edit_others_youbou_books' 		=> true,
		'publish_youbou_books' 			=> true,
		'read_youbou_book' 				=> true,
		'read_private_youbou_books'		=> true,
		'delete_youbou_book' 			=> true,
		'delete_youbou_books' 			=> true,
		'delete_private_youbou_books'	=> true,
		'delete_published_youbou_books'	=> true,
		'delete_others_youbou_books'	=> true,
		'edit_private_youbou_books'		=> true,
		'edit_published_youbou_books'	=> true
    );

    add_role( 'youbou_custom_role', 'My Custom Role', $custom_roles );
}
register_activation_hook( __FILE__, 'youbou_active_plugin' );

Note: WordPress will save our roles in the database, so for that I used register_activation_hook.

3. Add the Capabilities to Admin

If you want to grant the admin the same capabilities as the custom post type, you can add the following code within the youbou_active_plugin function:

$admin_role     = get_role( 'administrator' );
$custom_roles   = array(
    'edit_youbou_book',
    'edit_youbou_books',
    'edit_others_youbou_books',
    'publish_youbou_books',
    'read_youbou_book',
    'read_private_youbou_books',
    'delete_youbou_book',
    'delete_youbou_books',
	'delete_private_youbou_books',
	'delete_published_youbou_books',
	'delete_others_youbou_books',
	'edit_private_youbou_books',
	'edit_published_youbou_books'
);

foreach ( $custom_roles as $role ) {
    $admin_role->add_cap( $role );
}

4. Remove the Custom Role

To ensure clean-up when your plugin is deactivated, you can remove the custom role and its associated capabilities using the following code:

function youbou_deactive_plugin() {

    remove_role( 'youbou_custom_role' );

    $admin_role     = get_role( 'administrator' );
    $custom_roles   = array(
        'edit_youbou_book',
		'edit_youbou_books',
		'edit_others_youbou_books',
		'publish_youbou_books',
		'read_youbou_book',
		'read_private_youbou_books',
		'delete_youbou_book',
		'delete_youbou_books',
		'delete_private_youbou_books',
		'delete_published_youbou_books',
		'delete_others_youbou_books',
		'edit_private_youbou_books',
		'edit_published_youbou_books'	   
    );

    foreach ( $custom_roles as $role ) {
        $admin_role->remove_cap( $role );
    }
}
register_deactivation_hook( __FILE__, 'youbou_deactive_plugin' );