From c11f6191434de7fdd633d94f28d38ed7e361e18a Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Sun, 12 Jul 2026 03:36:36 +0000 Subject: [PATCH] fix: normalize rich text block attribute schemas --- src/wp-includes/class-wp-block-type.php | 23 ++++++++++++- ...lass-wp-rest-block-renderer-controller.php | 4 +-- .../rest-block-renderer-controller.php | 32 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/class-wp-block-type.php b/src/wp-includes/class-wp-block-type.php index 86f0ea21a2a3c..a72d01162fa8d 100644 --- a/src/wp-includes/class-wp-block-type.php +++ b/src/wp-includes/class-wp-block-type.php @@ -501,6 +501,8 @@ public function prepare_attributes_for_render( $attributes ) { return $attributes; } + $attribute_schemas = $this->get_attributes_for_rest_schema(); + foreach ( $attributes as $attribute_name => $value ) { // If the attribute is not defined by the block type, it cannot be // validated. @@ -508,7 +510,7 @@ public function prepare_attributes_for_render( $attributes ) { continue; } - $schema = $this->attributes[ $attribute_name ]; + $schema = $attribute_schemas[ $attribute_name ]; // Validate value by JSON schema. An invalid value should revert to // its default, if one exists. This occurs by virtue of the missing @@ -590,6 +592,25 @@ public function get_attributes() { array(); } + /** + * Gets block attributes normalized for REST schema validation. + * + * @since 7.1.0 + * + * @return array Block attributes with REST-compatible types. + */ + public function get_attributes_for_rest_schema() { + $attributes = $this->get_attributes(); + + foreach ( $attributes as $attribute_name => $attribute_schema ) { + if ( isset( $attribute_schema['type'] ) && 'rich-text' === $attribute_schema['type'] ) { + $attributes[ $attribute_name ]['type'] = 'string'; + } + } + + return $attributes; + } + /** * Get block variations. * diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php index de7e147c38917..8b4b32ff8ad87 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php @@ -64,7 +64,7 @@ public function register_routes() { $schema = array( 'type' => 'object', - 'properties' => $block->get_attributes(), + 'properties' => $block->get_attributes_for_rest_schema(), 'additionalProperties' => false, ); @@ -80,7 +80,7 @@ public function register_routes() { $schema = array( 'type' => 'object', - 'properties' => $block->get_attributes(), + 'properties' => $block->get_attributes_for_rest_schema(), 'additionalProperties' => false, ); diff --git a/tests/phpunit/tests/rest-api/rest-block-renderer-controller.php b/tests/phpunit/tests/rest-api/rest-block-renderer-controller.php index 3573ecb6e0bea..4452d1b63932b 100644 --- a/tests/phpunit/tests/rest-api/rest-block-renderer-controller.php +++ b/tests/phpunit/tests/rest-api/rest-block-renderer-controller.php @@ -171,6 +171,9 @@ public function register_test_block() { 'type' => 'integer', ), ), + 'rich_text' => array( + 'type' => 'rich-text', + ), ), 'render_callback' => array( $this, 'render_test_block' ), ) @@ -421,6 +424,35 @@ public function test_get_item() { ); } + /** + * Tests rendering a block with a rich text attribute. + * + * @covers WP_REST_Block_Renderer_Controller::register_routes + */ + public function test_get_item_with_rich_text_attribute() { + wp_set_current_user( self::$user_id ); + + $request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name ); + $request->set_param( 'context', 'edit' ); + $request->set_param( + 'attributes', + array( + 'some_string' => 'some_value', + 'rich_text' => 'Example', + ) + ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertSame( 200, $response->get_status() ); + $this->assertSame( + array( + 'some_string' => 'some_value', + 'rich_text' => 'Example', + ), + json_decode( $response->get_data()['rendered'], true ) + ); + } + /** * Check filtering block output using the pre_render_block filter. *