For the contact form of my own theme I have created a Custom Post Type in which the messages of the users are automatically stored. In the administration area the messages can be read similar to comments.

By doing this, you can create, change and delete messages in the administration area. All these functionalities should be prevented, so that only the reading of the messages remains possible.

I tried to achieve this by giving the custom post type its own capability and assigning read rights to all user roles only. Unfortunately, by doing so, the Custom Post Type is no longer displayed at all. As it turned out, this is probably because the read rights are meant for the frontend. So how is it possible to restrict access to the custom post type to reading only?

Here are my CPT args:

$args = array(
    'labels'             => $labels,
    'public'             => false,
    'publicly_queryable' => false,
    'show_ui'            => true,
    'show_in_menu'       => true,
    'show_in_admin_bar'  => false,
    'menu_icon'          => 'dashicons-email-alt',
    'query_var'          => true,
    'rewrite'            => array( 'slug' => 'contact-form' ),
    'capability_type'    => array( 'contactFormMessage', 'contactFormMessages' ),
    'capabilities'       => array(
        'edit_post'          => 'edit_contactFormMessage',
        'edit_posts'         => 'edit_contactFormMessages',
        'edit_others_posts'  => 'edit_other_contactFormMessages',
        'publish_posts'      => 'publish_contactFormMessages',
        'read_post'          => 'read_contactFormMessage',
        'read_private_posts' => 'read_private_contactFormMessages',
        'delete_post'        => 'delete_contactFormMessage'
    'map_meta_cap'       => true,
    'has_archive'        => true,
    'hierarchical'       => false,
    'menu_position'      => null,
    'supports'           => array( 'title', 'editor', 'author' )

And using the following loop, I gave the read rights to all the user roles.

global $wp_roles;

foreach ( $wp_roles->roles as $key => $value )
    $currentRole = get_role( $key );

     $currentRole->add_cap( 'read_contactFormMessages' );
     $currentRole->add_cap( 'read_private_contactFormMessages' );

For the sake of security, I'm searching for a plugin-free solution to this issue. However, should it be a huge effort to achieve this, the use of a plugin is still an option.

  • How exactly would this read-only function work in the backend? As soon as you open a post within the editor, you can also change it. Why not create a simple UI in the frontend and display all your contactFromMessages?
    – Hans
    Oct 12, 2018 at 23:28

2 Answers 2


You are correct that the read capability is intended for the frontend. The capability you're looking for does not exist.

Additionally, if it did exist ( which it does not ), the WP Admin user interface does not provide a UI for viewing/reading posts, only addition and editing.

If you want it, I'm afraid you have to take the following steps:

  • Add a new capability, and add it to the relevant roles
  • Remove the standard WP access to those custom post types for those roles
  • Implement a UI from scratch, including a listing screen, and an option page for viewing the items

Just seeing this now... I have implemented something similar to what you wish to implement with the help of @webaware answer on https://wordpress.stackexchange.com/a/124992/165023 if you need further clarification on his code do let me know... Here to help


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.