114 Responses

  1. Andrew Nacin
    Andrew Nacin Published |

    Nice write-up — beat me to it. We’re probably going to implement opt-in mapping in 3.1.

    Just a note, if you do give a role a meta capability, the sky won’t entirely fall on your head, assuming you have the underlying mapping code. When you return $caps, as long as the meta capability isn’t in there (which it should never be, under a typical mapping routine), then it doesn’t matter if the role/user has it, because it won’t be checked.

    Of course, it’s correct practice to stick to giving roles and users the primitive capabilities instead.

    Reply
  2. Saad Bassi
    Saad Bassi Published |

    Another awesome article as usual. I just love how much I have learnt from you. Thanks a lot for all these tuts Justin. You Rock

    Reply
  3. paul
    paul Published |

    Is it possible to limit an author to see only his posts in the backend?

    Reply
  4. shawn
    shawn Published |

    +1 on paul’s question.

    It’s rather confusing when you have hundreds of authors for them to have to sort through all the other users posts (custom) in order to find their own articles to edit.

    How is this done?

    Reply
  5. Andrew
    Andrew Published |

    Like Saad, I also love reading your blog because of all these tutorials you’re posting that’s easy to understand and follow. Looking forward to more of your tutorials. More Power!

    Reply
  6. imarvic
    imarvic Published |

    This information has been genuinely clearly penned, and it also has a great many interesting facts. I loved your professional manner of composing the posting. You have definitely made the idea easy so that i can fully grasp.

    Reply
  7. Koty
    Koty Published |

    This information has been interesting.
    Thanks ;)

    Reply
  8. Steve Marino
    Steve Marino Published |

    Thanks a lot, not just for this but for the rest of your tutorials. Really is a Wordpress For Dummies and this particular dummy if very grateful.

    Reply
  9. kosaidpo
    kosaidpo Published |

    hi great content ive been readin your articles lately got nethin to say except great …

    im just wondering how i can give users the right to edit only a certain custum post type and not standard ones too any thoughs

    and tnx for ur great articles once again

    Reply
  10. Rick
    Rick Published |

    Hi Justin,

    Excellent site. I have been reading through and utilizing your articles for quite a few months and would like to say thanks for providing your insight and skill for our benefit.

    The issue I am facing is that, logged in as admin (non-multisite), I am not able to edit custom post types created by wp_insert_post(), regardless of the capability_type and capabilities settings. I can, however, create and edit a post of custom type through the admin interface, but only when capability_type is post, and capabilities is not defined. In fact, when capability_type or capabilities are defined, the custom post types are not displayed in the admin interface. The map_meta_cap function appears to be the solution, but I have not had any success using it to solve this issue. I have also read the trac topics with no success.

    My goal is similar to, kosaidpo, in that I need to have a custom post type visible and editable to only the post author, and the necessary administrative roles.

    Are there specific idiosyncrasies I am missing? I appreciate any insight you or your readers can offer. I know that this issue is most likely due to pilot error. :-]

    Thanks again for your contributions!

    Reply
    1. Fabio
      Fabio Published |

      Hello
      I have your same problem, do you have resolved anyway?
      I have follow at line tutorials but when I add capabilities to my custom type I am not able to publish and see post of defined custom type.
      How can be fixed?
      Thanks

      Reply
  11. Justin Tadlock — Jan Boddez
    Justin Tadlock — Jan Boddez at |
  12. karim
    karim Published |

    Thanks a lot, not just for this but for the rest of your tutorials. Really is a Wordpress For Dummies and this particular dummy if very grateful.

    Reply
  13. Arti
    Arti Published |

    Really appreciate the info you provide Justin. Thanks a lot.

    Reply
  14. Sammy
    Sammy Published |

    Thanks for sharing this. Also, the hack with regards to authors only seeing their posts gets a huge thumbs up.

    Reply
  15. Aris
    Aris Published |

    This can maybe help…

    Map Cap: “Install this plugin to control which roles can publish, edit and delete posts of each custom type.”

    http://wordpress.org/extend/plugins/map-cap/

    Not tested.

    Reply
  16. Helen Hou
    Helen Hou Published |

    THANK YOU for this. It finally allowed me to figure out why I couldn’t view single posts of a custom post type unless I was logged in and fix it. However, a note: I am using Role Scoper (1.2.8 Beta 5, which works with CPTs on a multisite install) and actually mapping the capabilities using map_meta_cap broke the permissions I was setting using RS. I can still assign roles just fine with RS. In my case, I am assigning a single person to a single post for the most part, so I haven’t done too much experimenting, but it’s worth noting.

    Reply
  17. مصطفى
    مصطفى Published |

    THANK YOU for this. It finally allowed me to figure out why I couldn’t view single posts of a custom post type unless I was logged in and fix it. However, a note: I am using Role Scoper (1.2.8 Beta 5, which works with CPTs on a multisite install) and actually mapping the capabilities using map_meta_cap broke the permissions I was setting using RS. I can still assign roles just fine with RS. In my case, I am assigning a single person to a single post for the most part, so I haven’t done too much experimenting, but it’s worth noting.

    Reply
  18. Mindfriction
    Mindfriction Published |

    Hi

    How would I make the map meta function be more generic and work with multiple custom post types?

    Great tutorials by the way – i’ve bookedmarked your site now :)

    Reply
    1. Cristiano
      Cristiano Published |

      I have the same quastion!!!
      Thanks Justin for your excelent posts!

      Reply
  19. Alison Barrett
    Alison Barrett Published |

    Justin, thanks for the awesome tutorial. This really helped me wrap my head around the way capabilities work, which had previously seemed magical and mysterious to me.

    I’m working on a school website where parents can log in and edit their own students. The students are custom post types, the parents are users. The problem I’m running into is that students need to be associated with more than one parent, I can’t use author-based capabilities to limit their access to students in general. I’m stuck either blocking edit capabilities for all students or allowing them for all students.

    I have parents attached in a post meta field by user ID. I’ve tried this in the IF statements in your code:

    in_array($user_id, get_post_meta($post->ID, ‘parent’))

    Using that instead of $post->post_author isn’t working. Any advice? I know this is a complicated question, but I’ve been working on this for a while and I’m completely stuck.

    Reply
    1. Paul Novitski
      Paul Novitski Published |

      Alison, did you find a solution to this problem of wanting more than one user with permissions to edit one post?

      Just musing: creating a unique new role for each student and assigning that student’s parents to that role sounds ridiculous but might work if it didn’t gum up the works~

      Reply
  20. nomadone
    nomadone Published |

    Really great articles on Custom Post Types Justin, we really appreciate it. Does anyone know whether it’s via code possible to force textarea meta fields to use a wysiwyg editor instead of just a plain text editor.

    I noticed some meta box plugins have implemented this but so far haven’t found any reference to achieving this manually.

    Reply
  21. Richard
    Richard Published |

    Justin,

    You say that you’re dealing with the following three meta capabilities: edit_post delete_post read_post
    What other meta capabilities are there?
    The codex doesn’t give any information on edit_post delete_post read_post
    Why are these capabilities so important?

    Richard

    Reply
  22. ErisDS
    ErisDS Published |

    Just wanted to drop by and say THANK YOU for this post (and the Members plugin).

    I am currently having my first dig around the CPTs, translating some hacked up Pods & I needed tight control over who can edit what. Seems I hadn’t quite grasped the difference between the primitive and meta capabilities and I was just starting to dig around for a way to implement what I needed.

    This post just explained everything I needed in a nutshell, wicked :D

    Reply
  23. Custom Post Types in WordPress « Machina.LA
  24. Lucas
    Lucas Published |

    This was extremely helpful! I was working on this for a week before I stumbled across your site.

    I have a question. How can I set the custom post status back to “Pending Review” automatically if a contributor changes content in a published post?

    Reply
    1. Jonathan Wold
      Jonathan Wold Published |

      I’m working on the same question – haven’t found the answer yet, but I’m diligently searching.

      Reply
      1. bluantinoo
        bluantinoo Published |

        For that i would suggest using “revisionary” plugin.

  25. سـموئل گـرافیک
    سـموئل گـرافیک Published |

    Thanks Jastin. Great Tuts.

    Reply
  26. Tony Zeoli
    Tony Zeoli Published |

    Hey Justin:

    Just trying to figure out why “contributors” is not showing up on a post type we’ve created called “articles”.

    We need to assign current users to posts in “articles.”

    Isn’t “contributors” supposed to appear by default in the post editor once you create the post type?

    Reply
  27. Dan F.
    Dan F. Published |

    Hi Justin,

    great article, really helpful. I have a small (I hope ) problem, though.

    I have a custom post type and a custom role. I want to be able to set the author of a “custom” post to a user with the “custom” role, but the user(s) doesn’t show up in the author dropdown in the editor. No mather what capabilities I give them the dropdown only lists the “Administrators”.

    So the question is do you know a way to force the drop down to list all users?

    Thanks.

    Reply
    1. Rutwick
      Rutwick Published |

      Hi Dan,

      I had emailed you to know if you found any solution for the switch user dropdown not listing custom role users. If you haven’t yet, then a workaround that I wrote may be useful to you.

      Thanks,
      Rutwick

      Reply
  28. Nicolas
    Nicolas Published |

    hi there Justin,
    once again, countless thanks for your great work, and thanks for “sharing your wisdom with us” ;).

    I followed both tutorials (custom posts & this one) to the letter, and I got something quite strange :
    I created a custom content named “company”. I also created a custom role named “agent”. This role is allowed to submit companies but not to publish them.

    The agent guys log in, create new companies and submit them. So far, so good.

    My problem is that even with admin account, I can’t see the companies created by agents : the system behave as if I was like another agent, just granted to see the list entry but not being permitted to modify, or publish it.

    Is there anything to add in this case in the map_meta_cap filter?

    Your answer will be a relief !! Fighting with taht for 2 days…

    Manye thanks again,

    Nicolas

    Reply
    1. Dasha
      Dasha Published |

      Hello Nicolas,

      Have you figured out what was the problem with it? I have similar situation. Would appreciate any tips!

      Thanks,
      Dasha

      Reply
  29. Rhys L. Bartels-Waller
    Rhys L. Bartels-Waller Published |

    Great write up, but I think an update to show the correct use of the map_meta_cap param now 3.1 is out would just finish this off.

    Rhys

    Reply
  30. sebastien
    sebastien Published |

    what’s about map_meta_cap in wp3.1
    what must i use this ?

    Reply
  31. Roles and Capabilities for Custom Post Types | Adventures with Wordpress
  32. Jesse Miles Miller
    Jesse Miles Miller Published |

    I’ve been using a custom post type called ‘listing’(s) for a few months now and I am now adding the capability for Authors to edit their own listings once the Admin has initially set one up. my Listings share the post Categories and a custom taxonomy called Amenities with: ‘taxonomies’ => array(‘category’, ‘amen’)
    I’d like to be able to restrict the Authors to being able to Change their own listing’s Amenities only, but when I change their Role to not allow manage_categories then whatever Categories where there get wiped. Plus the Amenities need to be select only instead of allowing them to create new ones.

    I guess my Question is:
    do I need to setup similar ‘capabilities’ for my taxonomies as well, in order to accomplish this, or just give Authors more access then I’d prefer and hope they don’t screw anything up?

    Reply
  33. Rutwick
    Rutwick Published |

    Hi,
    Need some help. I tried to change the capability type to ‘company’ (its my custom post type) and the capabilities to ‘edit_company’, ‘read_company’ etc. But I’m getting the error message ‘Cheatin uh’?’ ! I just want to allow a user see only his company type custom post. The user is registered with ‘Contributor’ role (this was the only one that I found allows the user to see only his posts!) and I’m removing some of his capabilities through my code. I don’t want him to see the ‘Posts’, ‘Comments’ sections in the dashboard, but removing ‘edit_posts’ and ‘moderate_comments’ also disables the ‘Companies’ custom post section. Any workaround for this?

    Thanks for the article.
    Rutwick

    Reply
  34. Rutwick
    Rutwick Published |

    Hi Justin,
    I figured it out! I hadn’t duplicated all the capabilities and directly added those 3 meta capabilities, so it wasn’t working! Thanks if you were planning to answer my first comment ;)

    (BTW, I commented on your ‘Custom Posts’ post by mistake instead of here cuz I had opened both of them in my browser. Don’t mind!)

    Rutwick

    Reply
  35. Rutwick
    Rutwick Published |

    Hi Justin,
    I’m getting the ‘Cheatin’ uh?’ error message again! Here’s how I’m creating my custom post…

    add_action('init', 'createCompanyCustomPost');
    function createCompanyCustomPost()
    {
    	
    	$labels = array(
    		'name' => _x('Companies', 'post type general name'),
    		'singular_name' => _x('Company', 'post type singular name'),
    		'_new' => _x(' New Company', 'company item'),
    		'_new_item' => __('New Company'),
    		'edit_item' => __('Edit Company'),
    		'new_item' => __('New Company'),
    		'view_item' => __('View Company'),
    		'search_items' => __('Search Companies'),
    		'not_found' =>  __('No Companies Found'),
    		'not_found_in_trash' => __('Nothing found in Trash'),
    		'parent_item_colon' => ''
    	);
     
    	$args = array(
    		'labels' => $labels,
    		'public' => true,
    		'publicly_queryable' => true,
    		'show_ui' => true,
    		'query_var' => true,
    		'rewrite' => true,
    		'capability_type' => 'company',
    		'capabilities'=>array(
    								'publish_posts' => 'publish_companies',
    								'edit_posts' => 'edit_companies',
    								'edit_others_posts' => 'edit_others_companies',
    								'delete_posts' => 'delete_companies',
    								'delete_others_posts' => 'delete_others_companies',
    								'read_private_posts' => 'read_private_companies',
    								'edit_post' => 'edit_companies',
    								'delete_post' => 'delete_companies',
    								'read_post' => 'read_companies'
    								),
    		'hierarchical' => false,
    		'show_in_nav_menus' => true,
    		'show_in_menu'=>true,
    		'exclude_from_search'=>false,
    		'menu_position' => 55,
    		'has_archive'=>true,
    		'supports' => array('title','author','thumbnail','excerpt', 'comments', 'custom-fields')
    	  ); 
     	register_post_type( 'company' , $args);
    }

    Is there something wrong with this?
    Previously, I had the capability type set to posts, but I want to allow certain roles to manage the companies hence needed some custom roles. Please help!

    Thanks,
    Rutwick

    Reply
  36. natty
    natty Published |

    you saved my day man. very helpful tutorial. But thinking how to assign capability for taxonomy…

    Reply
  37. Mike Blouin
    Mike Blouin Published |

    Just curious, wouldn’t a slight change along these lines be preferable?

    function map_meta_caps( $caps, $cap, $user_id, $args ){
                /* List the caps we want to work with /*
                $meta_caps = array('edit_movie', 'delete_movie', 'read_movie');
                if (in_array($cap, $meta_caps)) {
    		$post = get_post( $args[0] );
    		$post_type = get_post_type_object( $post->post_type );
    
    		/* Set an empty array for the caps. */
    		$caps = array();
                    
                    /* If editing, assign the required capability. */
                    if ( strpos(strtolower($cap), 'edit_') !== false ) {
                            if ( $user_id == $post->post_author )
                                    $caps[] = $post_type->cap->edit_posts;
                            else
                                    $caps[] = $post_type->cap->edit_others_posts;
                    }
    
                    /* If deleting, assign the required capability. */
                    elseif ( strpos(strtolower($cap), 'delete_') !== false ) {
                            if ( $user_id == $post->post_author )
                                    $caps[] = $post_type->cap->delete_posts;
                            else
                                    $caps[] = $post_type->cap->delete_others_posts;
                    }
    
                    /* If reading, assign the required capability. */
                    elseif ( strpos(strtolower($cap), 'read_') !== false ) {
                            if ( 'private' != $post->post_status )
                                    $caps[] = 'read';
                            elseif ( $user_id == $post->post_author )
                                    $caps[] = 'read';
                            else
                                    $caps[] = $post_type->cap->read_private_posts;
                    }
                }
                
                //Return the capabilities required by the user
                return $caps;
            }

    This is nice because then all of those if/then statements aren’t processed if the filter is called on meta caps aside from your own (‘edit_movie’ etc..). (Okay, maybe the speed advantages are pretty small, but I guess all in all it could make a difference at the end of the day on a busy blog.) Also, this could be easily expanded if you had multiple custom types to work with, and they all followed pretty much the same capability types.

    But aside from that, thanks alot! I’m finding your site to be a fantastic resource!
    Mike

    Reply
  38. Travis Smith
    Travis Smith Published |

    Justin,

    Is there a way to implement capabilities without a role management plugin? Also, If I implement it as a custom capability type, is there some way I can continue to leave the ‘page’ security class as the default?

    Thanks,

    Reply
  39. David F. Carr
    David F. Carr Published |

    Travis was relaying a question I had. He had asked me to modify my Facebook Tab Manager plugin to have its own capability types. Currently, as part of the custom post type registration I use

    ‘capability_type’ => ‘page’,

    to have the type treated the same as a WordPress page for purposes of user access. This has the advantage of fitting in with the default security scheme of WordPress, where for example author class users can create a post but not a page.

    I understand that using a custom capability type would provide more possibilities for customization, but I want to make sure that if I do make a change I preserve a default security level that makes sense for existing users of the plugin.

    I do have your book, and I’ll try to reread the chapter on capabilities and see if I can figure out a strategy, but thought I should at least try to clarify what my question was.

    Reply
  40. Ayoub
    Ayoub Published |

    I want to thank you for the plugin Members. You’re saving my life

    Reply
  41. Vanessa
    Vanessa Published |

    Thanks for this post. It’s very helpful!

    I was wondering though if it is possible to relate Roles to the visibility of a menu item? For example, if I have a role called “Researchers”, and I wanted to show a page on the menu bar only when a Researcher logs in. Is it possible to do this with either the Member’s plugin or by extending the capabilities? And how would I go about it? Thanks!

    Reply
  42. Bill
    Bill Published |

    Justin, I’ve got your code working … mostly. I would like to make it so that Editors can delete the posts of a certain custom post type, and this is not working. Everything else is, so I wonder if there is a small problem. Do you have any hints?

    Reply
  43. Pete
    Pete Published |

    If I set up a custom post type, how do I format the data input in its own template? If I have “movies” as a custom post type and a field “year”, how can I display that in my custom post type template?

    And one more question: Is it possible to have a custom post type field with the formatting options as in a regular post/page, e.g. bold text, unordered lists etc.?

    Reply
  44. Dasha
    Dasha Published |

    Hello Justin,

    Thank you very much for the tutorial and code.
    I’ve re-read this post many many types and followed your code, however when I add the map_meta_cap filter my admin users still can’t even see the Custom Post Type menu… and I can’t understand why :S

    Is there something you could think of might be wrong?

    Many thanks,
    Dasha

    Reply
  45. Shaun
    Shaun Published |

    Hi Justin, great tutorial as always…
    Just wanted to know if there is a way to similarly hide the CPT’s UI all together, rather then disable particular capabilities? Disabling capabilities is great, but Id like for my clients to not be able to see anything, ie. the entire UI. Is this possible?

    Thanks in advance!
    Best,
    SB

    Reply
    1. Dasha
      Dasha Published |

      Hello Shaun,

      I believe you can do it while registering the actual Custom Post Type, using the one of the following arguments: ‘public’ or ‘show_ui’. Have a look for more explanation at the codex http://codex.wordpress.org/Function_Reference/register_post_type

      Dasha

      Reply
  46. Brian
    Brian Published |

    Quick question,

    I have a custom post type and a custom capability_type defined. I have followed your code and have it working basically the way I want. However, I want to prevent a user from editing a published post (like the standard WordPress ‘post’ post type). I’ve done some reading on edit_published_posts but I’m unable to get that to work. Any clues?

    Reply
  47. Meta_caps and Post_Types | | IF IT IS CREATIVEIF IT IS CREATIVE
  48. Dasha
    Dasha Published |

    Hello Justin,

    Thank you for the tutorial.
    I’m a bit stuck and don’t understand what’s happening. I’ve registered a Custom Post Type as in your code above (copy and paste). So if I understand correctly after I have registered a CPT with capabilities those capabilities should came up unticked in the Memebers plugin, right? But they don’t :S

    What am I doing wrong?
    I would really appreciate your help as I’ve been stack with it for a while :(

    Many thanks,
    Dasha

    Reply
    1. Dasha
      Dasha Published |

      Hm, just came across this http://wordpress.org/support/topic/anyone-managed-to-get-custom-post-types-capabilities-working/page/2?replies=47#post-1593534

      Maybe it should be added to this current post? :) It was a bit of a mission to find that post..

      Thanks again for the tutorial,
      Dasha

      Reply
  49. arru
    arru Published |

    Thank you Justin for a great article!

    It’s simple to understand but a lot to know. Just saved my day.

    Reply
  50. Erik Teichmann
    Erik Teichmann Published |

    my brain exploded
    then i read this awesome post
    now things work, heck yeah.

    (that was my haiku for you. cheers!)

    Reply
  51. Dave
    Dave Published |

    - disclaimer: noob status -

    Do the custom capabilities need to be plural with an “s”?

    I was hacking around and could not get things to work (I could have triggered something else) and when I changed “edit_thing” to “edit_things” (with an ‘s’) everything started working.

    Is this a correct assumtion? If not, feel free to delete this comment :)

    If so, I suggest you edit the bulleted meta capabilities in your post to be plural. Was getting confused with that and the pluralness in your code samples.

    Reply
  52. Lollo
    Lollo Published |

    Hi justin,

    first of all thanks a lot for all the time you give to us!

    i wasn’t understand why if I declare the capability in my custom post type I can’t see it in my admin! then after a while, my brain is quite slow, i thought that was because i didn’t give to administrator rule that capabilities.

    So the question is… I use Members plugin. Do i have to create (with Add New Capabilities) every capabilities I need? is that the right place to do so? How can i delete a capabilities from Members Plugin?

    thanks a lot for your patience!

    Reply
  53. WPSmith | Registering Custom Post Types
  54. Ciprian
    Ciprian Published |

    Hi Justin,

    Can you please point me in the right direction with one issue i’m experiencing?

    I added a custom capability type, and now i’m trying to add a custom meta box for it. The box is showing along with my fields but the values are not saved into the database.

    This is strange as the same thing works for regular custom post types, but not with this one.

    I guess it’s something related to add_action('save_post', 'save_custommeta_post').

    Thanks a lot,
    Ciprian

    Reply
    1. Pat East
      Pat East Published |

      I’m running into this same issue. I pulled out the custom capabilities and things worked fine again. Has there been a resolution to this issue?

      Reply
      1. Pat East
        Pat East Published |

        Nevermind – I figured out the issue.

        My post saving function was using within it’s authentication script one of the old capability names. Fixed that and it worked beautifully.

  55. Asaf Chertkoff
    Asaf Chertkoff Published |

    Hi, justin.
    thought that maybe you can help with this issue

    if you could try to help me, maybe one of your wishes will come true ;)

    thanks,
    Asaf.

    Reply
  56. Sam
    Sam Published |

    Hello,

    I’ve created a custom post type (vacancies) and used ‘capabilities’ to specify the plural and singular capability names, and I have then set map_meta_cap to true and once the roles are added it all works.

    The first time I read this article was a while back now, the question I have is do we still need to filter the map_meta_cap? or was this written before it worked in WordPress?

    If we don’t any more then what else could we use this code for? cross post type capabilities???

    Many Thanks for the article; it really helped me understand what was going on!

    Reply
  57. Ryan
    Ryan Published |

    Hi Justin.

    First off thanks so much for all the useful tips found scattered around the net that have assisted me greatly and led me here a while back.

    I have read your blog tuts on meta-capabilities-for-custom-post-types, a-wordpress-forum-plugin-using-custom-post-types, linking-terms-to-a-specific-post and others.

    I am in the planning stages of developing a CMS. I will create CPTs of ‘events’, ‘products’, and ‘support’, and taxonomies of ‘topic’, ‘product type’, ‘event format’ and two others.

    The real issue I need to get my head around is to be able to deliver those different types of content according to which member is logged in – only on the front-end. In other words, there will be content available to everyone (public), and then content only available to Joe Soap, who wont be able to view the content allocated to Jane Doe, but the content could be any of the above type or in any of those taxs.

    None of the ‘members’ need access to admin, while use of custom roles may help. What I’d love to be able to achieve is create a taxonomy “accounts” and do something like ‘if_user_can_[account_term]‘, show content. I don’t know what combination of CPTs (?nested), custom roles & custom tax to employ.

    I know there must be a logical way of achieving this but I keep going round in circles… Any advice?

    Thanks

    Reply
  58. BASTA!
    BASTA! Published |

    To assign specific capabilities to roles, you’re going to need a role management plugin.

    Awwwww it was so close! If only your solution didn’t depend on other plugins…

    Reply
    1. Leo Germani
      Leo Germani Published |
      $role = get_role('editor');
      $role->add_cap('aby_cap_you_like');

      You only need to run this code once. So the register_activation_hook is a good place for it

      Leo,,

      Reply
  59. Lars
    Lars Published |

    Thanks, this works very good. I did pull out some hair when i disabled the capability for admins to edit posts. They didnt need so i thought, why not disable it. But then I couldn’t save my wp_nav_menu’s anymore :)

    Anyhow, with debugging enabled on wordpress 3.3.2 i get the following notice on various places in the admin: Notice: Undefined property: stdClass::$delete_posts in \theme\functions\types\news.php on line 27

    Reply
  60. Leo Germani
    Leo Germani Published |

    Hi Justin,

    Just want to make sure of something.

    Do you really need to pass the “capabilities” option when registering the post type? I believe the capability_type is enough, isnt it? and WordPress will create all capabilities for you using capability_type as the prefix.

    According to the docs you can even pass a plural form:

    'capability_type' => array('movie', 'movies')

    Leo,,

    Reply
  61. Adeel
    Adeel Published |

    hey Justin Tadlock, i m sorry i subjected the wrong person before….i really liked your tutorial for custom fields, i have a question is this possible we can run query on publish or update the custom post page??? like i have made music and when i m adding music posts on publish all fields go into different custom db table…i m not good in db and php but it make sense to me we might have something to make it possible…..can you please help me in this???

    Reply
  62. Marlon
    Marlon Published |

    I create a custom post type

    $labels_resposta = array(
        'name' => _x('Respuestas', 'post type general name'),
        'singular_name' => _x('Respuesta', 'post type singular name'),
        'add_new' => _x('Añadir nueva', 'Respuesta'),
        'add_new_item' => __('Añadir nueva Respuesta'),
        'edit_item' => __('Editar Respuesta'),
        'new_item' => __('Nueva Respuesta'),
        'all_items' => __('Todas Respuestas'),
        'view_item' => __('Ver Respuesta'),
        'search_items' => __('Buscar Respuesta'),
        'not_found' =>  __('No encontró ningún Respuesta'),
        'not_found_in_trash' => __('Ninguna Respuesta encontrada en la basura'), 
        'parent_item_colon' => '',
        'menu_name' => 'Respuestas'
    
      );
      $args_resposta = array(
        'labels' => $labels_resposta,
        'public' => true,
    	'exclude_from_search' => true,
    	'publicly_queryable' => false,
        'show_ui' => true,
    	'menu_position' => 5,
        'rewrite' => array('slug' => 'respuesta'),
        'hierarchical' => false,
        'supports' => array( 'title', 'editor', 'author', 'excerpt', 'comments', 'custom-fields' ),
    	'capability_type' => 'resposta',
    	'capabilities' => array(
    		'publish_posts' => 'publish_respostas',
    		'edit_posts' => 'edit_respostas',
    		'edit_published_posts' => 'edit_published_respostas',
    		'delete_published_posts' => 'delete_published_respostas',
    		'edit_others_posts' => 'edit_others_respostas',
    		'delete_posts' => 'delete_respostas',
    		'delete_others_posts' => 'delete_others_respostas',
    		'read_private_posts' => 'read_private_respostas',
    		'edit_post' => 'edit_resposta',
    		'delete_post' => 'delete_resposta',
    		'read_post' => 'read_resposta',
    	)
      ); 
      register_post_type('resposta',$args_resposta);

    but when I declare parameters `capabilities` and `capability_type` the custom post type isn’t created.

    What is wrong?

    Thanks all!

    Reply
    1. Seth
      Seth Published |

      I’m having the exact same problem. Tried various names. Updates Wordpress. Don’t know why this isn’t working. If I declare ‘capabilities_type’ at all as any other than ‘post’ then the post does not display…

      I have no idea why.

      Reply
  63. Wayne Aretz
    Wayne Aretz Published |

    Thanks for the tutorial. I like others couldn’t see my custom post type in the Admin menu unless I included the Map Meta Cap code you outlined above. However, I am not seeing my Role Capabilities that I defined in the array when I attempt to define a new Role. Any help would be great.

    Thank you.

    Reply
  64. Grant
    Grant Published |

    Justin,
    thanks for the tips. The issue I am running in to is…
    I have a site with a blog and portfolio. The portfolio is set up as a custom post type ‘portfolio’ . I want to allow users to post to the blog but not the portfolio.
    When I give them permission to edit_posts , this also gives them the permission to edit the portfolio because it is a post, although it is a CPT. how can I allow posts but limit CPTs?

    Reply
  65. Casey Wise
    Casey Wise Published |

    Justin, you get a gold star today. I just leveled up in WP. CPTs + custom roles/capabilities was my boss battle which you helped with immensely. I only died 3 times!

    Thanks again dude, have a fine holiday season!

    Reply
  66. Genevieve
    Genevieve Published |

    Hi, Justin–thanks so much for this immensely helpful post! I’ve just run into one little snag that I can’t figure out. I’ve got a custom post type, and a custom user roll set up to access ONLY that post type. I used your instructions in this post give that roll access to the custom post type, and while they are able to create/edit/delete their custom posts as I intended, they can’t assign categories to their post. It seems category assignation is connected to the edit_post permission, and when I assign that to the custom user roll, they can select categories, but then they also have access to other post types, which I don’t want. I used custom taxonomies to create separate category groups for the custom post type. Is there a way to give my custom user roll the ability to assign categories just to their custom post type?

    Reply
  67. brent
    brent Published |

    Any idea why other plugins like “google maps store locator” doesn’t appear as a role in the edit role screen? Is it because members plugin cannot map this plugin. I was hoping to create a specific role for users to be able to edit/post/delete in managing the store locator plugin. Thanks!

    Reply
  68. Josh
    Josh Published |

    Hello Justin, Great write up! This is exactly what I was looking for. I have implemented in one of my sites and I had a question. You mention it up above but not in your code segment, but if I wanted users to be able to movie post, would I need to add a condition for ” if ( ‘publish_movie’ == $cap ) “? In the example I have worked up, users can read and edit my cpt, but when they try to create/publish a new cpt WP just creates a draft and not a published post.

    Thanks in advance for the insight.

    Reply
  69. Seath
    Seath Published |

    Thank YOU Justin!!
    Your post just save me time trying figuring this on my own. With small changes I was able to do what I was going for. So again Thank you.

    Reply
  70. Juan B
    Juan B Published |

    Thanks Justin! This works like a charm. I have a question I’ve been trying to wrap my head around, which I hope you can help with…

    Primarily I would want the behavior that if an author edits a post, although it’s published, the changes get set to pending and the post does not automatically get posted? Is there something I’m missing the my_meta_cap function?

    Thanks.

    Reply
    1. Juan B
      Juan B Published |

      Nevermind, realized I had not mapped capabilities. Once i set those up, everything works like a charm.

      Reply
  71. Aryan
    Aryan Published |

    Hello everyone!
    Capabilities Not working with Custom Post type In 3.5.1.

    Any Idea why?

    Thanks

    Reply
  72. カスタム投稿タイプにオリジナルの権限を設定する方法まとめ | モンキーレンチ
  73. Jon R.
    Jon R. Published |

    Thanks Justin, you really helped me understand custom post types. I’m having a problem in version 3.5.1 though.

    I’ve created a custom post type for recipes:

    register_post_type(
    	'recipes', array(
    		'label' => 'Recipes',
    		'description' => '',
    		'public' => true,
    		'show_ui' => true,
    		'show_in_menu' => true,
    		'map_meta_cap' => false,
    		'capability_type' => 'recipe',
    		'hierarchical' => true,
    		'rewrite' => array(
    			'slug' => ''),
    		'query_var' => true,
    		'exclude_from_search' => false,
    		'menu_position' => 25,
    		'supports' => array(
    			'title',
    			'editor',
    			'custom-fields',
    			'revisions',
    			'thumbnail',
    			'author',
    			'page-attributes',),
    		'taxonomies' => array(
    			'styles',),
    		'labels' => array (
    			'name' => 'Recipes',
    			'singular_name' => 'Recipe',
    			'menu_name' => 'Recipes',
    			'add_new' => 'Add Recipe',
    			'add_new_item' => 'Add New Recipe',
    			'edit' => 'Edit',
    			'edit_item' => 'Edit Recipe',
    			'new_item' => 'New Recipe',
    			'view' => 'View Recipe',
    			'view_item' => 'View Recipe',
    			'search_items' => 'Search Recipes',
    			'not_found' => 'No Recipes Found',
    			'not_found_in_trash' => 'No Recipes Found in Trash',
    			'parent' => 'Parent Recipe',),
    	)
    );

    I’ve also used the meta mapping function you used and replaced every instance of the word movies with recipes. I’ve used the Members plugin to assign the custom capabilities to the correct roles. For some reason though, none of the roles that can see the recipes have the ability to delete them. Every other capability works. I’ve checked to see that delete_recipes is set on the roles and it is.

    Any ideas why this isn’t working?

    Reply
    1. Mark Maskell
      Mark Maskell Published |

      change ‘map_meta_cap’ => false to true

      Reply
      1. sgaddo
        sgaddo Published |

        I have the same problem and even setting ‘map_meta_cap’ => true it’s not working.
        The users having the role to manage completely my custom post type can only add new posts…

        =(
        Any clue?

  74. Meta capabilities for custom post types | Bookmarks
  75. Meta capabilities for custom post types | Bookmarks
  76. Cedric Van Bockhaven
    Cedric Van Bockhaven Published |

    Like some people mentioned here, edit_posts capability appears to be needed to be able to create new posts of the Custom Post Type. Adding edit_posts to the capabilities allows the user to submit new posts however. This piece of code allows you to remove the edit_posts capability, while allowing the creation of new posts of the CPT.

    add_filter('user_has_cap', function ($allcaps, $cap, $args) {
                global $_wp_menu_nopriv, $_wp_submenu_nopriv;
    
                if (@$cap[0] == "edit_posts" && (@$allcaps["edit_ideas"] || @$allcaps["edit_apps"]))
                    unset($_wp_menu_nopriv["edit.php"], $_wp_submenu_nopriv["edit.php"]);
    
                return $allcaps;
            }, 10, 3);

    More info at https://github.com/oSoc13/AppsForX/issues/16

    Reply
  77. Betty
    Betty Published |

    This works for me,

    WP 3.6 and Capability Manager Enhanced plugin: http://wordpress.org/plugins/capability-manager-enhanced/

    Custom Post Type: testimonial

    add_action( 'init', 'register_cpt_testimonials' );
    
    function register_cpt_testimonials() {
    
        $labels = array( 
            'name' => _x( 'Testimonials', 'testimonials' ),
            'singular_name' => _x( 'Testimonial', 'testimonials' ),
            'add_new' => _x( 'Add New', 'testimonials' ),
            'add_new_item' => _x( 'Add New Testimonial', 'testimonials' ),
            'edit_item' => _x( 'Edit Testimonial', 'testimonials' ),
            'new_item' => _x( 'New Testimonial', 'testimonials' ),
            'view_item' => _x( 'View Testimonial', 'testimonials' ),
            'search_items' => _x( 'Search Testimonials', 'testimonials' ),
            'not_found' => _x( 'No Testimonials found', 'testimonials' ),
            'not_found_in_trash' => _x( 'No Testimonials found in Trash', 'testimonials' ),
            'parent_item_colon' => _x( 'Parent Testimonial:', 'testimonials' ),
            'menu_name' => _x( 'Testimonials', 'testimonials' ),
        );
    
        $args = array( 
            'labels' => $labels,
            'hierarchical' => false,
            
            'supports' => array( 'title', 'editor' ),
            
            'public' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'menu_position' => 20,
            
            'show_in_nav_menus' => false,
            'publicly_queryable' => true,
            'exclude_from_search' => false,
            'has_archive' => true,
            'query_var' => true,
            'can_export' => true,
            'rewrite' => true,
    		'capability_type' => 'testimonial',
            'capabilities' => array(
    			'publish_posts' => 'publish_testimonials',
    			'edit_posts' => 'edit_testimonials',
    			'edit_others_posts' => 'edit_others_testimonials',
    			'delete_posts' => 'delete_testimonials',
    			'delete_others_posts' => 'delete_others_testimonials',
    			'read_private_posts' => 'read_private_testimonials',
    			'edit_post' => 'edit_testimonial',
    			'delete_post' => 'delete_testimonial',
    			'read_post' => 'read_testimonial',
            )
        );
    
        register_post_type( 'testimonial', $args );
    }
    
    /**
     * Maps meta capabilities to primitive ones for testimonial post type
     *
     * @ignore
     * @access private
     * @since 1.0
     */
    function testimonial_meta_cap( $caps, $cap, $user_id, $args ) {
    
    	/* If editing, deleting, or reading a testimonial, get the post and post type object. */
    	if ( 'edit_testimonial' == $cap || 'delete_testimonial' == $cap || 'read_testimonial' == $cap ) {
    		$post = get_post( $args[0] );
    		$post_type = get_post_type_object( $post->post_type );	
    
    		/* Set an empty array for the caps. */
    		$caps = array();
    		if($post->post_type!='testimonial')
    			return $caps;
    	}
    
    	/* If editing a testimonial, assign the required capability. */
    	if ( 'edit_testimonial' == $cap ) {
    		if ( $user_id == $post->post_author )
    			$caps[] = $post_type->cap->edit_posts;
    		else
    			$caps[] = $post_type->cap->edit_others_posts;
    	}
    
    	/* If deleting a testimonial, assign the required capability. */
    	elseif ( 'delete_testimonial' == $cap ) {
    		if (isset($post->post_author ) && $user_id == $post->post_author)
    			$caps[] = $post_type->cap->delete_posts;
    		else
    			$caps[] = $post_type->cap->delete_others_posts;
    	}
    
    	/* If reading a private testimonial, assign the required capability. */
    	elseif ( 'read_testimonial' == $cap ) {
    
    		if ( 'private' != $post->post_status )
    			$caps[] = 'read';
    		elseif ( $user_id == $post->post_author )
    			$caps[] = 'read';
    		else
    			$caps[] = $post_type->cap->read_private_posts;
    	}
    
    	/* Return the capabilities required by the user. */
    	return $caps;
    }
    add_filter( 'map_meta_cap', 'testimonial_meta_cap', 10, 4 );
    Reply
  78. James
    James Published |

    As of WP 3.6 all you need is the following to create the capabilities for the post type (the ‘map_meta_cap’ part does what Justin’s add_filter( 'map_meta_cap'… part does, just simpler)

    register_post_type( 'my_custom_post_type',
    		'capability_type' => 'my_custom_post_type',
    		'map_meta_cap' => true,
    	)
    );

    Then the following capabilities will be created, and you just need to add the each one as a capability for the role of your choice.

    read_private_my_custom_post_type
    publish_my_custom_post_type
    edit_my_custom_post_type
    edit_published_my_custom_post_type
    edit_others_my_custom_post_type
    delete_my_custom_post_type
    delete_others_my_custom_post_type

    NOTE: I’m not sure when it was introduced, but Justin never mentions the edit_published_my_custom_post_type cap, without it you will not be able to edit the cpt!! Make sure you add that one as well.

    Thanks Justin!

    Reply
  79. Seth
    Seth Published |

    I have tried this both in a project and in a fresh wordpress local install.. Cannot get it to work. If you remove the “capability_type” declaration ti works. If you put it in it doesn’t. The codex says you need to set map_meta_cap to true. Which I tried. I have tried everything I can think of to get this to work. Any one out there know what I am doing wrong? I have tried the exact code stated above in wordperss 3.7 and it does not work. I have also tried this code here:

    register_post_type( 'bounty_product', array(
    
    'labels' => array(
    
    'name' => 'Products',
    
    'singular_name' => 'Product',
    
    'add_new' => 'Add New',
    
    'add_new_item' => 'Add New Product',
    
    'edit' => 'Edit',
    
    'edit_item' => 'Edit Product',
    
    'new_item' => 'New Product',
    
    'view' => 'View',
    
    'view_item' => 'View Product',
    
    'search_items' => 'Search Products',
    
    'not_found' => 'No Products found',
    
    'not_found_in_trash' => 'No Products found in Trash',
    
    'parent' => 'Parent Product'
    
    ),
    
    'description' => 'Used for the product review section',
    
    'public' => true,
    
    'capability_type' => 'product',
    
    'capabilities' => array(
    
    'publish_posts' => 'publish_product',
    
    'edit_posts' => 'edit_product',
    
    'edit_others_posts' => 'edit_others_product',
    
    'delete_posts' => 'delete_product',
    
    'delete_others_posts' => 'delete_others_product',
    
    'read_private_posts' => 'read_private_product',
    
    'edit_post' => 'edit_product',
    
    'delete_post' => 'delete_product',
    
    'read_post' => 'read_product',
    
    ),
    
    'show_in_menu' => true,
    
    'menu_position' => 20,
    
    'has_archive' => true,
    
    'supports' => array( 'title', 'editor', 'comments', 'thumbnail', 'custom-fields' ),
    
    ));
    Reply
    1. Seth
      Seth Published |

      Screwed up code so here we go again

      I have tried this both in a project and in a fresh wordpress local install.. Cannot get it to work. If you remove the “capability_type” declaration ti works. If you put it in it doesn’t. The codex says you need to set map_meta_cap to true. Which I tried. I have tried everything I can think of to get this to work. Any one out there know what I am doing wrong? I have tried the exact code stated above in wordperss 3.7 and it does not work. I have also tried this code here:

      register_post_type( 'bounty_product', array(
      
      'labels' => array(
      
      'name' => 'Products',
      
      'singular_name' => 'Product',
      
      'add_new' => 'Add New',
      
      'add_new_item' => 'Add New Product',
      
      'edit' => 'Edit',
      
      'edit_item' => 'Edit Product',
      
      'new_item' => 'New Product',
      
      'view' => 'View',
      
      'view_item' => 'View Product',
      
      'search_items' => 'Search Products',
      
      'not_found' => 'No Products found',
      
      'not_found_in_trash' => 'No Products found in Trash',
      
      'parent' => 'Parent Product'
      
      ),
      
      'description' => 'Used for the product review section',
      
      'public' => true,
      
      'capability_type' => 'product',
      
      'capabilities' => array(
      
      'publish_posts' => 'publish_product',
      
      'edit_posts' => 'edit_product',
      
      'edit_others_posts' => 'edit_others_product',
      
      'delete_posts' => 'delete_product',
      
      'delete_others_posts' => 'delete_others_product',
      
      'read_private_posts' => 'read_private_product',
      
      'edit_post' => 'edit_product',
      
      'delete_post' => 'delete_product',
      
      'read_post' => 'read_product',
      
      ),
      
      'show_in_menu' => true,
      
      'menu_position' => 20,
      
      'has_archive' => true,
      
      'supports' => array( 'title', 'editor', 'comments', 'thumbnail', 'custom-fields' ),
      
      ));
      Reply
  80. Role Based Help Notes | Justin's Blog
    Role Based Help Notes | Justin's Blog at |
  81. Hathija
    Hathija Published |

    I want to create a Custom Post Type and allow every users to publish this CPT (Admin, Editors, Subscribers). I follow this tutorial but it doesn’t work for Subscribers. I have CPT shown in the Admin Menu but after it says “You do not have sufficient permissions to access this page.. I also tried to use several user management plugins (Members, User Role Editor, Meta Cap…..) but it doesn’t work :(

    I can’t believe that i have been working on this since 4days !

    Any clues ?

    Reply

Leave a Reply

By submitting a comment here you grant this site a perpetual license to reproduce your words and name/Web site in attribution.

Please use your real name or a pseudonym (i.e., pen name, alias, nom de plume) when commenting. If you add your site name, company name, or something completely random, I'll likely change it to whatever I want.

css.php