Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -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( '/</', '\\u003c', $encoded_attributes );
Expand Down Expand Up @@ -1646,7 +1671,7 @@ function get_comment_delimited_block_content( $block_name, $block_attributes, $b
}

$serialized_block_name = strip_core_block_namespace( $block_name );
$serialized_attributes = empty( $block_attributes ) ? '' : serialize_block_attributes( $block_attributes ) . ' ';
$serialized_attributes = empty( $block_attributes ) ? '' : serialize_block_attributes( $block_attributes, $block_name ) . ' ';

if ( empty( $block_content ) ) {
return sprintf( '<!-- wp:%s %s/-->', $serialized_block_name, $serialized_attributes );
Expand Down
37 changes: 37 additions & 0 deletions tests/phpunit/tests/blocks/serialize.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -46,6 +77,12 @@ public function data_serialize_identity_from_parsed() {

// Block with attribute values that should not be escaped.
array( '<!-- wp:attributes {"key":"€1.00 / 3 for €2.00"} /-->' ),

// Block with empty array attribute value.
array( '<!-- wp:attributes {"array":[]} /-->' ),

// Block with empty object attribute value.
array( '<!-- wp:attributes {"object":{}} /-->' ),
);
}

Expand Down
Loading