for security reasons I need to:

  1. prevent all users except admins from permanently deleting posts from trash.
  2. They should still be able to trash drafts,
  3. and be able to restore drafts from trash.

The solution I have fulfills 1+2, but not 3.

First I'm removing the capabilities, here an example for the editor role:

$editor = get_role( 'editor' );
    $caps = array (
    foreach ( $caps as $cap ) {
        $editor->remove_cap( $cap );

This keeps the capability 'delete_others_posts' - don't ask me why but I found that this is the combination that lets users trash drafts but not other posts.

But: They can still permanently delete posts from trash.

So now I want to remove the option to delete from trash. This is what I have based on this answer:

add_filter ('user_has_cap', 'prevent_deletion', 10, 3);
function prevent_deletion ($allcaps, $caps, $args) {
    if (isset($args[0]) && isset($args[2]) && $args[0] == 'delete_post') {
        $post = get_post ($args[2]);
        if ($post->post_status == 'trash') {
            $allcaps[$caps[0]] = false;
    return $allcaps;

Now users can't delete from trash. But they also can't restore a post from trash.

I'm aware this is because the if statement is way too broad, but I don't know how to make it more specific. Or, if this is not the right path, what to do instead to achieve the goal.


For context, these other solutions didn't work:

  • hooking into before_delete_post and redirecting users when they try to delete: it works per se, but is too unpredictable, it fires when users are doing something else
  • Hiding via CSS/JS is not secure enough (as suggested here)

1 Answer 1


Found an elegant solution using pre_delete_post:

function modify_pre_delete_post_defaults($delete, $post, $force_delete) { 
    return true; 
add_filter( "pre_delete_post", "modify_pre_delete_post_defaults", 10, 3 );

This filters whether a post should be deleted. Returning any other value than $delete prevents deletion.

See more info:

Your Answer

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

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