diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index 838cd84a19921..64309565ec84c 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -1595,11 +1595,36 @@ function make_after_block_visitor( $hooked_blocks, $context, $callback = 'insert * to ensure consistent operation between PHP and JavaScript. * * @since 5.3.1 + * @since 6.8.2 Add $block_name parameter. * - * @param array $block_attributes Attributes object. + * @param array $block_attributes Attributes object. + * @param string|null $block_name Block name. Null if the block name is unknown. Optional. * @return string Serialized attributes. */ -function serialize_block_attributes( $block_attributes ) { +function serialize_block_attributes( $block_attributes, $block_name = null ) { + $attribute_definitions = null; + foreach ( $block_attributes as $attribute => $value ) { + if ( is_array( $value ) && empty( $value ) ) { + // An empty `array()` is encoded as `[]` in JSON. However, it's possible + // that the attribute type is really an object (associative array in PHP), + // so we need to check for that. + if ( null === $attribute_definitions ) { + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name ); + if ( $block_type && isset( $block_type->attributes ) ) { + $attribute_definitions = $block_type->attributes; + } else { + $attribute_definitions = array(); + } + } + if ( ! empty( $attribute_definitions ) && isset( $attribute_definitions[ $attribute ]['type'] ) ) { + $attribute_type = $attribute_definitions[ $attribute ]['type']; + if ( 'object' === $attribute_type ) { + $block_attributes[ $attribute ] = new stdClass(); + } + } + } + } + $encoded_attributes = wp_json_encode( $block_attributes, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); $encoded_attributes = preg_replace( '/--/', '\\u002d\\u002d', $encoded_attributes ); $encoded_attributes = preg_replace( '/', $serialized_block_name, $serialized_attributes ); diff --git a/tests/phpunit/tests/blocks/serialize.php b/tests/phpunit/tests/blocks/serialize.php index b4221ef3c5a15..5a529e60a04e1 100644 --- a/tests/phpunit/tests/blocks/serialize.php +++ b/tests/phpunit/tests/blocks/serialize.php @@ -10,6 +10,37 @@ * @group blocks */ class Tests_Blocks_Serialize extends WP_UnitTestCase { + /** + * Set up. + * + * @ticket 63325. + */ + public static function wpSetUpBeforeClass() { + register_block_type( + 'core/attributes', + array( + 'attributes' => array( + 'array' => array( + 'type' => 'array', + ), + 'object' => array( + 'type' => 'object', + ), + ), + ) + ); + } + + /** + * Tear down. + * + * @ticket 63325. + */ + public static function wpTearDownAfterClass() { + $registry = WP_Block_Type_Registry::get_instance(); + + $registry->unregister( 'core/attributes' ); + } /** * @dataProvider data_serialize_identity_from_parsed @@ -46,6 +77,12 @@ public function data_serialize_identity_from_parsed() { // Block with attribute values that should not be escaped. array( '' ), + + // Block with empty array attribute value. + array( '' ), + + // Block with empty object attribute value. + array( '' ), ); }