Prevent Users from Deleting Posts in Specific WordPress Post Types

We once built an order system on top of WordPress. When a user submitted an order from the front end, the order data was stored in a custom post type. Customer service staff could view and process those orders in the dashboard, but we needed to make sure they could not delete them accidentally.

Remove the delete capability for a specific post type

The following code uses map_meta_cap to block deletion for the target post type. Once it is in place, the post row actions for that post type can be reduced to actions such as viewing and editing only.

add_filter( 'map_meta_cap', function ( $caps, $cap, $user_id, $args ) {
    // Do nothing unless WordPress is checking delete_post.
    if ( 'delete_post' !== $cap || empty( $args[0] ) ) {
        return $caps;
    }

    // For the target post type, deny deletion.
    if ( in_array( get_post_type( $args[0] ), [ 'order' ], true ) ) {
        return [ 'do_not_allow' ];
    }

    return $caps;
}, 10, 4 );

After that, the post row actions will no longer include deletion for that post type, leaving only actions such as Edit, as shown below.

Post row actions after the delete action is removed

Remove the “Move to Trash” bulk action

Even after the delete capability is removed, the post list can still show the Move to Trash option in bulk actions. If a user selects it and clicks Apply, WordPress simply throws a permissions error.

Bulk action menu still showing Move to Trash

To clean that up, remove the trash action from the bulk action list:

add_filter( 'bulk_actions-edit-message', function ( $actions ) {
    unset( $actions['trash'] );

    return $actions;
} );

The same general approach can be used to block other actions as well. If some roles should still be allowed to delete those posts, you can add your own capability checks around the restriction.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *