Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block API: Preserve unknown, respect null in server attributes preparation #12003

Merged
merged 4 commits into from Nov 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 25 additions & 14 deletions lib/class-wp-block-type.php
Expand Up @@ -120,36 +120,47 @@ public function is_dynamic() {

/**
* Validates attributes against the current block schema, populating
* defaulted and missing values, and omitting unknown attributes.
* defaulted and missing values.
*
* @param array $attributes Original block attributes.
* @return array Prepared block attributes.
*/
public function prepare_attributes_for_render( $attributes ) {
// If there are no attribute definitions for the block type, skip
// processing and return vebatim.
if ( ! isset( $this->attributes ) ) {
return $attributes;
}

$prepared_attributes = array();
foreach ( $attributes as $attribute_name => $value ) {
// If the attribute is not defined by the block type, it cannot be
// validated.
if ( ! isset( $this->attributes[ $attribute_name ] ) ) {
continue;
}

foreach ( $this->attributes as $attribute_name => $schema ) {
$value = null;
$schema = $this->attributes[ $attribute_name ];

if ( isset( $attributes[ $attribute_name ] ) ) {
$is_valid = rest_validate_value_from_schema( $attributes[ $attribute_name ], $schema );
if ( ! is_wp_error( $is_valid ) ) {
$value = rest_sanitize_value_from_schema( $attributes[ $attribute_name ], $schema );
}
// Validate value by JSON schema. An invalid value should revert to
// its default, if one exists. This occurs by virtue of the missing
// attributes loop immediately following. If there is not a default
// assigned, the attribute value should remain unset.
$is_valid = rest_validate_value_from_schema( $value, $schema );
if ( is_wp_error( $is_valid ) ) {
unset( $attributes[ $attribute_name ] );
}
}

if ( is_null( $value ) && isset( $schema['default'] ) ) {
$value = $schema['default'];
// Populate values of any missing attributes for which the block type
// defines a default.
$missing_schema_attributes = array_diff_key( $this->attributes, $attributes );
foreach ( $missing_schema_attributes as $attribute_name => $schema ) {
if ( isset( $schema['default'] ) ) {
$attributes[ $attribute_name ] = $schema['default'];
}

$prepared_attributes[ $attribute_name ] = $value;
}

return $prepared_attributes;
return $attributes;
}

/**
Expand Down
1 change: 1 addition & 0 deletions lib/class-wp-rest-block-renderer-controller.php
Expand Up @@ -59,6 +59,7 @@ public function register_routes() {
'type' => 'object',
'additionalProperties' => false,
'properties' => $block_type->get_attributes(),
'default' => array(),
),
'post_id' => array(
'description' => __( 'ID of the post context.', 'gutenberg' ),
Expand Down
21 changes: 19 additions & 2 deletions phpunit/class-block-type-test.php
Expand Up @@ -139,7 +139,8 @@ function test_prepare_attributes() {
'wrongType' => 5,
'wrongTypeDefaulted' => 5,
/* missingDefaulted */
'undefined' => 'omit',
'undefined' => 'include',
'intendedNull' => null,
);

$block_type = new WP_Block_Type(
Expand All @@ -160,6 +161,10 @@ function test_prepare_attributes() {
'type' => 'string',
'default' => 'define',
),
'intendedNull' => array(
'type' => array( 'string', 'null' ),
'default' => 'wrong',
),
),
)
);
Expand All @@ -169,14 +174,26 @@ function test_prepare_attributes() {
$this->assertEquals(
array(
'correct' => 'include',
'wrongType' => null,
/* wrongType */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this change about?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's indicating that we expect that 'wrongType' will not appear in $prepared_attributes.

'wrongTypeDefaulted' => 'defaulted',
'missingDefaulted' => 'define',
'undefined' => 'include',
'intendedNull' => null,
),
$prepared_attributes
);
}

function test_prepare_attributes_none_defined() {
$attributes = array( 'exists' => 'keep' );

$block_type = new WP_Block_Type( 'core/dummy', array() );

$prepared_attributes = $block_type->prepare_attributes_for_render( $attributes );

$this->assertEquals( $attributes, $prepared_attributes );
}

function test_has_block_with_mixed_content() {
$mixed_post_content = 'before' .
'<!-- wp:core/dummy --><!-- /wp:core/dummy -->' .
Expand Down
4 changes: 3 additions & 1 deletion phpunit/class-rest-block-renderer-controller-test.php
Expand Up @@ -272,7 +272,9 @@ public function test_get_item_default_attributes() {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( self::$block_name );
$defaults = array();
foreach ( $block_type->attributes as $key => $attribute ) {
$defaults[ $key ] = isset( $attribute['default'] ) ? $attribute['default'] : null;
if ( isset( $attribute['default'] ) ) {
$defaults[ $key ] = $attribute['default'];
}
}

$request = new WP_REST_Request( 'GET', self::$rest_api_route . self::$block_name );
Expand Down