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?


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'))

Remove the "Add New" Menu

function remove_add_new_menu_wpse_94776() {
  if (!current_user_can('administrator')) {

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');

Prevent sneaky submissions

function stop_submit_wpse_94776() {
  if (!empty($_POST) && $_POST['post_type'] == 'book' && !current_user_can('administrator')) {
    if (true === DOING_AJAX) {
    if (!empty($_POST['post_ID'])) {
    } else {

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.

  • Now you talked Canonical ;) Didn't know most of those globals in admin_head, really cool stuff. Just a note on the UI side, Return to Index shouldn't appear in the edit.php screen, applying an empty string hides it. ::: There should be an item: [faq#no-refunds] !
    – brasofilo
    Apr 7 '13 at 0:46
  • Argh... I knew there was going to be something I missed... or maybe I missed pasted something. I'll recheck.
    – s_ha_dum
    Apr 7 '13 at 2:08
  • @brasofilo, an empty string still leaves a light gray box where the link should be. I haven't worked out how to remove that entirely, other than CSS or JS, so I let that little flaw slide :) I should remove the link under "+ New" in the admin bar too.
    – s_ha_dum
    Apr 7 '13 at 4:28

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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