wp_update_post

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

WordPress Version: 6.1

/**
 * Updates a post with new post data.
 *
 * The date does not have to be set for drafts. You can set the date and it will
 * not be overridden.
 *
 * @since 1.0.0
 * @since 3.5.0 Added the `$wp_error` parameter to allow a WP_Error to be returned on failure.
 * @since 5.6.0 Added the `$fire_after_hooks` parameter.
 *
 * @param array|object $postarr          Optional. Post data. Arrays are expected to be escaped,
 *                                       objects are not. See wp_insert_post() for accepted arguments.
 *                                       Default array.
 * @param bool         $wp_error         Optional. Whether to return a WP_Error on failure. Default false.
 * @param bool         $fire_after_hooks Optional. Whether to fire the after insert hooks. Default true.
 * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
 */
function wp_update_post($postarr = array(), $wp_error = false, $fire_after_hooks = true)
{
    if (is_object($postarr)) {
        // Non-escaped post was passed.
        $postarr = get_object_vars($postarr);
        $postarr = wp_slash($postarr);
    }
    // First, get all of the original fields.
    $post = get_post($postarr['ID'], ARRAY_A);
    if (is_null($post)) {
        if ($wp_error) {
            return new WP_Error('invalid_post', __('Invalid post ID.'));
        }
        return 0;
    }
    // Escape data pulled from DB.
    $post = wp_slash($post);
    // Passed post category list overwrites existing category list if not empty.
    if (isset($postarr['post_category']) && is_array($postarr['post_category']) && count($postarr['post_category']) > 0) {
        $post_cats = $postarr['post_category'];
    } else {
        $post_cats = $post['post_category'];
    }
    // Drafts shouldn't be assigned a date unless explicitly done so by the user.
    if (isset($post['post_status']) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft'), true) && empty($postarr['edit_date']) && '0000-00-00 00:00:00' === $post['post_date_gmt']) {
        $clear_date = true;
    } else {
        $clear_date = false;
    }
    // Merge old and new fields with new fields overwriting old ones.
    $postarr = array_merge($post, $postarr);
    $postarr['post_category'] = $post_cats;
    if ($clear_date) {
        $postarr['post_date'] = current_time('mysql');
        $postarr['post_date_gmt'] = '';
    }
    if ('attachment' === $postarr['post_type']) {
        return wp_insert_attachment($postarr, false, 0, $wp_error);
    }
    // Discard 'tags_input' parameter if it's the same as existing post tags.
    if (isset($postarr['tags_input']) && is_object_in_taxonomy($postarr['post_type'], 'post_tag')) {
        $tags = get_the_terms($postarr['ID'], 'post_tag');
        $tag_names = array();
        if ($tags && !is_wp_error($tags)) {
            $tag_names = wp_list_pluck($tags, 'name');
        }
        if ($postarr['tags_input'] === $tag_names) {
            unset($postarr['tags_input']);
        }
    }
    return wp_insert_post($postarr, $wp_error, $fire_after_hooks);
}

WordPress Version: 5.6

/**
 * Update a post with new post data.
 *
 * The date does not have to be set for drafts. You can set the date and it will
 * not be overridden.
 *
 * @since 1.0.0
 * @since 3.5.0 Added the `$wp_error` parameter to allow a WP_Error to be returned on failure.
 * @since 5.6.0 Added the `$fire_after_hooks` parameter.
 *
 * @param array|object $postarr          Optional. Post data. Arrays are expected to be escaped,
 *                                       objects are not. See wp_insert_post() for accepted arguments.
 *                                       Default array.
 * @param bool         $wp_error         Optional. Whether to return a WP_Error on failure. Default false.
 * @param bool         $fire_after_hooks Optional. Whether to fire the after insert hooks. Default true.
 * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
 */
