From 8ef1b05bfe59a61645dc36e163a494612b30b262 Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Wed, 21 Nov 2018 14:34:09 +0000 Subject: [PATCH] REST API: Always include `title.raw`/`content.raw` for Blocks in `context=view`. Demarcations for reusable blocks are always expected to be accessible by clients. Props noisysocks, youknowriad. See #45145 for the patch, #45098 for the original ticket. git-svn-id: https://develop.svn.wordpress.org/branches/5.0@43917 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-rest-blocks-controller.php | 53 +++++++++++++++++ .../tests/rest-api/rest-blocks-controller.php | 59 +++++++++++++------ 2 files changed, 95 insertions(+), 17 deletions(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-blocks-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-blocks-controller.php index 66a2e7adad..a523764dc5 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-blocks-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-blocks-controller.php @@ -36,4 +36,57 @@ class WP_REST_Blocks_Controller extends WP_REST_Posts_Controller { return parent::check_read_permission( $post ); } + + /** + * Filters a response based on the context defined in the schema. + * + * @since 5.0.0 + * + * @param array $data Response data to fiter. + * @param string $context Context defined in the schema. + * @return array Filtered response. + */ + public function filter_response_by_context( $data, $context ) { + $data = parent::filter_response_by_context( $data, $context ); + + /* + * Remove `title.rendered` and `content.rendered` from the response. It + * doesn't make sense for a reusable block to have rendered content on its + * own, since rendering a block requires it to be inside a post or a page. + */ + unset( $data['title']['rendered'] ); + unset( $data['content']['rendered'] ); + + return $data; + } + + /** + * Retrieves the block's schema, conforming to JSON Schema. + * + * @since 5.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() { + $schema = parent::get_item_schema(); + + /* + * Allow all contexts to access `title.raw` and `content.raw`. Clients always + * need the raw markup of a reusable block to do anything useful, e.g. parse + * it or display it in an editor. + */ + $schema['properties']['title']['properties']['raw']['context'] = array( 'view', 'edit' ); + $schema['properties']['content']['properties']['raw']['context'] = array( 'view', 'edit' ); + + /* + * Remove `title.rendered` and `content.rendered` from the schema. It doesn’t + * make sense for a reusable block to have rendered content on its own, since + * rendering a block requires it to be inside a post or a page. + */ + unset( $schema['properties']['title']['properties']['rendered'] ); + unset( $schema['properties']['content']['properties']['rendered'] ); + + return $schema; + } + } diff --git a/tests/phpunit/tests/rest-api/rest-blocks-controller.php b/tests/phpunit/tests/rest-api/rest-blocks-controller.php index 70798b2756..1c77633f0b 100644 --- a/tests/phpunit/tests/rest-api/rest-blocks-controller.php +++ b/tests/phpunit/tests/rest-api/rest-blocks-controller.php @@ -29,13 +29,13 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { protected static $post_id; /** - * Our fake user's ID. + * Our fake user IDs, keyed by their role. * * @since 5.0.0 * - * @var int + * @var array */ - protected static $user_id; + protected static $user_ids; /** * Create fake data before our tests run. @@ -50,14 +50,14 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { 'post_type' => 'wp_block', 'post_status' => 'publish', 'post_title' => 'My cool block', - 'post_content' => '

Hello!

', + 'post_content' => '

Hello!

', ) ); - self::$user_id = $factory->user->create( - array( - 'role' => 'editor', - ) + self::$user_ids = array( + 'editor' => $factory->user->create( array( 'role' => 'editor' ) ), + 'author' => $factory->user->create( array( 'role' => 'author' ) ), + 'contributor' => $factory->user->create( array( 'role' => 'contributor' ) ), ); } @@ -69,7 +69,9 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { public static function wpTearDownAfterClass() { wp_delete_post( self::$post_id ); - self::delete_user( self::$user_id ); + foreach ( self::$user_ids as $user_id ) { + self::delete_user( $user_id ); + } } /** @@ -114,7 +116,7 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { */ public function test_capabilities( $action, $role, $expected_status ) { if ( $role ) { - $user_id = $this->factory->user->create( array( 'role' => $role ) ); + $user_id = self::$user_ids[ $role ]; wp_set_current_user( $user_id ); } else { wp_set_current_user( 0 ); @@ -126,7 +128,7 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { $request->set_body_params( array( 'title' => 'Test', - 'content' => '

Test

', + 'content' => '

Test

', ) ); @@ -149,7 +151,7 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { 'post_type' => 'wp_block', 'post_status' => 'publish', 'post_title' => 'My cool block', - 'post_content' => '

Hello!

', + 'post_content' => '

Hello!

', 'post_author' => $user_id, ) ); @@ -158,7 +160,7 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { $request->set_body_params( array( 'title' => 'Test', - 'content' => '

Test

', + 'content' => '

Test

', ) ); @@ -179,7 +181,7 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { $request->set_body_params( array( 'title' => 'Test', - 'content' => '

Test

', + 'content' => '

Test

', ) ); @@ -196,9 +198,32 @@ class REST_Blocks_Controller_Test extends WP_UnitTestCase { default: $this->fail( "'$action' is not a valid action." ); } + } - if ( isset( $user_id ) ) { - self::delete_user( $user_id ); - } + /** + * Check that the raw title and content of a block can be accessed when there + * is no set schema, and that the rendered content of a block is not included + * in the response. + */ + public function test_content() { + wp_set_current_user( self::$user_ids['author'] ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/blocks/' . self::$post_id ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertEquals( + array( + 'raw' => 'My cool block', + ), + $data['title'] + ); + $this->assertEquals( + array( + 'raw' => '

Hello!

', + 'protected' => false, + ), + $data['content'] + ); } }