Read only capability for custom post in admin area

I’m actually building custom type to WP and need to be able to restrict post access to some user role, ie. in admin area, collaborators can see posts but can’t edit them, just only open them as read-only. I used some plugins (Adminimize and User Role Editor) but, as far as I know, they don’t apply to my needs.

Does any one give me directions in order to solve this?

Related posts

Leave a Reply

2 comments

  1. brasolfilo’s suggestion that you remove the submit meta box is only part of what I’d consider a complete solution. I can hack a “submit” button into that page using FireBug or any of a few other tools, in a matter of minutes.

    I would…

    1. Remove the meta box. This is brasofilo’s solution, and I won’t elaborate as that code looks fine.
    2. Remove all access to post-new.php for that post type for users who should have only read-only access.
    3. Alter the “Add New” link on the edit page.
    4. Kill the post submission in PHP to stop like minded (minded like me 🙂 ) individuals from getting sneaky.

    The following code uses the ‘Book’ post type that can be found in the Codex. You can modify it to match your CPT.

    Remove access to post-new.php

    function conditional_redirect_post_new_wpse_94776() {
      global $_REQUEST,$pagenow;
      if (!empty($_REQUEST['post_type'])
        && 'book' == $_REQUEST['post_type']
        && !empty($pagenow)
        && 'post-new.php' == $pagenow
        && !current_user_can('administrator'))
      {
        wp_safe_redirect(admin_url('edit.php?post_type=book'));
      }
    }
    add_filter('admin_menu','conditional_redirect_post_new_wpse_94776');
    

    Remove the “Add New” Menu

    function remove_add_new_menu_wpse_94776() {
      if (!current_user_can('administrator')) {
        remove_submenu_page('edit.php?post_type=book','post-new.php?post_type=book');
      }
    }
    add_action('admin_menu','remove_add_new_menu_wpse_94776');
    

    Alter the “Add New” link on the Edit page

    function reset_post_new_link_wpse_94776() {
      global $post_new_file,$post_type_object;
      if (!isset($post_type_object) || 'book' != $post_type_object->name) return false;
    
      if (!current_user_can('administrator')) {
        $post_type_object->labels->add_new = 'Return to Index';
        $post_new_file = admin_url('edit.php?post_type=book');
      }
    }
    add_action('admin_head','reset_post_new_link_wpse_94776');
    

    Prevent sneaky submissions

    function stop_submit_wpse_94776() {
      if (!empty($_POST) && $_POST['post_type'] == 'book' && !current_user_can('administrator')) {
        if (true === DOING_AJAX) {
          exit;
        }
        if (!empty($_POST['post_ID'])) {
          wp_safe_redirect(admin_url('post.php?post='.$_POST['post_ID'].'&action=edit'));
          exit;
        } else {
          wp_safe_redirect(admin_url('edit.php?post_type=book'));
          exit;
        }
      }
    }
    add_action('admin_init','stop_submit_wpse_94776');
    

    I think has got it. It seems to work as I’ve been testing it, but I would not be surprised if there were bugs, especially in that last block of code, nor would I be surprised if there were more elegant ways of doing some of the same things. Caveat Emptor. No refunds.

  2. If you simply remove the meta box, there’s no way of saving/updating the post. Tested here with the regular Post post type:

    add_action( 'do_meta_boxes', 'remove_publish_mbox_wpse_94776', 10, 3 );
    
    function remove_publish_mbox_wpse_94776( $post_type, $position, $post )
    {
        remove_meta_box( 'submitdiv', 'post', 'side' );
    }
    

    There could be issues with Autosave and Revisions.

    Other solution would be making the fields read-only with jQuery, but maybe it’s not very solid.

    Finally, another option would be removing the Title and Content fields and printing simple text in replacement.