Is it possible to remove all references to 'edit' or 'add' from a particular post type on its post list display screen in admin?

So basically what I need is that for this post type, all roles defined, whatever they are, can only view a list of these posts, and not do anything with them except trash them. So that means removing the 'Add New myposttype' button, as well as the 'Edit | Quick Edit' links beneath each entry of the list posts screen.

In my custom post type these are my capability related settings:

        'capability_type' => array('food_item','food_items'),
        'map_meta_cap'    => true,
        'capabilities' => array(
                        'publish_posts' => 'publish_food_items',
                        'edit_posts' => 'edit_food_items',
                        'edit_others_posts' => 'edit_others_food_items',
                        'delete_posts' => 'delete_food_items',
                        'delete_others_posts' => 'delete_others_food_items',
                        'read_private_posts' => 'read_private_food_items',
                        'edit_post' => 'edit_food_item',
                        'delete_post' => 'delete_food_item',
                        'read_post' => 'read_food_item'

In my plugin init function, I'm adding the following:

    global $wp_roles;
    $wp_roles->add_cap( 'administrator', 'edit_food_item' );
    $wp_roles->add_cap( 'administrator', 'edit_food_items' );

At this point the administrator just cannot see the food items entry in the menu at all.

3 Answers 3


For say the 'moomin' post type, when defining the custom post type specify its 'capability_type' as 'moomin'.

This will give you the 'capabilities' edit_moomin' etc which you can then remove from individual roles, e.g.:

global $wp_roles;
// remove capability edit_moomin from role editor
$wp_roles->remove_cap( 'editor', 'edit_moomin' );

@Simon Forster claims readonly posts IS possible, if so then this should do the job:

$wp_roles->add_cap( 'editor', 'read_moomin' );
  • I would like that all roles would not have the capability to add a post of this CPT, else they have all capabilities. How do I do that?
    – urok93
    Commented Sep 5, 2012 at 9:09
  • By repeating the code for each role, there's a list of roles in the codex, e.g. Subscriber etc There's no 'All' or 'Everyone' role
    – Tom J Nowell
    Commented Sep 5, 2012 at 9:16
  • When I tried the code for the administrator role, I couldn't access the CPT listing of posts either, and I just need to prevent adding of new posts, not disable viewing altogether.
    – urok93
    Commented Sep 5, 2012 at 9:37
  • That's a symptom of how WordPress roles work unfortunately. There's no 'read only' edit page screen in the admin area, that's what the frontend is for, as such it immediately makes the edit pages listing somewhat unusable. A version with no hyperlinks was never made/added
    – Tom J Nowell
    Commented Sep 5, 2012 at 12:04
  • 1
    Well then, if you're correct then the extra line I added to my answer should do the job
    – Tom J Nowell
    Commented Sep 6, 2012 at 14:14

As requested...

add_action( 'init', 'create_my_post_types' );

function create_my_post_types() {
            'public' => true,
            'capability_type' => 'name_of_your_post_type_singular'

add_action('admin_init', 'give_user_read', 10, 0);
function give_user_edit() {
    if(current_user_can('edit_others_posts')) {
        global $wp_roles;
        $wp_roles->add_cap('author','read_name_of_your_post_type_plural' );
        $wp_roles->add_cap('editor','read_name_of_your_post_type_plural' );
                etc. etc.

I've added the read capability to the user roles. As I have not given anyone edit or delete.. they won't have it. As I've given author and editor read access, they will have it.

In case you're not sure what the capabilities will be, when you add the type as I have above you'll generate the capabilities below

'capabilities' => array(
            'publish_posts' => 'publish_name_of_your_post_type_plural',
            'edit_posts' => 'edit_name_of_your_post_type_plural',
            'edit_others_posts' => 'edit_others_name_of_your_post_type_plural',
            'delete_posts' => 'delete_name_of_your_post_type_plural',
            'delete_others_posts' => 'delete_others_name_of_your_post_type_plural',
            'read_private_posts' => 'read_private_name_of_your_post_type_plural',
            'edit_post' => 'edit_name_of_your_post_type_singular',
            'delete_post' => 'delete_name_of_your_post_type_singular',
            'read_post' => 'read_name_of_your_post_type_singular'

You could remove it by using some css in your plugin within the admin area

In your functions.php file link to some CSS (reference: http://codex.wordpress.org/Function_Reference/wp_enqueue_style)

add_action('admin_enqueue_scripts', 'my_admin_script');
function my_admin_script()
wp_register_style( 'myPluginStylesheet', plugins_url('stylesheet.css', __FILE__) );

The CSS:

#adminmenu a[href="edit.php?post_type=events"],
#adminmenu a.editinline,
#adminmenu a[title="Edit this item"] {

In the CSS you'll need to replace the references to 'events' with the name of your custom post type. This will work IE7+ I believe using those selectors.

  • Thanks, that will indeed accomplish the job from a 'display' perspective, however I wanted a more robust way of doing it, which would actually make those pages inaccessible rather than just hiding their links. If I don't manage to make then inaccessible, the next best solution would be to just hide them via CSS.
    – urok93
    Commented Sep 7, 2012 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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