Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I've got a custom post type that I want to allow a specific user role to add posts to, however they must not be able to read posts from others.

Here's my custom post type code:

register_post_type('product', array(
    'labels'                => create_post_type_labels('Product'),
    'public'                => TRUE,
    'query_var'             => TRUE,
    'rewrite'               => array('slug' => 'products', 'with_front' => FALSE),
    'capability_type'       => 'directory',
    'capabilities'          => array(
        'edit_post'         => "edit_directory",
        'read_post'         => "read_directory",
        'delete_post'       => "delete_directory",
        'edit_posts'        => "edit_directorys",
        'edit_others_posts'     => "edit_others_directorys",
        'publish_posts'       => "publish_directorys",
        'read_private_posts'    => "read_private_directorys",
        'delete_posts'        => "delete_directorys",
        'delete_private_posts'    => "delete_private_directorys",
        'delete_published_posts'  => "delete_published_directorys",
        'delete_others_posts'   => "delete_others_directorys",
        'edit_private_posts'    => "edit_private_directorys",
        'edit_published_posts'    => "edit_published_directorys"
    ),
    'supports'              => array('title', 'author'),
    'has_archive'           => TRUE
));

And here's a screenshot of the role permissions:

enter image description here

The problem I'm having is my directory contributor user can still see the posts from the other users.

Can anyone spot an error in the way I am doing things here?

share|improve this question
    
First you're not "doing things here", but clicking together stuff with a plugin - this is not the default admin interface. Second, you're missing the mapping of meta caps IIRC. –  kaiser Dec 4 '13 at 1:08
    
Semantics aside, I had used code to replicate the capabilities set in this plugin. However I didn't realise I needed to make the meta capabilities unless I wanted to do something against the default. After the mapping code from here (justintadlock.com/archives/2010/07/10/…) it now works as desired. Thanks Kaiser, want to add that as an answer? –  Ben Everard Dec 4 '13 at 13:48
    
Ben, I added you a more in depth explanation that works without some bogus filter callback - no idea how he got on that one. But for the future: Please make your questions more detailed, stuff all the needed info inside (plugin, anyone?) and show your efforts in code. –  kaiser Dec 4 '13 at 15:31
    
Any progress? .. –  kaiser Dec 12 '13 at 0:24
    
@kaiser Damn... completely forgot to update you, on it now :-) –  Ben Everard Dec 12 '13 at 10:57

1 Answer 1

up vote 1 down vote accepted

The problem

The problem is, that you have a custom capability_type. This means, that this post type will be handled differently from default post types, that have a capability type of post: Users need to be granted access to this capabilities. Important thing here: This is a good decision.

Foundation

What you're missing is mapping the capabilities to their corresponding meta capabilities. A short explanation straight from Codex:

edit_post, read_post, and delete_post - These three are meta capabilities, which are then generally mapped to corresponding primitive capabilities depending on the context, for example the post being edited/read/deleted and the user or role being checked. Thus these capabilities would generally not be granted directly to users or roles.

Then there're the other 4 primitive capbilities: edit_posts, edit_others_posts, publish_posts and read_private_posts. All those (7 in total) caps are assigned in the capabilities array and checked on various locations in core.

But then there're another 7 capabilities that are not checked against, but only mapped inside map_meta_cap(). When you look at the source of map_meta_cap(), then you'll see 17 cases for the switch in total. Don't be confused by that, as not everything is related to posts, but to plugins activation, users and other stuff.

Now the core function map_meta_caps() checks which type of cap is checked, then starts filling an array of capabilities. Then at the end the following is returned:

return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );

Now let's take a look at the core registration process of post types: map_meta_cap is NULL per default and if not explicitly set, it's FALSE.

And when we look at a user capability check with the has_cap() function, we can see that map_meta_cap() will be called to retrieve all needed capabilities and then it will be looped through and checked against the resulting capabilities from the mapped caps.

The rule

If you assign a capability_type, you better set map_meta_cap to TRUE.

share|improve this answer
1  
Thank you @kaiser, I didn't realise I had to map the custom capabilities, after I had done this the user permissions behaved themselves. –  Ben Everard Dec 12 '13 at 10:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.