Skip to content

Commit 30175c9

Browse files
Revisions: only create autosave when content changed.
In the autosave REST API endpoint, avoid excessive database writes when an autosave is sent with content that is unchanged from the saved post. Before this fix, clicking "preview" in the editor (which uses the autosave feature) multiple times would cause an identical autosave entry to be deleted and re-created repeatedly. Props inwerpsel, aduth, mukesh27, ironprogrammer. Fixes #49532. git-svn-id: https://develop.svn.wordpress.org/trunk@55154 602fd350-edb4-49c9-b593-d223f7449a82
1 parent ece2e85 commit 30175c9

File tree

2 files changed

+53
-20
lines changed

2 files changed

+53
-20
lines changed

src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -360,35 +360,34 @@ public function create_post_autosave( $post_data ) {
360360
return $post;
361361
}
362362

363+
// Only create an autosave when it is different from the saved post.
364+
$autosave_is_different = false;
365+
$new_autosave = _wp_post_revision_data( $post_data, true );
366+
367+
foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $post ) ) ) as $field ) {
368+
if ( normalize_whitespace( $new_autosave[ $field ] ) !== normalize_whitespace( $post->$field ) ) {
369+
$autosave_is_different = true;
370+
break;
371+
}
372+
}
373+
374+
if ( ! $autosave_is_different ) {
375+
return new WP_Error(
376+
'rest_autosave_no_changes',
377+
__( 'There is nothing to save. The autosave and the post content are the same.' ),
378+
array( 'status' => 400 )
379+
);
380+
}
381+
363382
$user_id = get_current_user_id();
364383

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

368387
if ( $old_autosave ) {
369-
$new_autosave = _wp_post_revision_data( $post_data, true );
370388
$new_autosave['ID'] = $old_autosave->ID;
371389
$new_autosave['post_author'] = $user_id;
372390

373-
// If the new autosave has the same content as the post, delete the autosave.
374-
$autosave_is_different = false;
375-
376-
foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $post ) ) ) as $field ) {
377-
if ( normalize_whitespace( $new_autosave[ $field ] ) !== normalize_whitespace( $post->$field ) ) {
378-
$autosave_is_different = true;
379-
break;
380-
}
381-
}
382-
383-
if ( ! $autosave_is_different ) {
384-
wp_delete_post_revision( $old_autosave->ID );
385-
return new WP_Error(
386-
'rest_autosave_no_changes',
387-
__( 'There is nothing to save. The autosave and the post content are the same.' ),
388-
array( 'status' => 400 )
389-
);
390-
}
391-
392391
/** This filter is documented in wp-admin/post.php */
393392
do_action( 'wp_creating_autosave', $new_autosave );
394393

tests/phpunit/tests/rest-api/rest-autosaves-controller.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,4 +674,38 @@ public function test_rest_autosave_draft_post_locked_to_different_author() {
674674

675675
wp_delete_post( $post_id );
676676
}
677+
678+
/**
679+
* @ticket 49532
680+
*
681+
* @covers WP_REST_Autosaves_Controller::create_post_autosave
682+
*/
683+
public function test_rest_autosave_do_not_create_autosave_when_post_is_unchanged() {
684+
// Create a post by the editor.
685+
$post_data = array(
686+
'post_content' => 'Test post content',
687+
'post_title' => 'Test post title',
688+
'post_excerpt' => 'Test post excerpt',
689+
'post_author' => self::$editor_id,
690+
'post_status' => 'publish',
691+
);
692+
$post_id = wp_insert_post( $post_data );
693+
694+
wp_set_current_user( self::$editor_id );
695+
696+
$autosave_data = array(
697+
'post_content' => $post_data['post_content'],
698+
);
699+
700+
// Create autosaves response.
701+
$request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . $post_id . '/autosaves' );
702+
$request->add_header( 'content-type', 'application/json' );
703+
$request->set_body( wp_json_encode( $autosave_data ) );
704+
705+
$response = rest_get_server()->dispatch( $request );
706+
$data = $response->get_data();
707+
708+
$this->assertSame( 400, $response->get_status(), 'Response status is not 400.' );
709+
$this->assertSame( 'rest_autosave_no_changes', $data['code'], 'Response "code" is not "rest_autosave_no_changes"' );
710+
}
677711
}

0 commit comments

Comments
 (0)