Skip to content

Commit 9340284

Browse files
Dan Luudmsnell
authored andcommitted
RTC: Backport fix to prevent autosaves from losing content.
This is a companion change to WordPress/gutenberg#77865.
1 parent 75b4131 commit 9340284

2 files changed

Lines changed: 107 additions & 3 deletions

File tree

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ public function create_item( $request ) {
229229
require_once ABSPATH . 'wp-admin/includes/post.php';
230230
}
231231

232-
$post_lock = wp_check_post_lock( $post->ID );
233-
$is_draft = 'draft' === $post->post_status || 'auto-draft' === $post->post_status;
232+
$post_lock = wp_check_post_lock( $post->ID );
233+
$is_auto_draft = 'auto-draft' === $post->post_status;
234+
$is_draft = 'draft' === $post->post_status || $is_auto_draft;
234235

235236
/*
236237
* In the context of real-time collaboration, all peers are effectively
@@ -256,10 +257,19 @@ public function create_item( $request ) {
256257
*/
257258
$is_collaboration_enabled = wp_is_collaboration_enabled();
258259

259-
if ( $is_draft && (int) $post->post_author === $user_id && ! $post_lock && ! $is_collaboration_enabled ) {
260+
if (
261+
$is_draft &&
262+
(int) $post->post_author === $user_id &&
263+
! $post_lock &&
264+
( ! $is_collaboration_enabled || $is_auto_draft )
265+
) {
260266
/*
261267
* Draft posts for the same author: autosaving updates the post and does not create a revision.
262268
* Convert the post object to an array and add slashes, wp_update_post() expects escaped array.
269+
*
270+
* Auto-drafts must still be promoted to drafts when collaboration is enabled so that a new post
271+
* survives URL loss and appears in Drafts. Regular draft autosaves remain revisions under
272+
* collaboration to keep the saved post from diverging from the persisted CRDT document.
263273
*/
264274
$autosave_id = wp_update_post( wp_slash( (array) $prepared_post ), true );
265275
} else {
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
/**
3+
* Tests for the collaboration autosaves REST controller override.
4+
*
5+
* @package gutenberg
6+
* @subpackage Collaboration
7+
*
8+
* @group collaboration
9+
* @group restapi
10+
*/
11+
class Tests_Collaboration_RestAutosavesController extends WP_UnitTestCase {
12+
13+
protected static int $author_id;
14+
15+
public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
16+
self::$author_id = $factory->user->create( array( 'role' => 'author' ) );
17+
}
18+
19+
public static function wpTearDownAfterClass() {
20+
self::delete_user( self::$author_id );
21+
delete_option( 'wp_collaboration_enabled' );
22+
}
23+
24+
public function set_up() {
25+
parent::set_up();
26+
wp_set_current_user( self::$author_id );
27+
}
28+
29+
/**
30+
* Creates an empty auto-draft post.
31+
*
32+
* @return int Post ID.
33+
*/
34+
private function create_auto_draft(): int {
35+
return self::factory()->post->create(
36+
array(
37+
'post_author' => self::$author_id,
38+
'post_content' => '',
39+
'post_status' => 'auto-draft',
40+
'post_title' => 'Auto Draft',
41+
'post_type' => 'post',
42+
)
43+
);
44+
}
45+
46+
/**
47+
* Dispatches an autosave request for a post.
48+
*
49+
* @param int $post_id Post ID.
50+
* @param string $title Autosaved post title.
51+
* @param string $content Autosaved post content.
52+
* @return WP_REST_Response Autosave response.
53+
*/
54+
private function dispatch_autosave( int $post_id, string $title, string $content ): WP_REST_Response {
55+
$request = new WP_REST_Request( 'POST', "/wp/v2/posts/{$post_id}/autosaves" );
56+
$request->set_param( 'title', $title );
57+
$request->set_param( 'content', $content );
58+
$request->set_param( 'status', 'draft' );
59+
60+
return rest_get_server()->dispatch( $request );
61+
}
62+
63+
public function test_auto_draft_autosave_promotes_parent_post_when_collaboration_is_disabled() {
64+
update_option( 'wp_collaboration_enabled', 0 );
65+
66+
$post_id = $this->create_auto_draft();
67+
$title = 'No RTC autosaved title';
68+
$content = '<!-- wp:paragraph --><p>No RTC autosaved content</p><!-- /wp:paragraph -->';
69+
70+
$response = $this->dispatch_autosave( $post_id, $title, $content );
71+
72+
$this->assertSame( 200, $response->get_status() );
73+
$post = get_post( $post_id );
74+
$this->assertSame( 'draft', $post->post_status );
75+
$this->assertSame( $title, $post->post_title );
76+
$this->assertSame( $content, $post->post_content );
77+
}
78+
79+
public function test_auto_draft_autosave_promotes_parent_post_when_collaboration_is_enabled() {
80+
update_option( 'wp_collaboration_enabled', 1 );
81+
82+
$post_id = $this->create_auto_draft();
83+
$title = 'RTC autosaved title';
84+
$content = '<!-- wp:paragraph --><p>RTC autosaved content</p><!-- /wp:paragraph -->';
85+
86+
$response = $this->dispatch_autosave( $post_id, $title, $content );
87+
88+
$this->assertSame( 200, $response->get_status() );
89+
$post = get_post( $post_id );
90+
$this->assertSame( 'draft', $post->post_status );
91+
$this->assertSame( $title, $post->post_title );
92+
$this->assertSame( $content, $post->post_content );
93+
}
94+
}

0 commit comments

Comments
 (0)