for security reasons I need to:
- prevent all users except admins from permanently deleting posts from trash.
- They should still be able to trash drafts,
- 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 (
'delete_posts',
'delete_published_posts'
);
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.
Thanks!
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)