wp_delete_post

The timeline below displays how wordpress function wp_delete_post has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.1

/**
 * Trashes or deletes a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to Trash instead of permanently deleted unless
 * Trash is disabled, item is already in the Trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass Trash and force deletion.
 *                           Default false.
 * @return WP_Post|false|null Post data on success, false or null on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    $post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid));
    if (!$post) {
        return $post;
    }
    $post = get_post($post);
    if (!$force_delete && ('post' === $post->post_type || 'page' === $post->post_type) && 'trash' !== get_post_status($postid) && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ('attachment' === $post->post_type) {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filters whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param WP_Post|false|null $delete       Whether to go forward with deletion.
     * @param WP_Post            $post         Post object.
     * @param bool               $force_delete Whether to bypass the Trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @see wp_delete_post()
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('before_delete_post', $postid, $post);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        if ($children) {
            $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
        }
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d ORDER BY comment_ID DESC", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('delete_post', $postid, $post);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('deleted_post', $postid, $post);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @see wp_delete_post()
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('after_delete_post', $postid, $post);
    return $post;
}

WordPress Version: 5.9

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to Trash instead of permanently deleted unless
 * Trash is disabled, item is already in the Trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass Trash and force deletion.
 *                           Default false.
 * @return WP_Post|false|null Post data on success, false or null on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    $post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid));
    if (!$post) {
        return $post;
    }
    $post = get_post($post);
    if (!$force_delete && ('post' === $post->post_type || 'page' === $post->post_type) && 'trash' !== get_post_status($postid) && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ('attachment' === $post->post_type) {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filters whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param bool|null $delete       Whether to go forward with deletion.
     * @param WP_Post   $post         Post object.
     * @param bool      $force_delete Whether to bypass the Trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @see wp_delete_post()
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('before_delete_post', $postid, $post);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        if ($children) {
            $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
        }
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d ORDER BY comment_ID DESC", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('delete_post', $postid, $post);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('deleted_post', $postid, $post);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @see wp_delete_post()
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('after_delete_post', $postid, $post);
    return $post;
}

WordPress Version: 5.5

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to Trash instead of permanently deleted unless
 * Trash is disabled, item is already in the Trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass Trash and force deletion.
 *                           Default false.
 * @return WP_Post|false|null Post data on success, false or null on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    $post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid));
    if (!$post) {
        return $post;
    }
    $post = get_post($post);
    if (!$force_delete && ('post' === $post->post_type || 'page' === $post->post_type) && 'trash' !== get_post_status($postid) && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ('attachment' === $post->post_type) {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filters whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param bool|null $delete       Whether to go forward with deletion.
     * @param WP_Post   $post         Post object.
     * @param bool      $force_delete Whether to bypass the Trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @see wp_delete_post()
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('before_delete_post', $postid, $post);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        if ($children) {
            $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
        }
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('delete_post', $postid, $post);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('deleted_post', $postid, $post);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     * @since 5.5.0 Added the `$post` parameter.
     *
     * @see wp_delete_post()
     *
     * @param int     $postid Post ID.
     * @param WP_Post $post   Post object.
     */
    do_action('after_delete_post', $postid, $post);
    return $post;
}