function wp_update_post($postarr = array(), $wp_error = false, $fire_after_hooks = true)
{
    if (is_object($postarr)) {
        // Non-escaped post was passed.
        $postarr = get_object_vars($postarr);
        $postarr = wp_slash($postarr);
    }
    // First, get all of the original fields.
    $post = get_post($postarr['ID'], ARRAY_A);
    if (is_null($post)) {
        if ($wp_error) {
            return new WP_Error('invalid_post', __('Invalid post ID.'));
        }
        return 0;
    }
    // Escape data pulled from DB.
    $post = wp_slash($post);
    // Passed post category list overwrites existing category list if not empty.
    if (isset($postarr['post_category']) && is_array($postarr['post_category']) && count($postarr['post_category']) > 0) {
        $post_cats = $postarr['post_category'];
    } else {
        $post_cats = $post['post_category'];
    }
    // Drafts shouldn't be assigned a date unless explicitly done so by the user.
    if (isset($post['post_status']) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft'), true) && empty($postarr['edit_date']) && '0000-00-00 00:00:00' === $post['post_date_gmt']) {
        $clear_date = true;
    } else {
        $clear_date = false;
    }
    // Merge old and new fields with new fields overwriting old ones.
    $postarr = array_merge($post, $postarr);
    $postarr['post_category'] = $post_cats;
    if ($clear_date) {
        $postarr['post_date'] = current_time('mysql');
        $postarr['post_date_gmt'] = '';
    }
    if ('attachment' === $postarr['post_type']) {
        return wp_insert_attachment($postarr, false, 0, $wp_error);
    }
    // Discard 'tags_input' parameter if it's the same as existing post tags.
    if (isset($postarr['tags_input']) && is_object_in_taxonomy($postarr['post_type'], 'post_tag')) {
        $tags = get_the_terms($postarr['ID'], 'post_tag');
        $tag_names = array();
        if ($tags && !is_wp_error($tags)) {
            $tag_names = wp_list_pluck($tags, 'name');
        }
        if ($postarr['tags_input'] === $tag_names) {
            unset($postarr['tags_input']);
        }
    }
    return wp_insert_post($postarr, $wp_error, $fire_after_hooks);
}

WordPress Version: 5.5

/**
 * Update a post with new post data.
 *
 * The date does not have to be set for drafts. You can set the date and it will
 * not be overridden.
 *
 * @since 1.0.0
 *
 * @param array|object $postarr  Optional. Post data. Arrays are expected to be escaped,
 *                               objects are not. Default array.
 * @param bool         $wp_error Optional. Allow return of WP_Error on failure. Default false.
 * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
 */
function wp_update_post($postarr = array(), $wp_error = false)
{
    if (is_object($postarr)) {
        // Non-escaped post was passed.
        $postarr = get_object_vars($postarr);
        $postarr = wp_slash($postarr);
    }
    // First, get all of the original fields.
    $post = get_post($postarr['ID'], ARRAY_A);
    if (is_null($post)) {
        if ($wp_error) {
            return new WP_Error('invalid_post', __('Invalid post ID.'));
        }
        return 0;
    }
    // Escape data pulled from DB.
    $post = wp_slash($post);
    // Passed post category list overwrites existing category list if not empty.
    if (isset($postarr['post_category']) && is_array($postarr['post_category']) && count($postarr['post_category']) > 0) {
        $post_cats = $postarr['post_category'];
    } else {
        $post_cats = $post['post_category'];
    }
    // Drafts shouldn't be assigned a date unless explicitly done so by the user.
    if (isset($post['post_status']) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft'), true) && empty($postarr['edit_date']) && '0000-00-00 00:00:00' === $post['post_date_gmt']) {
        $clear_date = true;
    } else {
        $clear_date = false;
    }
    // Merge old and new fields with new fields overwriting old ones.
    $postarr = array_merge($post, $postarr);
    $postarr['post_category'] = $post_cats;
    if ($clear_date) {
        $postarr['post_date'] = current_time('mysql');
        $postarr['post_date_gmt'] = '';
    }
    if ('attachment' === $postarr['post_type']) {
        return wp_insert_attachment($postarr, false, 0, $wp_error);
    }
    // Discard 'tags_input' parameter if it's the same as existing post tags.
    if (isset($postarr['tags_input']) && is_object_in_taxonomy($postarr['post_type'], 'post_tag')) {
        $tags = get_the_terms($postarr['ID'], 'post_tag');
        $tag_names = array();
        if ($tags && !is_wp_error($tags)) {
            $tag_names = wp_list_pluck($tags, 'name');
        }
        if ($postarr['tags_input'] === $tag_names) {
            unset($postarr['tags_input']);
        }
    }
    return wp_insert_post($postarr, $wp_error);
}

WordPress Version: 5.4

