diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index ed0c4d2dbf..f65ddb6c2e 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -262,3 +262,17 @@ function _recurse_do_blocks( $blocks, $all_blocks ) { return $rendered_content; } + +/** + * Returns the current version of the block format that the content string is using. + * + * If the string doesn't contain blocks, it returns 0. + * + * @since 5.0.0 + * + * @param string $content Content to test. + * @return int The block format version. + */ +function block_version( $content ) { + return has_blocks( $content ) ? 1 : 0; +} diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index 5002484ed8..93d2f0806f 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -1521,10 +1521,11 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { if ( in_array( 'content', $fields, true ) ) { $data['content'] = array( - 'raw' => $post->post_content, + 'raw' => $post->post_content, /** This filter is documented in wp-includes/post-template.php */ - 'rendered' => post_password_required( $post ) ? '' : apply_filters( 'the_content', $post->post_content ), - 'protected' => (bool) $post->post_password, + 'rendered' => post_password_required( $post ) ? '' : apply_filters( 'the_content', $post->post_content ), + 'protected' => (bool) $post->post_password, + 'block_version' => block_version( $post->post_content ), ); } @@ -2062,18 +2063,24 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database() ), 'properties' => array( - 'raw' => array( + 'raw' => array( 'description' => __( 'Content for the object, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), ), - 'rendered' => array( + 'rendered' => array( 'description' => __( 'HTML content for the object, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'protected' => array( + 'block_version' => array( + 'description' => __( 'Version of the content block format used by the object.' ), + 'type' => 'integer', + 'context' => array( 'edit' ), + 'readonly' => true, + ), + 'protected' => array( 'description' => __( 'Whether the content is protected with a password.' ), 'type' => 'boolean', 'context' => array( 'view', 'edit', 'embed' ), diff --git a/tests/phpunit/tests/blocks/block-type.php b/tests/phpunit/tests/blocks/block-type.php index 5eed28d0df..ba80ab69a9 100644 --- a/tests/phpunit/tests/blocks/block-type.php +++ b/tests/phpunit/tests/blocks/block-type.php @@ -310,4 +310,47 @@ class WP_Test_Block_Type extends WP_UnitTestCase { return json_encode( $attributes ); } + + /** + * Testing the block version. + * + * @ticket 43887 + * + * @dataProvider data_block_version + * + * @param string|null $content Content. + * @param int $expected Expected block version. + */ + public function test_block_version( $content, $expected ) { + $this->assertSame( $expected, block_version( $content ) ); + } + + /** + * Test cases for test_block_version(). + * + * @since 5.0.0 + * + * @return array { + * @type array { + * @type string|null Content. + * @type int Expected block version. + * } + * } + */ + public function data_block_version() { + return array( + // Null. + array( null, 0 ), + // Empty post content. + array( '', 0 ), + // Post content without blocks. + array( '
', 0 ), + // Post content with a block. + array( '', 1 ), + // Post content with a fake block. + array( '', 1 ), + // Post content with an invalid block. + array( '', 0 ), + ); + } } diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index ebb2d507dd..e952629bba 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -1554,6 +1554,65 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $this->assertTrue( $data['excerpt']['protected'] ); } + /** + * The post response should not have `block_version` when in view context. + * + * @ticket 43887 + */ + public function test_get_post_should_not_have_block_version_when_context_view() { + $post_id = $this->factory->post->create( + array( + 'post_content' => '', + ) + ); + + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $post_id ) ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertFalse( isset( $data['content']['block_version'] ) ); + } + + /** + * The post response should have `block_version` indicate that block content is present when in edit context. + * + * @ticket 43887 + */ + public function test_get_post_should_have_block_version_indicate_block_content_when_context_edit() { + wp_set_current_user( self::$editor_id ); + + $post_id = $this->factory->post->create( + array( + 'post_content' => '', + ) + ); + + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $post_id ) ); + $request->set_param( 'context', 'edit' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertSame( 1, $data['content']['block_version'] ); + } + + /** + * The post response should have `block_version` indicate that no block content is present when in edit context. + * + * @ticket 43887 + */ + public function test_get_post_should_have_block_version_indicate_no_block_content_when_context_edit() { + wp_set_current_user( self::$editor_id ); + + $post_id = $this->factory->post->create( + array( + 'post_content' => '
', + ) + ); + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $post_id ) ); + $request->set_param( 'context', 'edit' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertSame( 0, $data['content']['block_version'] ); + } + public function test_get_item_read_permission_custom_post_status_not_authenticated() { register_post_status( 'testpubstatus', array( 'public' => true ) ); register_post_status( 'testprivtatus', array( 'public' => false ) ); diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 9842de3244..ba068560d1 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -4350,13 +4350,13 @@ mockedApiResponse.postRevisions = [ "author": 359, "date": "2017-02-14T00:00:00", "date_gmt": "2017-02-14T00:00:00", - "id": 36734, + "id": 3153, "modified": "2017-02-14T00:00:00", "modified_gmt": "2017-02-14T00:00:00", - "parent": 36733, - "slug": "36733-revision-v1", + "parent": 3152, + "slug": "3152-revision-v1", "guid": { - "rendered": "http://example.org/?p=36734" + "rendered": "http://example.org/?p=3153" }, "title": { "rendered": "REST API Client Fixture: Post" @@ -4370,7 +4370,7 @@ mockedApiResponse.postRevisions = [ "_links": { "parent": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/posts/36733" + "href": "http://example.org/index.php?rest_route=/wp/v2/posts/3152" } ] } @@ -4405,13 +4405,13 @@ mockedApiResponse.postAutosaves = [ "author": 359, "date": "2017-02-14T00:00:00", "date_gmt": "2017-02-14T00:00:00", - "id": 36735, + "id": 3154, "modified": "2017-02-14T00:00:00", "modified_gmt": "2017-02-14T00:00:00", - "parent": 36733, - "slug": "36733-autosave-v1", + "parent": 3152, + "slug": "3152-autosave-v1", "guid": { - "rendered": "http://example.org/?p=36735" + "rendered": "http://example.org/?p=3154" }, "title": { "rendered": "" @@ -4425,7 +4425,7 @@ mockedApiResponse.postAutosaves = [ "_links": { "parent": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/posts/36733" + "href": "http://example.org/index.php?rest_route=/wp/v2/posts/3152" } ] } @@ -4436,13 +4436,13 @@ mockedApiResponse.autosave = { "author": 359, "date": "2017-02-14T00:00:00", "date_gmt": "2017-02-14T00:00:00", - "id": 36735, + "id": 3154, "modified": "2017-02-14T00:00:00", "modified_gmt": "2017-02-14T00:00:00", - "parent": 36733, - "slug": "36733-autosave-v1", + "parent": 3152, + "slug": "3152-autosave-v1", "guid": { - "rendered": "http://example.org/?p=36735" + "rendered": "http://example.org/?p=3154" }, "title": { "rendered": "" @@ -4610,13 +4610,13 @@ mockedApiResponse.pageRevisions = [ "author": 359, "date": "2017-02-14T00:00:00", "date_gmt": "2017-02-14T00:00:00", - "id": 36737, + "id": 3156, "modified": "2017-02-14T00:00:00", "modified_gmt": "2017-02-14T00:00:00", - "parent": 36736, - "slug": "36736-revision-v1", + "parent": 3155, + "slug": "3155-revision-v1", "guid": { - "rendered": "http://example.org/?p=36737" + "rendered": "http://example.org/?p=3156" }, "title": { "rendered": "REST API Client Fixture: Page" @@ -4630,7 +4630,7 @@ mockedApiResponse.pageRevisions = [ "_links": { "parent": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/pages/36736" + "href": "http://example.org/index.php?rest_route=/wp/v2/pages/3155" } ] } @@ -4665,13 +4665,13 @@ mockedApiResponse.pageAutosaves = [ "author": 359, "date": "2017-02-14T00:00:00", "date_gmt": "2017-02-14T00:00:00", - "id": 36738, + "id": 3157, "modified": "2017-02-14T00:00:00", "modified_gmt": "2017-02-14T00:00:00", - "parent": 36736, - "slug": "36736-autosave-v1", + "parent": 3155, + "slug": "3155-autosave-v1", "guid": { - "rendered": "http://example.org/?p=36738" + "rendered": "http://example.org/?p=3157" }, "title": { "rendered": "" @@ -4685,7 +4685,7 @@ mockedApiResponse.pageAutosaves = [ "_links": { "parent": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/pages/36736" + "href": "http://example.org/index.php?rest_route=/wp/v2/pages/3155" } ] } @@ -4696,13 +4696,13 @@ mockedApiResponse.pageAutosave = { "author": 359, "date": "2017-02-14T00:00:00", "date_gmt": "2017-02-14T00:00:00", - "id": 36738, + "id": 3157, "modified": "2017-02-14T00:00:00", "modified_gmt": "2017-02-14T00:00:00", - "parent": 36736, - "slug": "36736-autosave-v1", + "parent": 3155, + "slug": "3155-autosave-v1", "guid": { - "rendered": "http://example.org/?p=36738" + "rendered": "http://example.org/?p=3157" }, "title": { "rendered": ""