Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -370,57 +370,69 @@ public function get_item_schema() {
*
* @since 5.0.0
* @since 6.4.0 The `$meta` parameter was added.
* @since 7.1.0 Compares incoming data against the existing autosave instead
* of the published post.
Comment on lines +373 to +374
*
* @param array $post_data Associative array containing the post data.
* @param array $meta Associative array containing the post meta data.
* @return mixed The autosave revision ID or WP_Error.
*/
public function create_post_autosave( $post_data, array $meta = array() ) {

$post_id = (int) $post_data['ID'];
$post = get_post( $post_id );

if ( is_wp_error( $post ) ) {
return $post;
}

// Only create an autosave when it is different from the saved post.
$autosave_is_different = false;
$new_autosave = _wp_post_revision_data( $post_data, true );

foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $post ) ) ) as $field ) {
if ( normalize_whitespace( $new_autosave[ $field ] ) !== normalize_whitespace( $post->$field ) ) {
$autosave_is_different = true;
break;
}
}
$new_autosave = _wp_post_revision_data( $post_data, true );

// Check if meta values have changed.
if ( ! empty( $meta ) ) {
$revisioned_meta_keys = wp_post_revision_meta_keys( $post->post_type );
foreach ( $revisioned_meta_keys as $meta_key ) {
// get_metadata_raw is used to avoid retrieving the default value.
$old_meta = get_metadata_raw( 'post', $post_id, $meta_key, true );
$new_meta = $meta[ $meta_key ] ?? '';
}

if ( $new_meta !== $old_meta ) {
$user_id = get_current_user_id();

// Store one autosave per author. If there is already an autosave, overwrite it.
$old_autosave = wp_get_post_autosave( $post_id, $user_id );

if ( $old_autosave ) {
/*
* When an autosave revision already exists, compare the incoming data
* against its current field values rather than the published post. A field
* reverted to the published value - such as a title edit that was undone -
* must still overwrite any stale value in the existing autosave, otherwise
* consumers like Preview will display incorrect content indefinitely.
*/
Comment on lines +399 to +406
$autosave_is_different = false;
foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $post ) ) ) as $field ) {
if ( normalize_whitespace( $new_autosave[ $field ] ) !== normalize_whitespace( $old_autosave->$field ) ) {
$autosave_is_different = true;
break;
}
}
}

$user_id = get_current_user_id();
if ( ! $autosave_is_different && ! empty( $meta ) ) {
foreach ( $revisioned_meta_keys as $meta_key ) {
if ( ! array_key_exists( $meta_key, $meta ) ) {
continue;
}
Comment on lines +416 to +419

// Store one autosave per author. If there is already an autosave, overwrite it.
$old_autosave = wp_get_post_autosave( $post_id, $user_id );
$old_meta_value = get_metadata_raw( 'post', $old_autosave->ID, $meta_key, true );
$new_meta_value = $meta[ $meta_key ];

Comment on lines +415 to 423
if ( ! $autosave_is_different && $old_autosave ) {
// Nothing to save, return the existing autosave.
return $old_autosave->ID;
}
if ( $new_meta_value !== $old_meta_value ) {
$autosave_is_different = true;
break;
}
}
}

if ( ! $autosave_is_different ) {
// Nothing to save, return the existing autosave.
return $old_autosave->ID;
}

if ( $old_autosave ) {
$new_autosave['ID'] = $old_autosave->ID;
$new_autosave['post_author'] = $user_id;

Expand Down
34 changes: 34 additions & 0 deletions tests/phpunit/tests/rest-api/rest-autosaves-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -920,4 +920,38 @@ public static function data_head_request_with_specified_fields_returns_success_r
'get_items request' => array( '/wp/v2/posts/%d' ),
);
}

/**
* @ticket 65694
*/
public function test_create_post_autosave_updates_stale_field_on_revert() {
wp_set_current_user( self::$editor_id );

$post_id = $this->factory->post->create(
array(
'post_title' => 'Original Title',
'post_status' => 'publish',
'post_author' => self::$editor_id,
)
);

$controller = new WP_REST_Autosaves_Controller( 'post' );

$controller->create_post_autosave(
array(
'ID' => $post_id,
'post_title' => 'Original Title !!',
)
);

$controller->create_post_autosave(
array(
'ID' => $post_id,
'post_title' => 'Original Title',
)
);

$autosave = wp_get_post_autosave( $post_id, self::$editor_id );
$this->assertSame( 'Original Title', $autosave->post_title );
}
}
Loading