WordPress Version: 5.4

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to Trash instead of permanently deleted unless
 * Trash is disabled, item is already in the Trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass Trash and force deletion.
 *                           Default false.
 * @return WP_Post|false|null Post data on success, false or null on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    $post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid));
    if (!$post) {
        return $post;
    }
    $post = get_post($post);
    if (!$force_delete && ('post' === $post->post_type || 'page' === $post->post_type) && 'trash' !== get_post_status($postid) && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ('attachment' === $post->post_type) {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filters whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param bool|null $delete       Whether to go forward with deletion.
     * @param WP_Post   $post         Post object.
     * @param bool      $force_delete Whether to bypass the Trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        if ($children) {
            $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
        }
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 5.3

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless
 * trash is disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
 *                           Default false.
 * @return WP_Post|false|null Post data on success, false or null on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    $post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid));
    if (!$post) {
        return $post;
    }
    $post = get_post($post);
    if (!$force_delete && ('post' === $post->post_type || 'page' === $post->post_type) && 'trash' !== get_post_status($postid) && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ('attachment' === $post->post_type) {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filters whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param bool|null $delete       Whether to go forward with deletion.
     * @param WP_Post   $post         Post object.
     * @param bool      $force_delete Whether to bypass the trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        if ($children) {
            $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
        }
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 4.9

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless
 * trash is disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
 *                           Default false.
 * @return WP_Post|false|null Post data on success, false or null on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    $post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid));
    if (!$post) {
        return $post;
    }
    $post = get_post($post);
    if (!$force_delete && ('post' === $post->post_type || 'page' === $post->post_type) && 'trash' !== get_post_status($postid) && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ('attachment' === $post->post_type) {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filters whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param bool    $delete       Whether to go forward with deletion.
     * @param WP_Post $post         Post object.
     * @param bool    $force_delete Whether to bypass the trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        if ($children) {
            $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
        }
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 4.6

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless
 * trash is disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
 *                           Default false.
 * @return array|false|WP_Post False on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filters whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param bool    $delete       Whether to go forward with deletion.
     * @param WP_Post $post         Post object.
     * @param bool    $force_delete Whether to bypass the trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        if ($children) {
            $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
        }
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 4.5

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless
 * trash is disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
 *                           Default false.
 * @return array|false|WP_Post False on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filter whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param bool    $delete       Whether to go forward with deletion.
     * @param WP_Post $post         Post object.
     * @param bool    $force_delete Whether to bypass the trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        if ($children) {
            $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
        }
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 4.4

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless
 * trash is disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
 *                           Default false.
 * @return array|false|WP_Post False on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Filter whether a post deletion should take place.
     *
     * @since 4.4.0
     *
     * @param bool    $delete       Whether to go forward with deletion.
     * @param WP_Post $post         Post object.
     * @param bool    $force_delete Whether to bypass the trash.
     */
    $check = apply_filters('pre_delete_post', null, $post, $force_delete);
    if (null !== $check) {
        return $check;
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    wp_defer_comment_counting(true);
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    wp_defer_comment_counting(false);
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 4.3

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless
 * trash is disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
 *                           Default false.
 * @return array|false|WP_Post False on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 4.1

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless
 * trash is disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
 *                           Default false.
 * @return array|bool|WP_Post False on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 4.0

/**
 * Trash or delete a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to
 * it is deleted also. This includes comments, post meta fields, and terms
 * associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless
 * trash is disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database access abstraction object.
 * @see wp_delete_attachment()
 * @see wp_trash_post()
 *
 * @param int  $postid       Optional. Post ID. Default 0.
 * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
 *                           Default false.
 * @return array|bool|WP_Post False on failure.
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children.
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
    }
    // Do raw query. wp_get_post_revisions() is filtered.
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level.
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 3.9

/**
 * Trashes or deletes a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to it is deleted also.
 * This includes comments, post meta fields, and terms associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless trash is
 * disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 *
 * @uses wp_delete_attachment() if post type is 'attachment'.
 * @uses wp_trash_post() if item should be trashed.
 *
 * @param int $postid Post ID.
 * @param bool $force_delete Whether to bypass trash and force deletion. Defaults to false.
 * @return mixed False on failure
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    /**
     * Fires before a post is deleted, at the start of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
    }
    // Do raw query. wp_get_post_revisions() is filtered
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    /**
     * Fires immediately before a post is deleted from the database.
     *
     * @since 1.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    /**
     * Fires immediately after a post is deleted from the database.
     *
     * @since 2.2.0
     *
     * @param int $postid Post ID.
     */
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    /**
     * Fires after a post is deleted, at the conclusion of wp_delete_post().
     *
     * @since 3.2.0
     *
     * @see wp_delete_post()
     *
     * @param int $postid Post ID.
     */
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 3.8

/**
 * Trashes or deletes a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to it is deleted also.
 * This includes comments, post meta fields, and terms associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless trash is
 * disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 * @uses do_action() on 'delete_post' before deletion unless post type is 'attachment'.
 * @uses do_action() on 'deleted_post' after deletion unless post type is 'attachment'.
 * @uses wp_delete_attachment() if post type is 'attachment'.
 * @uses wp_trash_post() if item should be trashed.
 *
 * @param int $postid Post ID.
 * @param bool $force_delete Whether to bypass trash and force deletion. Defaults to false.
 * @return mixed False on failure
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
    }
    // Do raw query. wp_get_post_revisions() is filtered
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    do_action('delete_post', $postid);
    $result = $wpdb->delete($wpdb->posts, array('ID' => $postid));
    if (!$result) {
        return false;
    }
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    do_action('after_delete_post', $postid);
    return $post;
}

WordPress Version: 3.7

/**
 * Trashes or deletes a post or page.
 *
 * When the post and page is permanently deleted, everything that is tied to it is deleted also.
 * This includes comments, post meta fields, and terms associated with the post.
 *
 * The post or page is moved to trash instead of permanently deleted unless trash is
 * disabled, item is already in the trash, or $force_delete is true.
 *
 * @since 1.0.0
 * @uses do_action() on 'delete_post' before deletion unless post type is 'attachment'.
 * @uses do_action() on 'deleted_post' after deletion unless post type is 'attachment'.
 * @uses wp_delete_attachment() if post type is 'attachment'.
 * @uses wp_trash_post() if item should be trashed.
 *
 * @param int $postid Post ID.
 * @param bool $force_delete Whether to bypass trash and force deletion. Defaults to false.
 * @return mixed False on failure
 */
function wp_delete_post($postid = 0, $force_delete = false)
{
    global $wpdb;
    if (!$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", $postid))) {
        return $post;
    }
    if (!$force_delete && ($post->post_type == 'post' || $post->post_type == 'page') && get_post_status($postid) != 'trash' && EMPTY_TRASH_DAYS) {
        return wp_trash_post($postid);
    }
    if ($post->post_type == 'attachment') {
        return wp_delete_attachment($postid, $force_delete);
    }
    do_action('before_delete_post', $postid);
    delete_post_meta($postid, '_wp_trash_meta_status');
    delete_post_meta($postid, '_wp_trash_meta_time');
    wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
    $parent_data = array('post_parent' => $post->post_parent);
    $parent_where = array('post_parent' => $postid);
    if (is_post_type_hierarchical($post->post_type)) {
        // Point children of this page to its parent, also clean the cache of affected children
        $children_query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = %s", $postid, $post->post_type);
        $children = $wpdb->get_results($children_query);
        $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => $post->post_type));
    }
    // Do raw query. wp_get_post_revisions() is filtered
    $revision_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_type = 'revision'", $postid));
    // Use wp_delete_post (via wp_delete_post_revision) again. Ensures any meta/misplaced data gets cleaned up.
    foreach ($revision_ids as $revision_id) {
        wp_delete_post_revision($revision_id);
    }
    // Point all attachments to this post up one level
    $wpdb->update($wpdb->posts, $parent_data, $parent_where + array('post_type' => 'attachment'));
    $comment_ids = $wpdb->get_col($wpdb->prepare("SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d", $postid));
    foreach ($comment_ids as $comment_id) {
        wp_delete_comment($comment_id, true);
    }
    $post_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d ", $postid));
    foreach ($post_meta_ids as $mid) {
        delete_metadata_by_mid('post', $mid);
    }
    do_action('delete_post', $postid);
    $wpdb->delete($wpdb->posts, array('ID' => $postid));
    do_action('deleted_post', $postid);
    clean_post_cache($post);
    if (is_post_type_hierarchical($post->post_type) && $children) {
        foreach ($children as $child) {
            clean_post_cache($child);
        }
    }
    wp_clear_scheduled_hook('publish_future_post', array($postid));
    do_action('after_delete_post', $postid);
    return $post;
}