Wordpress - Prevent trash/delete action on specific post types

Here's another approach using the map_meta_cap filter that's applied within the map_meta_cap() function within the has_cap() method of the WP_User class (PHP 5.4+):

add_filter( 'map_meta_cap', function ( $caps, $cap, $user_id, $args )
{
    // Nothing to do
    if( 'delete_post' !== $cap || empty( $args[0] ) )
        return $caps;

    // Target the payment and transaction post types
    if( in_array( get_post_type( $args[0] ), [ 'payment', 'transaction' ], true ) )
        $caps[] = 'do_not_allow';       

    return $caps;    
}, 10, 4 );

where we target the delete_post meta capability and the payment and transaction custom post types.

As far as I understand and skimming through the get_post_type_capabilities() function we don't need the map_meta_cap argument set as true, in the register_post_type settings, to target the delete_post meta capability.

ps: Here are some good descriptions of the map_meta_cap filter and helpful examples by Justin Tadlock here and Toscho here. Here I found an old example that I had forgot I wrote, that we could also adjust to avoid trash/delete on some given pages and user roles. Here's an answer by TheDeadMedic that links to an answer by Seamus Leahy regarding register_post_type approach. Here are some more examples on this site. Hope it helps!


A better way to prevent deletion would be to disable that capability for all roles. When you register your post types 'payment' and 'transaction' also define a capability_type with the same name as your post type. This will give you capabilities read_payment, edit_payment and delete_payment (same for transaction).

You can then deny this capability on roles in this way:

$wp_roles->remove_cap( 'editor', 'delete_payment' );
$wp_roles->remove_cap( 'admin', 'delete_payment' );

Always beware that since admins can edit code on your site, they will still be able to circumvent the deletion, unless you block code editing in the backend and restrict ftp and database access. Also read this discussion on getting all available roles.