diff --git a/src/wp-includes/navigation-fallback.php b/src/wp-includes/navigation-fallback.php index e5bcc168019d7..cfd92f07e880b 100644 --- a/src/wp-includes/navigation-fallback.php +++ b/src/wp-includes/navigation-fallback.php @@ -13,29 +13,44 @@ * Navigation Fallback REST endpoint. * * The endpoint may embed the full Navigation Menu object into the - * response as the `self` link. By default the Posts Controller - * will only exposes a limited subset of fields but the editor requires - * additional fields to be available in order to utilise the menu. + * response as the `self` link. By default, the Posts Controller + * will only expose a limited subset of fields but the editor requires + * additional fields to be available in order to utilize the menu. * * @since 6.3.0 * * @param array $schema the schema for the `wp_navigation` post. * @return array the modified schema. */ -function wp_add_fields_to_navigation_fallback_embeded_links( $schema ) { +function wp_add_fields_to_navigation_fallback_embedded_links( $schema ) { // Expose top level fields. $schema['properties']['status']['context'] = array_merge( $schema['properties']['status']['context'], array( 'embed' ) ); $schema['properties']['content']['context'] = array_merge( $schema['properties']['content']['context'], array( 'embed' ) ); - // Expose sub properties of content field. + /* + * Exposes sub properties of content field. + * These sub properties aren't exposed by the posts controller by default, + * for requests where context is `embed`. + * + * @see WP_REST_Posts_Controller::get_item_schema() + */ $schema['properties']['content']['properties']['raw']['context'] = array_merge( $schema['properties']['content']['properties']['raw']['context'], array( 'embed' ) ); $schema['properties']['content']['properties']['rendered']['context'] = array_merge( $schema['properties']['content']['properties']['rendered']['context'], array( 'embed' ) ); $schema['properties']['content']['properties']['block_version']['context'] = array_merge( $schema['properties']['content']['properties']['block_version']['context'], array( 'embed' ) ); + /* + * Exposes sub properties of title field. + * These sub properties aren't exposed by the posts controller by default, + * for requests where context is `embed`. + * + * @see WP_REST_Posts_Controller::get_item_schema() + */ + $schema['properties']['title']['properties']['raw']['context'] = array_merge( $schema['properties']['title']['properties']['raw']['context'], array( 'embed' ) ); + return $schema; } add_filter( 'rest_wp_navigation_item_schema', - 'wp_add_fields_to_navigation_fallback_embeded_links' + 'wp_add_fields_to_navigation_fallback_embedded_links' ); diff --git a/src/wp-settings.php b/src/wp-settings.php index f59e280f08deb..bc86b8a2e866e 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -347,6 +347,7 @@ require ABSPATH . WPINC . '/block-supports/spacing.php'; require ABSPATH . WPINC . '/block-supports/typography.php'; require ABSPATH . WPINC . '/block-supports/settings.php'; +require ABSPATH . WPINC . '/navigation-fallback.php'; require ABSPATH . WPINC . '/style-engine.php'; require ABSPATH . WPINC . '/style-engine/class-wp-style-engine.php'; require ABSPATH . WPINC . '/style-engine/class-wp-style-engine-css-declarations.php'; diff --git a/tests/phpunit/tests/rest-api/rest-navigation-fallback-controller.php b/tests/phpunit/tests/rest-api/rest-navigation-fallback-controller.php index 263547da5d09d..369c97dd621a8 100644 --- a/tests/phpunit/tests/rest-api/rest-navigation-fallback-controller.php +++ b/tests/phpunit/tests/rest-api/rest-navigation-fallback-controller.php @@ -143,6 +143,50 @@ public function test_adds_links() { $this->assertTrue( $links['self'][0]['attributes']['embeddable'], 'Self link should be embeddable.' ); } + /** + * Tests that the correct filters are applied to the context parameter. + * + * By default, the REST response for the Posts Controller will not return all fields + * when the context is set to 'embed'. Assert that correct additional fields are added + * to the embedded Navigation Post, when the navigation fallback endpoint + * is called with the `_embed` param. + * + * @ticket 58557 + * + * @covers wp_add_fields_to_navigation_fallback_embedded_links + * + * @since 6.3.0 Added Navigation Fallbacks endpoint. + */ + public function test_embedded_navigation_post_contains_required_fields() { + // First we'll use the navigation fallback to get a link to the navigation endpoint. + $request = new WP_REST_Request( 'GET', '/wp-block-editor/v1/navigation-fallback' ); + $response = rest_get_server()->dispatch( $request ); + $links = $response->get_links(); + + // Extract the navigation endpoint URL from the response. + $embedded_navigation_href = $links['self'][0]['href']; + preg_match( '/\?rest_route=(.*)/', $embedded_navigation_href, $matches ); + $navigation_endpoint = $matches[1]; + + // Fetch the "linked" navigation post from the endpoint, with the context parameter set to 'embed' to simulate fetching embedded links. + $request = new WP_REST_Request( 'GET', $navigation_endpoint ); + $request->set_param( 'context', 'embed' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + // Verify that the additional status field is present. + $this->assertArrayHasKey( 'status', $data, 'Response title should contain a "status" field.' ); + + // Verify that the additional content fields are present. + $this->assertArrayHasKey( 'content', $data, 'Response should contain a "content" field.' ); + $this->assertArrayHasKey( 'raw', $data['content'], 'Response content should contain a "raw" field.' ); + $this->assertArrayHasKey( 'rendered', $data['content'], 'Response content should contain a "rendered" field.' ); + $this->assertArrayHasKey( 'block_version', $data['content'], 'Response should contain a "block_version" field.' ); + + // Verify that the additional title.raw field is present. + $this->assertArrayHasKey( 'raw', $data['title'], 'Response title should contain a "raw" key.' ); + } + private function get_navigations_in_database() { $navs_in_db = new WP_Query( array( diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 64290ad64e1d4..27aa52edcc352 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -6682,7 +6682,8 @@ mockedApiResponse.Schema = { "description": "Title for the post, as it exists in the database.", "type": "string", "context": [ - "edit" + "edit", + "embed" ] }, "rendered": { @@ -6706,7 +6707,8 @@ mockedApiResponse.Schema = { "description": "Content for the post, as it exists in the database.", "type": "string", "context": [ - "edit" + "edit", + "embed" ] }, "rendered": { @@ -6714,7 +6716,8 @@ mockedApiResponse.Schema = { "type": "string", "context": [ "view", - "edit" + "edit", + "embed" ], "readonly": true }, @@ -6722,7 +6725,8 @@ mockedApiResponse.Schema = { "description": "Version of the content block format used by the post.", "type": "integer", "context": [ - "edit" + "edit", + "embed" ], "readonly": true }, @@ -6859,7 +6863,8 @@ mockedApiResponse.Schema = { "description": "Title for the post, as it exists in the database.", "type": "string", "context": [ - "edit" + "edit", + "embed" ] }, "rendered": { @@ -6883,7 +6888,8 @@ mockedApiResponse.Schema = { "description": "Content for the post, as it exists in the database.", "type": "string", "context": [ - "edit" + "edit", + "embed" ] }, "rendered": { @@ -6891,7 +6897,8 @@ mockedApiResponse.Schema = { "type": "string", "context": [ "view", - "edit" + "edit", + "embed" ], "readonly": true }, @@ -6899,7 +6906,8 @@ mockedApiResponse.Schema = { "description": "Version of the content block format used by the post.", "type": "integer", "context": [ - "edit" + "edit", + "embed" ], "readonly": true }, @@ -7192,7 +7200,8 @@ mockedApiResponse.Schema = { "description": "Title for the post, as it exists in the database.", "type": "string", "context": [ - "edit" + "edit", + "embed" ] }, "rendered": { @@ -7216,7 +7225,8 @@ mockedApiResponse.Schema = { "description": "Content for the post, as it exists in the database.", "type": "string", "context": [ - "edit" + "edit", + "embed" ] }, "rendered": { @@ -7224,7 +7234,8 @@ mockedApiResponse.Schema = { "type": "string", "context": [ "view", - "edit" + "edit", + "embed" ], "readonly": true }, @@ -7232,7 +7243,8 @@ mockedApiResponse.Schema = { "description": "Version of the content block format used by the post.", "type": "integer", "context": [ - "edit" + "edit", + "embed" ], "readonly": true },