From 5460a98e22e2e23310444e153841d105971448f5 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 28 Sep 2023 11:06:36 -0600 Subject: [PATCH 1/7] Revisions: slash meta values for previews MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct an issue where meta values with values like a quote `”` could not be previewed. update_metadata expects data to be slashed. --- .../rest-api/endpoints/class-wp-rest-autosaves-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php index cbc3dc4c90da0..d14119133aff3 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php @@ -421,7 +421,7 @@ public function create_post_autosave( $post_data, array $meta = array() ) { if ( ! empty( $meta ) ) { foreach ( $revisioned_meta_keys as $meta_key ) { if ( isset( $meta[ $meta_key ] ) ) { - update_metadata( 'post', $revision_id, $meta_key, $meta[ $meta_key ] ); + update_metadata( 'post', $revision_id, $meta_key, wp_slash( $meta[ $meta_key ] ) ); } } } From 3a0c3c6b9ed0eaab839dc5cf913bba7f1ceb57d3 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 28 Sep 2023 15:02:51 -0600 Subject: [PATCH 2/7] Test autosaves controller works with meta, including slashed data --- .../tests/rest-api/rest-post-meta-fields.php | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php index c164c406b0159..6f1d7a45860a9 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -3468,7 +3468,58 @@ public function test_revisioned_single_post_meta_with_posts_endpoint_page_and_cp false, 'cpt', ), + // Include a test case with slashed data. + array( + 'Test string"', + 'Test string"', + 'page', + ), + ); + } + + /** + * Test autosaves controller works with meta, including slashed data + */ + public function test_autosaves_controller_works_with_meta() { + $meta = '[{\"content\":\"foot 1\",\"id\":\"fa97a10d-7401-42b9-ac54-df8f4510749a\"},{\"content\":\"fdddddoot 2\\\"\",\"id\":\"2216d0aa-34b8-42b4-b441-84dedc0406e0\"}]'; + $this->grant_write_permission(); + + // Create the custom meta. + register_post_meta( + 'post', + 'foo', + array( + 'show_in_rest' => true, + 'revisions_enabled' => true, + 'single' => true, + 'type' => 'string', + ) + ); + // Set up a new post. + $post_id = $this->factory->post->create( + array( + 'post_content' => 'initial content', + 'post_type' => 'post', + 'meta_input' => array( + 'foo' => 'foo', + ), + ) ); + + // Create an autosave with the test meta. + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d/autosaves', $post_id ) ); + $request->set_body_params( + array( + 'title' => 'Revision 1', + 'meta' => array( 'foo' => $meta ), + ) + ); + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status() ); + $data = $response->get_data(); + // Can json decode values. + $values = json_decode( wp_unslash( $data['meta']['foo'] ), true ); + $this->assertNotNull( $values ); } } From d2f0c3d07ece1b61dc54e866893c1abeadab3362 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 28 Sep 2023 15:03:10 -0600 Subject: [PATCH 3/7] Fix test naming --- tests/phpunit/tests/rest-api/rest-post-meta-fields.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php index 6f1d7a45860a9..a3d391074442a 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -3364,7 +3364,7 @@ public function test_revisioned_multiple_post_meta_with_posts_endpoint() { * Test post meta revisions with a custom post type and the page post type. * * @group revision - * @dataProvider test_revisioned_single_post_meta_with_posts_endpoint_page_and_cpt_data_provider + * @dataProvider data_revisioned_single_post_meta_with_posts_endpoint_page_and_cpt_data_provider */ public function test_revisioned_single_post_meta_with_posts_endpoint_page_and_cpt( $passed, $expected, $post_type ) { @@ -3451,7 +3451,7 @@ public function test_revisioned_single_post_meta_with_posts_endpoint_page_and_cp /** * Provide data for the meta revision checks. */ - public function test_revisioned_single_post_meta_with_posts_endpoint_page_and_cpt_data_provider() { + public function data_revisioned_single_post_meta_with_posts_endpoint_page_and_cpt_data_provider() { return array( array( 'Test string', From cc15512b74b83b8de6b1cbb45dce911c192cae95 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 28 Sep 2023 21:30:19 -0600 Subject: [PATCH 4/7] Cleanup --- tests/phpunit/tests/rest-api/rest-post-meta-fields.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php index a3d391074442a..5165c6abc90e5 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -3468,12 +3468,6 @@ public function data_revisioned_single_post_meta_with_posts_endpoint_page_and_cp false, 'cpt', ), - // Include a test case with slashed data. - array( - 'Test string"', - 'Test string"', - 'page', - ), ); } @@ -3521,5 +3515,9 @@ public function test_autosaves_controller_works_with_meta() { // Can json decode values. $values = json_decode( wp_unslash( $data['meta']['foo'] ), true ); $this->assertNotNull( $values ); + + // Clean up the post. + delete_post_meta( $post_id, 'foo' ); + unregister_post_meta( 'post', 'foo' ); } } From 6927209e425dac834183c5c45c0a62ac174d8906 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 28 Sep 2023 21:59:16 -0600 Subject: [PATCH 5/7] Remove problematic test for now --- .../tests/rest-api/rest-post-meta-fields.php | 50 ------------------- 1 file changed, 50 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php index 5165c6abc90e5..dcf39f59c99e6 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -3470,54 +3470,4 @@ public function data_revisioned_single_post_meta_with_posts_endpoint_page_and_cp ), ); } - - /** - * Test autosaves controller works with meta, including slashed data - */ - public function test_autosaves_controller_works_with_meta() { - $meta = '[{\"content\":\"foot 1\",\"id\":\"fa97a10d-7401-42b9-ac54-df8f4510749a\"},{\"content\":\"fdddddoot 2\\\"\",\"id\":\"2216d0aa-34b8-42b4-b441-84dedc0406e0\"}]'; - $this->grant_write_permission(); - - // Create the custom meta. - register_post_meta( - 'post', - 'foo', - array( - 'show_in_rest' => true, - 'revisions_enabled' => true, - 'single' => true, - 'type' => 'string', - ) - ); - - // Set up a new post. - $post_id = $this->factory->post->create( - array( - 'post_content' => 'initial content', - 'post_type' => 'post', - 'meta_input' => array( - 'foo' => 'foo', - ), - ) - ); - - // Create an autosave with the test meta. - $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d/autosaves', $post_id ) ); - $request->set_body_params( - array( - 'title' => 'Revision 1', - 'meta' => array( 'foo' => $meta ), - ) - ); - $response = rest_get_server()->dispatch( $request ); - $this->assertSame( 200, $response->get_status() ); - $data = $response->get_data(); - // Can json decode values. - $values = json_decode( wp_unslash( $data['meta']['foo'] ), true ); - $this->assertNotNull( $values ); - - // Clean up the post. - delete_post_meta( $post_id, 'foo' ); - unregister_post_meta( 'post', 'foo' ); - } } From 9da147948226b23ff6c0bb67e82b169eea0be0c0 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 29 Sep 2023 07:58:13 -0600 Subject: [PATCH 6/7] Reintroduce test to validate meta slashing for autosaves --- tests/phpunit/tests/post/metaRevisions.php | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/phpunit/tests/post/metaRevisions.php b/tests/phpunit/tests/post/metaRevisions.php index 74442b53c82ad..2f08d6dd93e4e 100644 --- a/tests/phpunit/tests/post/metaRevisions.php +++ b/tests/phpunit/tests/post/metaRevisions.php @@ -719,4 +719,61 @@ public function page_post_type_data_provider() { ), ); } + + /** + * Test autosaves controller works with meta, including slashed data + */ + public function test_autosaves_controller_works_with_meta() { + $meta = '[{\"content\":\"foot 1\",\"id\":\"fa97a10d-7401-42b9-ac54-df8f4510749a\"},{\"content\":\"fdddddoot 2\\\"\",\"id\":\"2216d0aa-34b8-42b4-b441-84dedc0406e0\"}]'; + $user = self::factory()->user->create( + array( + 'role' => 'editor', + ) + ); + wp_set_current_user( $user ); + + // Create the custom meta. + register_post_meta( + 'post', + 'foo', + array( + 'show_in_rest' => true, + 'revisions_enabled' => true, + 'single' => true, + 'type' => 'string', + ) + ); + + // Set up a new post. + $post_id = $this->factory->post->create( + array( + 'post_content' => 'initial content', + 'post_type' => 'post', + 'meta_input' => array( + 'foo' => 'foo', + ), + ) + ); + + // Create an autosave with the test meta. + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d/autosaves', $post_id ) ); + $request->add_header( 'Content-Type', 'application/x-www-form-urlencoded' ); + $request->set_body_params( + array( + 'title' => 'Revision 1', + 'meta' => array( 'foo' => $meta ), + ) + ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status() ); + $data = $response->get_data(); + // Can json decode values. + $v = json_decode( wp_unslash( $data['meta']['foo'] ), true ); + $this->assertNotNull( $v ); + + // Clean up. + unregister_post_meta( 'post', 'foo' ); + wp_delete_post( $post_id, true ); + } } From 413ac9fc4eb5299fe6bf738a8b57d98f6c2dc36a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 29 Sep 2023 08:52:41 -0600 Subject: [PATCH 7/7] Improve tests and move to tests/phpunit/tests/rest-api/rest-autosaves-controller.php --- tests/phpunit/tests/post/metaRevisions.php | 57 --------------- .../rest-api/rest-autosaves-controller.php | 70 +++++++++++++++++++ 2 files changed, 70 insertions(+), 57 deletions(-) diff --git a/tests/phpunit/tests/post/metaRevisions.php b/tests/phpunit/tests/post/metaRevisions.php index 2f08d6dd93e4e..74442b53c82ad 100644 --- a/tests/phpunit/tests/post/metaRevisions.php +++ b/tests/phpunit/tests/post/metaRevisions.php @@ -719,61 +719,4 @@ public function page_post_type_data_provider() { ), ); } - - /** - * Test autosaves controller works with meta, including slashed data - */ - public function test_autosaves_controller_works_with_meta() { - $meta = '[{\"content\":\"foot 1\",\"id\":\"fa97a10d-7401-42b9-ac54-df8f4510749a\"},{\"content\":\"fdddddoot 2\\\"\",\"id\":\"2216d0aa-34b8-42b4-b441-84dedc0406e0\"}]'; - $user = self::factory()->user->create( - array( - 'role' => 'editor', - ) - ); - wp_set_current_user( $user ); - - // Create the custom meta. - register_post_meta( - 'post', - 'foo', - array( - 'show_in_rest' => true, - 'revisions_enabled' => true, - 'single' => true, - 'type' => 'string', - ) - ); - - // Set up a new post. - $post_id = $this->factory->post->create( - array( - 'post_content' => 'initial content', - 'post_type' => 'post', - 'meta_input' => array( - 'foo' => 'foo', - ), - ) - ); - - // Create an autosave with the test meta. - $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d/autosaves', $post_id ) ); - $request->add_header( 'Content-Type', 'application/x-www-form-urlencoded' ); - $request->set_body_params( - array( - 'title' => 'Revision 1', - 'meta' => array( 'foo' => $meta ), - ) - ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertSame( 200, $response->get_status() ); - $data = $response->get_data(); - // Can json decode values. - $v = json_decode( wp_unslash( $data['meta']['foo'] ), true ); - $this->assertNotNull( $v ); - - // Clean up. - unregister_post_meta( 'post', 'foo' ); - wp_delete_post( $post_id, true ); - } } diff --git a/tests/phpunit/tests/rest-api/rest-autosaves-controller.php b/tests/phpunit/tests/rest-api/rest-autosaves-controller.php index 4108d05efc538..c268b74518561 100644 --- a/tests/phpunit/tests/rest-api/rest-autosaves-controller.php +++ b/tests/phpunit/tests/rest-api/rest-autosaves-controller.php @@ -341,6 +341,76 @@ public function test_update_item() { $this->check_create_autosave_response( $response ); } + public function test_update_item_with_meta() { + wp_set_current_user( self::$editor_id ); + $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); + $request->add_header( 'Content-Type', 'application/x-www-form-urlencoded' ); + register_post_meta( + 'post', + 'foo', + array( + 'show_in_rest' => true, + 'revisions_enabled' => true, + 'single' => true, + ) + ); + $params = $this->set_post_data( + array( + 'id' => self::$post_id, + 'author' => self::$contributor_id, + 'meta' => array( + 'foo' => 'bar', + ), + ) + ); + + $request->set_body_params( $params ); + $response = rest_get_server()->dispatch( $request ); + + $this->check_create_autosave_response( $response ); + + $data = $response->get_data(); + $this->assertArrayHasKey( 'meta', $data ); + $this->assertArrayHasKey( 'foo', $data['meta'] ); + $this->assertSame( 'bar', $data['meta']['foo'] ); + } + + public function test_update_item_with_json_meta() { + $meta = '[{\"content\":\"foot 1\",\"id\":\"fa97a10d-7401-42b9-ac54-df8f4510749a\"},{\"content\":\"fdddddoot 2\\\"\",\"id\":\"2216d0aa-34b8-42b4-b441-84dedc0406e0\"}]'; + wp_set_current_user( self::$editor_id ); + $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); + $request->add_header( 'Content-Type', 'application/x-www-form-urlencoded' ); + register_post_meta( + 'post', + 'foo', + array( + 'show_in_rest' => true, + 'revisions_enabled' => true, + 'single' => true, + ) + ); + $params = $this->set_post_data( + array( + 'id' => self::$post_id, + 'author' => self::$contributor_id, + 'meta' => array( + 'foo' => $meta, + ), + ) + ); + + $request->set_body_params( $params ); + $response = rest_get_server()->dispatch( $request ); + + $this->check_create_autosave_response( $response ); + + $data = $response->get_data(); + $this->assertArrayHasKey( 'meta', $data ); + $this->assertArrayHasKey( 'foo', $data['meta'] ); + $values = json_decode( wp_unslash( $data['meta']['foo'] ), true ); + $this->assertNotNull( $values ); + } + public function test_update_item_nopriv() { wp_set_current_user( self::$contributor_id );