9

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?

2
  • If you remove the posts related capabilities from the Editor role (or whichever you're using) these options shouldn't appear. Feb 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!!! */" Apr 22 at 12:53

4 Answers 4

17

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' );
}
2
  • This is the cleanest way, although the New button in the admin bar still points to post-new.php - can be disabled with some Javascript e.g. $(document).on('click', '#wp-admin-bar-new-content', function(){ return false })
    – Mina
    Jul 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
9

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

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);
4
  • 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 the init action but with an priority of 0. 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 themes functions.php for example.
    – Stefan
    Feb 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.
    – noway
    Nov 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 Biggs
    Jul 22, 2020 at 15:31
0

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);
1
  • current_user_can throws an error. It is not defined yet at this stage.
    – noway
    Nov 17, 2019 at 11:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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