diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php index db88950faa481..92a175417fa9f 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php @@ -99,6 +99,29 @@ public function register_routes() { ), ) ); + + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/(?P[a-zA-Z0-9_-]+)/render', + array( + array( + 'methods' => WP_REST_Server::CREATABLE, + 'permission_callback' => array( $this, 'get_item_permissions_check' ), + 'callback' => array( $this, 'render' ), + 'args' => array( + 'id_base' => array( + 'description' => __( 'The widget type id.' ), + 'type' => 'string', + 'required' => true, + ), + 'instance' => array( + 'description' => __( 'Current instance settings of the widget.' ), + 'type' => 'object', + ), + ), + ), + ) + ); } /** @@ -397,6 +420,76 @@ public function get_item_schema() { return $this->add_additional_fields_schema( $this->schema ); } + /** + * Renders a single Legacy Widget and wraps it in a JSON-encodable array. + * + * @param WP_REST_Request $request Full details about the request. + * @since 5.8.1 + * + * @return array An array with rendered Legacy Widget HTML. + */ + public function render( $request ) { + return array( + 'preview' => $this->render_legacy_widget_preview_iframe( + $request['id_base'], + isset( $request['instance'] ) ? $request['instance'] : null + ), + ); + } + + /** + * Renders a page containing a preview of the requested Legacy Widget block. + * + * @param string $id_base The id base of the requested widget. + * @param array $instance The widget instance attributes. + * @since 5.8.1 + * + * @return string Rendered Legacy Widget block preview. + */ + private function render_legacy_widget_preview_iframe( $id_base, $instance ) { + if ( ! defined( 'IFRAME_REQUEST' ) ) { + define( 'IFRAME_REQUEST', true ); + } + + ob_start(); + ?> + + > + + + + + + + + > +
+
+ get_registered( 'core/legacy-widget' ); + echo $block->render( + array( + 'idBase' => $id_base, + 'instance' => $instance, + ) + ); + ?> +
+
+ + + + [a-zA-Z0-9_-]+)', '/wp/v2/widget-types/(?P[a-zA-Z0-9_-]+)/encode', + '/wp/v2/widget-types/(?P[a-zA-Z0-9_-]+)/render', '/wp/v2/widgets', '/wp/v2/widgets/(?P[\w\-]+)', '/wp-site-health/v1', diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 1e6eaefb063e4..564f20e4e1cfc 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -7067,6 +7067,31 @@ mockedApiResponse.Schema = { } ] }, + "/wp/v2/widget-types/(?P[a-zA-Z0-9_-]+)/render": { + "namespace": "wp/v2", + "methods": [ + "POST" + ], + "endpoints": [ + { + "methods": [ + "POST" + ], + "args": { + "id_base": { + "description": "The widget type id.", + "type": "string", + "required": true + }, + "instance": { + "description": "Current instance settings of the widget.", + "type": "object", + "required": false + } + } + } + ] + }, "/wp/v2/widgets": { "namespace": "wp/v2", "methods": [