Prevent WordPress from deleting a post

At first glance it seems as though there are no hooks or filters in WordPress for preventing a post/page deletion. But you can do it by filtering user_has_cap (short for user has capability). This is a very powerful filter, and you can use it to block almost anything in WordPress. It has three parameters:

  • $allcaps (an array of all the capabilities, each one set to true or false)
  • $caps (an array of the capabilities being requested by the current operation)
  • $args (an array of arguments relevant to this operation).
  • When a post is being deleted, $args is set to array ('delete_post', $user_id, $post_id). The capabilities required to allow the deletion are stored in the array $caps, and will vary depending on what type of post is being deleted (e.g. ‘delete_published_posts’). Each capability in $caps corresponds to an item in $allcaps. To prevent the post being deleted, all we need to do is modify $allcaps by setting one of the values listed in $caps to false (e.g. $allcaps[$caps[0]] = false).

    As an example, the following code prevents the last published page of a site being deleted.

    add_filter ('user_has_cap', 'wpcs_prevent_last_page_deletion', 10, 3);
    
    function wpcs_prevent_last_page_deletion ($allcaps, $caps, $args) {
    	global $wpdb;
    	if (isset($args[0]) && isset($args[2]) && $args[0] == 'delete_post') {
    		$post = get_post ($args[2]);
    		if ($post->post_status == 'publish' && $post->post_type == 'page') {
    			$query = "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type = %s";
    			$num_posts = $wpdb->get_var ($wpdb->prepare ($query, $post->post_type));
    			if ($num_posts < 2)
    				$allcaps[$caps[0]] = false;
    		}
    	}
    	return $allcaps;
    }
    

Comments

  1. Thanks for this code guy!

  2. I needed this logic for a different purpose: it works perfectly!
    Now I only need to provide a feedback to users that won’t find a way to delete/trash their posts.
    This feedback must be shown in both posts/pages/cpts list page and single page as well.

    I will google a bit, but if you have any tip, it will be more than welcome!

    • Mark Barnes says:

      The trash buttons should hide themselves, so users won’t be able to delete post/pages without using the bulk trash feature, or manipulating URLs. If they to use the bulk trash, they’ll get the message: “You are not allowed to move this item to the Trash.” If they try to manipulate the URL, the nonce will be wrong and they’ll get the message: “Are you sure you want to do this?”.

  3. Use This Plugin. It will prevent you from deleting pages and posts https://wordpress.org/plugins/prevent-users-from-deleting-pages-posts-custom-post-types/

Speak Your Mind

*