/**
 * Update a post with new post data.
 *
 * The date does not have to be set for drafts. You can set the date and it will
 * not be overridden.
 *
 * @since 1.0.0
 *
 * @param array|object $postarr  Optional. Post data. Arrays are expected to be escaped,
 *                               objects are not. Default array.
 * @param bool         $wp_error Optional. Allow return of WP_Error on failure. Default false.
 * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
 */
function wp_update_post($postarr = array(), $wp_error = false)
{
    if (is_object($postarr)) {
        // Non-escaped post was passed.
        $postarr = get_object_vars($postarr);
        $postarr = wp_slash($postarr);
    }
    // First, get all of the original fields.
    $post = get_post($postarr['ID'], ARRAY_A);
    if (is_null($post)) {
        if ($wp_error) {
            return new WP_Error('invalid_post', __('Invalid post ID.'));
        }
        return 0;
    }
    // Escape data pulled from DB.
    $post = wp_slash($post);
    // Passed post category list overwrites existing category list if not empty.
    if (isset($postarr['post_category']) && is_array($postarr['post_category']) && 0 != count($postarr['post_category'])) {
        $post_cats = $postarr['post_category'];
    } else {
        $post_cats = $post['post_category'];
    }
    // Drafts shouldn't be assigned a date unless explicitly done so by the user.
    if (isset($post['post_status']) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft')) && empty($postarr['edit_date']) && '0000-00-00 00:00:00' == $post['post_date_gmt']) {
        $clear_date = true;
    } else {
        $clear_date = false;
    }
    // Merge old and new fields with new fields overwriting old ones.
    $postarr = array_merge($post, $postarr);
    $postarr['post_category'] = $post_cats;
    if ($clear_date) {
        $postarr['post_date'] = current_time('mysql');
        $postarr['post_date_gmt'] = '';
    }
    if ('attachment' === $postarr['post_type']) {
        return wp_insert_attachment($postarr, false, 0, $wp_error);
    }
    // Discard 'tags_input' parameter if it's the same as existing post tags.
    if (isset($postarr['tags_input']) && is_object_in_taxonomy($postarr['post_type'], 'post_tag')) {
        $tags = get_the_terms($postarr['ID'], 'post_tag');
        $tag_names = array();
        if ($tags && !is_wp_error($tags)) {
            $tag_names = wp_list_pluck($tags, 'name');
        }
        if ($postarr['tags_input'] === $tag_names) {
            unset($postarr['tags_input']);
        }
    }
    return wp_insert_post($postarr, $wp_error);
}

WordPress Version: 5.1

/**
 * Update a post with new post data.
 *
 * The date does not have to be set for drafts. You can set the date and it will
 * not be overridden.
 *
 * @since 1.0.0
 *
 * @param array|object $postarr  Optional. Post data. Arrays are expected to be escaped,
 *                               objects are not. Default array.
 * @param bool         $wp_error Optional. Allow return of WP_Error on failure. Default false.
 * @return int|WP_Error The value 0 or WP_Error on failure. The post ID on success.
 */
function wp_update_post($postarr = array(), $wp_error = false)
{
    if (is_object($postarr)) {
        // Non-escaped post was passed.
        $postarr = get_object_vars($postarr);
        $postarr = wp_slash($postarr);
    }
    // First, get all of the original fields.
    $post = get_post($postarr['ID'], ARRAY_A);
    if (is_null($post)) {
        if ($wp_error) {
            return new WP_Error('invalid_post', __('Invalid post ID.'));
        }
        return 0;
    }
    // Escape data pulled from DB.
    $post = wp_slash($post);
    // Passed post category list overwrites existing category list if not empty.
    if (isset($postarr['post_category']) && is_array($postarr['post_category']) && 0 != count($postarr['post_category'])) {
        $post_cats = $postarr['post_category'];
    } else {
        $post_cats = $post['post_category'];
    }
    // Drafts shouldn't be assigned a date unless explicitly done so by the user.
    if (isset($post['post_status']) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft')) && empty($postarr['edit_date']) && '0000-00-00 00:00:00' == $post['post_date_gmt']) {
        $clear_date = true;
    } else {
        $clear_date = false;
    }
    // Merge old and new fields with new fields overwriting old ones.
    $postarr = array_merge($post, $postarr);
    $postarr['post_category'] = $post_cats;
    if ($clear_date) {
        $postarr['post_date'] = current_time('mysql');
        $postarr['post_date_gmt'] = '';
    }
    if ($postarr['post_type'] == 'attachment') {
        return wp_insert_attachment($postarr, false, 0, $wp_error);
    }
    return wp_insert_post($postarr, $wp_error);
}

