Read only capability for custom post in admin area

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.

Leave a Comment