diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php index 9ce7e2b3df66a..db1be197e5ab4 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php @@ -47,6 +47,7 @@ public function __construct() { * Registers the controller's routes. * * @since 6.3.0 + * @since 6.5.0 Added route to fetch individual global styles revisions. */ public function register_routes() { register_rest_route( @@ -68,6 +69,32 @@ public function register_routes() { 'schema' => array( $this, 'get_public_item_schema' ), ) ); + + register_rest_route( + $this->namespace, + '/' . $this->parent_base . '/(?P[\d]+)/' . $this->rest_base . '/(?P[\d]+)', + array( + 'args' => array( + 'parent' => array( + 'description' => __( 'The ID for the parent of the global styles revision.' ), + 'type' => 'integer', + ), + 'id' => array( + 'description' => __( 'Unique identifier for the global styles revision.' ), + 'type' => 'integer', + ), + ), + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_item' ), + 'permission_callback' => array( $this, 'get_item_permissions_check' ), + 'args' => array( + 'context' => $this->get_context_param( array( 'default' => 'view' ) ), + ), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); } /** @@ -241,6 +268,56 @@ public function get_items( $request ) { return $response; } + /** + * Retrieves one global styles revision from the collection. + * + * @since 6.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item( $request ) { + $parent = $this->get_parent( $request['parent'] ); + if ( is_wp_error( $parent ) ) { + return $parent; + } + + $revision = $this->get_revision( $request['id'] ); + if ( is_wp_error( $revision ) ) { + return $revision; + } + + $response = $this->prepare_item_for_response( $revision, $request ); + return rest_ensure_response( $response ); + } + + /** + * Gets the global styles revision, if the ID is valid. + * + * @since 6.5.0 + * + * @param int $id Supplied ID. + * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise. + */ + protected function get_revision( $id ) { + $error = new WP_Error( + 'rest_post_invalid_id', + __( 'Invalid global styles revision ID.' ), + array( 'status' => 404 ) + ); + + if ( (int) $id <= 0 ) { + return $error; + } + + $revision = get_post( (int) $id ); + if ( empty( $revision ) || empty( $revision->ID ) || 'revision' !== $revision->post_type ) { + return $error; + } + + return $revision; + } + /** * Checks the post_date_gmt or modified_gmt and prepare any post or * modified date for single post output. diff --git a/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php b/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php index 30e5b983eae9c..3773b5fd1f9e4 100644 --- a/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php +++ b/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php @@ -226,6 +226,7 @@ public function set_up() { /** * @ticket 58524 + * @ticket 59810 * * @covers WP_REST_Global_Styles_Controller::register_routes */ @@ -236,6 +237,11 @@ public function test_register_routes() { $routes, 'Global style revisions based on the given parentID route does not exist.' ); + $this->assertArrayHasKey( + '/wp/v2/global-styles/(?P[\d]+)/revisions/(?P[\d]+)', + $routes, + 'Single global style revisions based on the given parentID and revision ID route does not exist.' + ); } /** @@ -304,6 +310,38 @@ public function test_get_items() { $this->check_get_revision_response( $data[2], $this->revision_1 ); } + /** + * @ticket 59810 + * + * @covers WP_REST_Global_Styles_Controller::get_item + */ + public function test_get_item() { + wp_set_current_user( self::$admin_id ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/' . $this->revision_1_id ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertSame( 200, $response->get_status(), 'Response status is 200.' ); + $this->check_get_revision_response( $data, $this->revision_1 ); + } + + /** + * @ticket 59810 + * + * @covers WP_REST_Global_Styles_Controller::get_revision + */ + public function test_get_item_invalid_revision_id_should_error() { + wp_set_current_user( self::$admin_id ); + + $expected_error = 'rest_post_invalid_id'; + $expected_status = 404; + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/20000001' ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertErrorResponse( $expected_error, $response, $expected_status ); + } + /** * @ticket 58524 * @@ -794,13 +832,6 @@ public function test_context_param() { // Controller does not implement test_context_param(). } - /** - * @doesNotPerformAssertions - */ - public function test_get_item() { - // Controller does not implement get_item(). - } - /** * @doesNotPerformAssertions */ diff --git a/tests/phpunit/tests/rest-api/rest-schema-setup.php b/tests/phpunit/tests/rest-api/rest-schema-setup.php index c53f887bc822c..3ff35260f0fb8 100644 --- a/tests/phpunit/tests/rest-api/rest-schema-setup.php +++ b/tests/phpunit/tests/rest-api/rest-schema-setup.php @@ -135,6 +135,7 @@ public function test_expected_routes_in_schema() { '/wp/v2/comments/(?P[\\d]+)', '/wp/v2/global-styles/(?P[\/\w-]+)', '/wp/v2/global-styles/(?P[\d]+)/revisions', + '/wp/v2/global-styles/(?P[\d]+)/revisions/(?P[\d]+)', '/wp/v2/global-styles/themes/(?P[\/\s%\w\.\(\)\[\]\@_\-]+)/variations', '/wp/v2/global-styles/themes/(?P[^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)', '/wp/v2/search', diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index ef8e53d4bb508..6c961548eb8e2 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -10044,6 +10044,42 @@ mockedApiResponse.Schema = { } ] }, + "/wp/v2/global-styles/(?P[\\d]+)/revisions/(?P[\\d]+)": { + "namespace": "wp/v2", + "methods": [ + "GET" + ], + "endpoints": [ + { + "methods": [ + "GET" + ], + "args": { + "parent": { + "description": "The ID for the parent of the global styles revision.", + "type": "integer", + "required": false + }, + "id": { + "description": "Unique identifier for the global styles revision.", + "type": "integer", + "required": false + }, + "context": { + "description": "Scope under which the request is made; determines fields present in response.", + "type": "string", + "enum": [ + "view", + "embed", + "edit" + ], + "default": "view", + "required": false + } + } + } + ] + }, "/wp/v2/global-styles/themes/(?P[\\/\\s%\\w\\.\\(\\)\\[\\]\\@_\\-]+)/variations": { "namespace": "wp/v2", "methods": [