WordPress Version: 4.0

/**
 * Update a post with new post data.
 *
 * The date does not have to be set for drafts. You can set the date and it will
 * not be overridden.
 *
 * @since 1.0.0
 *
 * @param array|object $postarr  Optional. Post data. Arrays are expected to be escaped,
 *                               objects are not. Default array.
 * @param bool         $wp_error Optional. Allow return of WP_Error on failure. Default false.
 * @return int|WP_Error The value 0 or WP_Error on failure. The post ID on success.
 */
function wp_update_post($postarr = array(), $wp_error = false)
{
    if (is_object($postarr)) {
        // Non-escaped post was passed.
        $postarr = get_object_vars($postarr);
        $postarr = wp_slash($postarr);
    }
    // First, get all of the original fields.
    $post = get_post($postarr['ID'], ARRAY_A);
    if (is_null($post)) {
        if ($wp_error) {
            return new WP_Error('invalid_post', __('Invalid post ID.'));
        }
        return 0;
    }
    // Escape data pulled from DB.
    $post = wp_slash($post);
    // Passed post category list overwrites existing category list if not empty.
    if (isset($postarr['post_category']) && is_array($postarr['post_category']) && 0 != count($postarr['post_category'])) {
        $post_cats = $postarr['post_category'];
    } else {
        $post_cats = $post['post_category'];
    }
    // Drafts shouldn't be assigned a date unless explicitly done so by the user.
    if (isset($post['post_status']) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft')) && empty($postarr['edit_date']) && '0000-00-00 00:00:00' == $post['post_date_gmt']) {
        $clear_date = true;
    } else {
        $clear_date = false;
    }
    // Merge old and new fields with new fields overwriting old ones.
    $postarr = array_merge($post, $postarr);
    $postarr['post_category'] = $post_cats;
    if ($clear_date) {
        $postarr['post_date'] = current_time('mysql');
        $postarr['post_date_gmt'] = '';
    }
    if ($postarr['post_type'] == 'attachment') {
        return wp_insert_attachment($postarr);
    }
    return wp_insert_post($postarr, $wp_error);
}

WordPress Version: 3.7

/**
 * Update a post with new post data.
 *
 * The date does not have to be set for drafts. You can set the date and it will
 * not be overridden.
 *
 * @since 1.0.0
 *
 * @param array|object $postarr Post data. Arrays are expected to be escaped, objects are not.
 * @param bool $wp_error Optional. Allow return of WP_Error on failure.
 * @return int|WP_Error The value 0 or WP_Error on failure. The post ID on success.
 */
function wp_update_post($postarr = array(), $wp_error = false)
{
    if (is_object($postarr)) {
        // non-escaped post was passed
        $postarr = get_object_vars($postarr);
        $postarr = wp_slash($postarr);
    }
    // First, get all of the original fields
    $post = get_post($postarr['ID'], ARRAY_A);
    if (is_null($post)) {
        if ($wp_error) {
            return new WP_Error('invalid_post', __('Invalid post ID.'));
        }
        return 0;
    }
    // Escape data pulled from DB.
    $post = wp_slash($post);
    // Passed post category list overwrites existing category list if not empty.
    if (isset($postarr['post_category']) && is_array($postarr['post_category']) && 0 != count($postarr['post_category'])) {
        $post_cats = $postarr['post_category'];
    } else {
        $post_cats = $post['post_category'];
    }
    // Drafts shouldn't be assigned a date unless explicitly done so by the user
    if (isset($post['post_status']) && in_array($post['post_status'], array('draft', 'pending', 'auto-draft')) && empty($postarr['edit_date']) && '0000-00-00 00:00:00' == $post['post_date_gmt']) {
        $clear_date = true;
    } else {
        $clear_date = false;
    }
    // Merge old and new fields with new fields overwriting old ones.
    $postarr = array_merge($post, $postarr);
    $postarr['post_category'] = $post_cats;
    if ($clear_date) {
        $postarr['post_date'] = current_time('mysql');
        $postarr['post_date_gmt'] = '';
    }
    if ($postarr['post_type'] == 'attachment') {
        return wp_insert_attachment($postarr);
    }
    return wp_insert_post($postarr, $wp_error);
}