简体   繁体   中英

How to limit a new user role to access only regular posts, not custom post types?

We're trying to add a new user role called 'post_editor' that can only access Wordpress' default posts, not 2 custom post types we have named 'content_blocks' and 'slides'.

We've been able to achieve this through the plugin User Role Editor but we're trying to not add another plugin.

Here is what we have tried. In each case it creates the new user role but they can continue to see, edit, and publish the 2 custom post types of 'content_blocks' and 'slides'.

How do we prevent this user role from accessing those 2 custom post types?

// Attempt 1

  add_action( 'admin_init', 'add_role_post_editor' );

  function add_role_post_editor(){
    global $wp_roles;
    if( get_role( 'post_editor' ) == NULL){
        $cap = array(
            'edit_posts' => true,
            'edit_others_posts' => true,
            'edit_published_posts' => true,
            'read' => true,  
            'create_content_blocks' => false,
            'delete_content_blocks' => false,
            'edit_content_blocks' => false,
            'edit_slides' => false,
            'create_slides' => false,
            'delete_slides' => false,
          );
        add_role( 'post_editor', 'Post Editor', $cap );
     }
// Attempt 2

  add_action( 'admin_init', 'add_role_post_editor' );

  function add_role_post_editor(){
    global $wp_roles;
    if( get_role( 'post_editor' ) == NULL){

        $cap = array(
            'edit_posts' => true,
            'edit_others_posts' => true,
            'edit_published_posts' => true,
            'read' => true
          );
        add_role( 'post_editor', 'Post Editor', $cap );

        $role = get_role( 'post_editor' );

        $role->remove_cap( 'create_content_blocks');
        $role->remove_cap( 'delete_content_blocks' );
        $role->remove_cap( 'edit_content_blocks' );
        $role->remove_cap( 'edit_others_content_blocks' );
        $role->remove_cap( 'edit_published_content_blocks' );
        $role->remove_cap( 'publish_content_blocks');
        $role->remove_cap( 'read_slides' );
        $role->remove_cap( 'edit_slides' );
        $role->remove_cap( 'edit_others_slides' );
    }
   }

Is the issue that when we register the custom post types we have to also register these capabilities too, otherwise they are not available for us to add or remove from user_roles?

This might point you in the right direction.

First of all, you should fix how you update the user's roles and capabilities. These are stored in the database very much unlike a custom post type which is simply registered at runtime. If you are managing user roles or caps with custom code I recommend not using a plugin to do the same as this has not worked out well for me in the past.

There are two general approaches.

  1. Give the user no capabilities at all except for 'read' when you register the user role, and then use map_meta_cap to give them only the things they need.

  2. Give the user more capabilities than they need when you register the role and then use map_meta_cap to try to take things away.

In my experience, #1 works best , but the code below is much closer to #2.

Furthermore, I think that the 'edit_posts' capabilities actually give the user more than what it sounds like. You'll want to read some docs on caps for more info.

// update this to re-init caps which are stored in DB
$custom_user_role_version = "1.1";

if ( $custom_user_role_version !== get_option( "custom_user_role_version" ) ) {
    update_option( "custom_user_role_version", $custom_user_role_version );

    $r = 'post_editor';

    remove_role( $r );
    add_role( $r, [
        'edit_posts' => true,
        'edit_others_posts' => true,
        'edit_published_posts' => true,
        'read' => true,
        // whether or not these do anything is dependant upon how the custom post type is registered
        // and what we put inside of 'map_meta_cap'. Even though we say false here, it's possible
        // that it does not do anything.
        'create_content_blocks' => false,
        'delete_content_blocks' => false,
        'edit_content_blocks' => false,
        'edit_slides' => false,
        'create_slides' => false,
        'delete_slides' => false,
    ]);
}

Now we hook onto 'map_meta_cap'. This filter is actually just the last line of a function with the same name. You should read the function to see the options for each of the input parameters. You will have to do some research and some testing to complete the problem. Reading the code in the function will also give you some insight in how the parameters of register_post_type work in regards to meta capabilities.

function is_post_editor( $user ){
    return $user instanceof WP_User && in_array( 'post_editor', $user->roles );
};

/**
 * @see map_meta_cap
 */
add_filter( 'map_meta_cap', function( $caps, $cap = '', $user_id = null, $args = []  ){

    // can return this to allow an action after authenticating the logged in user
//    $caps_to_allow = [
//        'exist'
//    ];

    switch( $cap ) {
        case 'edit_post':

            if ( in_array( get_post_type( $args[0]), [ 'content_blocks', 'slides' ] ) ){

                if ( is_post_editor( get_user_by( 'ID', $user_id ) ) ) {

                    // I think pushing 'do_not_allow' to $caps will also work.
                    return [
                        'do_not_allow'
                    ];
                }
            }

            break;
        case 'read_post':

            // you might need something here too.
            break;
    }

    // the $caps that the user must have to perform the thing that requires $cap
    return $caps;
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM