We're configuring a new WordPress to use custom post types, and we want our editors to log in and only see only the custominzed post types, not the default 'post' post type. We've been able to remove 'post' from the Admin menu using this trick, but that still leaves the "+ New" Admin toolbar button, which contains a post option and defaults to creating a post. Is there an easy and safe way to remove post from the new toolbar button and/or hide the new toolbar button?
-
If you remove the posts related capabilities from the Editor role (or whichever you're using) these options shouldn't appear.– Jacob PeattieFeb 5, 2018 at 3:38
-
If the post type refuses to unregister, and if the "register_post_type" function isn't in functions.php, see if the registration is saved in a "must use plugin". As a reminder I place this comment at the top of my functoins.php "/* if something is stuck, look in must use plugins!!! */"– Dave MillerApr 22 at 12:53
4 Answers
You need to hook to 3 different action hooks to fully hide the default post type. However, a direct access to the default post by URL is still possible. So, let's get started.
The Side Menu
add_action( 'admin_menu', 'remove_default_post_type' );
function remove_default_post_type() {
remove_menu_page( 'edit.php' );
}
The + New > Post link in Admin Bar
add_action( 'admin_bar_menu', 'remove_default_post_type_menu_bar', 999 );
function remove_default_post_type_menu_bar( $wp_admin_bar ) {
$wp_admin_bar->remove_node( 'new-post' );
}
The + New link in Admin Bar
function remove_add_new_post_href_in_admin_bar() {
?>
<script type="text/javascript">
function remove_add_new_post_href_in_admin_bar() {
var add_new = document.getElementById('wp-admin-bar-new-content');
if(!add_new) return;
var add_new_a = add_new.getElementsByTagName('a')[0];
if(add_new_a) add_new_a.setAttribute('href','#!');
}
remove_add_new_post_href_in_admin_bar();
</script>
<?php
}
add_action( 'admin_footer', 'remove_add_new_post_href_in_admin_bar' );
function remove_frontend_post_href(){
if( is_user_logged_in() ) {
add_action( 'wp_footer', 'remove_add_new_post_href_in_admin_bar' );
}
}
add_action( 'init', 'remove_frontend_post_href' );
The Quick Draft Dashboard Widget
add_action( 'wp_dashboard_setup', 'remove_draft_widget', 999 );
function remove_draft_widget(){
remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );
}
-
This is the cleanest way, although the
New
button in the admin bar still points topost-new.php
- can be disabled with some Javascript e.g.$(document).on('click', '#wp-admin-bar-new-content', function(){ return false })
– MinaJul 27, 2019 at 10:39 -
This seems faultlessly working, but: "At a glance" still shows the posts (and it doesn't show the CPTs in any case!), just like the "Next Steps" part of the "Welcome to WP" dashboard item [which I hate and dismiss anyway]. Also "Activity" might still show posts, but shouldn't if you set it up neatly. Mar 25, 2021 at 20:55
An alternative, but similar solution to Stefan and Rafa's. This does not throw errors, and notice if you navigate directly to /wp-admin/edit.php you will not be able to view the list of posts (default post type), or edit them.
Note this code does not actually disable the default post type, i.e. existing post types will still be published and accessible via public URL. It effectively disables backend access to the default post type for all users.
function remove_default_post_type($args, $postType) {
if ($postType === 'post') {
$args['public'] = false;
$args['show_ui'] = false;
$args['show_in_menu'] = false;
$args['show_in_admin_bar'] = false;
$args['show_in_nav_menus'] = false;
$args['can_export'] = false;
$args['has_archive'] = false;
$args['exclude_from_search'] = true;
$args['publicly_queryable'] = false;
$args['show_in_rest'] = false;
}
return $args;
}
add_filter('register_post_type_args', 'remove_default_post_type', 0, 2);
In principle it is possible to unregister already registered post types using unregister_post_type()
. Unfortunately this is not possible for _builtin
post types.
Alternatively it is possible to change the capabilities which are required to edit/create/delete/... posts for a specific post type. You could use the register_post_type_args
filter to change the capabilities which are required for the default post
post type. Setting all capabilities to false
will result in nobody having access to the default post post type. WordPress is smart enough to automatically hide the navigation entries.
add_filter('register_post_type_args', function($args, $postType){
if ($postType === 'post') {
$args['capabilities'] = [
'edit_post' => false,
'read_post' => false,
'delete_post' => false,
'edit_posts' => false,
'edit_others_posts' => false,
'publish_posts' => false,
'read' => false,
'delete_posts' => false,
'delete_private_posts' => false,
'delete_published_posts' => false,
'delete_others_posts' => false,
'edit_private_posts' => false,
'edit_published_posts' => false,
'create_posts' => false,
];
}
return $args
}, 0, 2);
-
Thanks, I put this code into a function that was fired on the 'init' event, but it didn't seem to have any effect on my UI. Am I hooking the wrong event? Feb 5, 2018 at 17:48
-
That is too late. WordPress registers all
_builtin
post types at theinit
action but with an priority of0
. The code above is registering just a filter, you do not have to put it inside another action/filter, just write it directly into your themesfunctions.php
for example.– StefanFeb 5, 2018 at 18:47 -
+1. The thing is it throws 3 notices. "Notice: Undefined offset: 0 in /var/www/html/wp-includes/capabilities.php on line 70". I couldn't get rid of them.– nowayNov 17, 2019 at 11:37
-
Note that this doesn't remove the "category" and "post_tag" taxonomies, so the "Posts" nav menu item remains (albeit without letting you view or edit posts themselves.)– W BiggsJul 22, 2020 at 15:31
Stefan's solution is great, but if you active debug you can see : Undefined offset: 0 in wp-includes/capabilities.php on line 62 plus there is a missing ; after return $args
Exhaustive code should be :
add_filter('register_post_type_args', function($args, $postType){
if ($postType === 'post' && current_user_can( 'create_posts' ) && current_user_can( 'edit_post' ) ) {
$args['capabilities'] = [
'edit_post' => false,
'read_post' => false,
'delete_post' => false,
'edit_posts' => false,
'edit_others_posts' => false,
'publish_posts' => false,
'read' => false,
'delete_posts' => false,
'delete_private_posts' => false,
'delete_published_posts' => false,
'delete_others_posts' => false,
'edit_private_posts' => false,
'edit_published_posts' => false,
'create_posts' => false,
];
}
return $args;
}, 0, 2);
-
current_user_can throws an error. It is not defined yet at this stage.– nowayNov 17, 2019 at 11:59