diff --git a/src/wp-includes/class-wp-block-supports.php b/src/wp-includes/class-wp-block-supports.php
index ec5bc9c8d6846..247de79fe9658 100644
--- a/src/wp-includes/class-wp-block-supports.php
+++ b/src/wp-includes/class-wp-block-supports.php
@@ -181,9 +181,14 @@ function get_block_wrapper_attributes( $extra_attributes = array() ) {
// This is hardcoded on purpose.
// We only support a fixed list of attributes.
- $attributes_to_merge = array( 'style', 'class', 'id', 'aria-label' );
- $attributes = array();
- foreach ( $attributes_to_merge as $attribute_name ) {
+ $handled_attributes = array(
+ 'style' => true,
+ 'class' => true,
+ 'id' => false,
+ 'aria-label' => false,
+ );
+ $attributes = array();
+ foreach ( $handled_attributes as $attribute_name => $is_merged ) {
if ( empty( $new_attributes[ $attribute_name ] ) && empty( $extra_attributes[ $attribute_name ] ) ) {
continue;
}
@@ -198,11 +203,15 @@ function get_block_wrapper_attributes( $extra_attributes = array() ) {
continue;
}
- $attributes[ $attribute_name ] = $extra_attributes[ $attribute_name ] . ' ' . $new_attributes[ $attribute_name ];
+ if ( $is_merged ) {
+ $attributes[ $attribute_name ] = $extra_attributes[ $attribute_name ] . ' ' . $new_attributes[ $attribute_name ];
+ } else {
+ $attributes[ $attribute_name ] = $extra_attributes[ $attribute_name ];
+ }
}
foreach ( $extra_attributes as $attribute_name => $value ) {
- if ( ! in_array( $attribute_name, $attributes_to_merge, true ) ) {
+ if ( ! isset( $handled_attributes[ $attribute_name ] ) ) {
$attributes[ $attribute_name ] = $value;
}
}
diff --git a/tests/phpunit/tests/blocks/supportedStyles.php b/tests/phpunit/tests/blocks/supportedStyles.php
index c733b7218d8c5..f60ecadbc6d9c 100644
--- a/tests/phpunit/tests/blocks/supportedStyles.php
+++ b/tests/phpunit/tests/blocks/supportedStyles.php
@@ -90,37 +90,17 @@ private function get_content_from_block( $block ) {
/**
* Returns the rendered output for the current block.
*
- * @param array $block Block to render.
+ * @param array $block Block to render.
+ * @param array $extra_attributes Extra attributes to pass to get_block_wrapper_attributes().
* @return string Rendered output for the current block.
*/
- private function render_example_block( $block ) {
+ private function render_example_block( $block, $extra_attributes = array() ) {
WP_Block_Supports::init();
WP_Block_Supports::$block_to_render = $block;
- $wrapper_attributes = get_block_wrapper_attributes(
- array(
- 'class' => 'foo-bar-class',
- 'style' => 'test: style;',
- )
- );
+ $wrapper_attributes = get_block_wrapper_attributes( $extra_attributes );
return '
' . self::BLOCK_CONTENT . '
';
}
- /**
- * Runs assertions that the rendered output has expected class/style attrs.
- *
- * @param array $block Block to render.
- * @param string $expected_classes Expected output class attr string.
- * @param string $expected_styles Expected output styles attr string.
- */
- private function assert_styles_and_classes_match( $block, $expected_classes, $expected_styles ) {
- $styled_block = $this->render_example_block( $block );
- $class_list = $this->get_attribute_from_block( 'class', $styled_block );
- $style_list = $this->get_attribute_from_block( 'style', $styled_block );
-
- $this->assertSame( $expected_classes, $class_list, 'Class list does not match expected classes' );
- $this->assertSame( $expected_styles, $style_list, 'Style list does not match expected styles' );
- }
-
/**
* Runs assertions that the rendered output has expected content and class/style attrs.
*
@@ -129,7 +109,13 @@ private function assert_styles_and_classes_match( $block, $expected_classes, $ex
* @param string $expected_styles Expected output styles attr string.
*/
private function assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ) {
- $styled_block = $this->render_example_block( $block );
+ $styled_block = $this->render_example_block(
+ $block,
+ array(
+ 'class' => 'foo-bar-class',
+ 'style' => 'test: style;',
+ )
+ );
// Ensure blocks to not add extra whitespace.
$this->assertSame( $styled_block, trim( $styled_block ) );
@@ -158,7 +144,13 @@ private function assert_content_and_styles_and_classes_match( $block, $expected_
* @param string $expected_aria_label Expected output aria-label attr string.
*/
private function assert_content_and_aria_label_match( $block, $expected_aria_label ) {
- $styled_block = $this->render_example_block( $block );
+ $styled_block = $this->render_example_block(
+ $block,
+ array(
+ 'class' => 'foo-bar-class',
+ 'style' => 'test: style;',
+ )
+ );
$content = $this->get_content_from_block( $styled_block );
$this->assertSame( self::BLOCK_CONTENT, $content, 'Block content does not match expected content' );
@@ -201,6 +193,43 @@ public function test_named_color_support() {
$this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles );
}
+ /**
+ * Ensures that class and style attributes from extra attributes and block supports are merged.
+ *
+ * @ticket 64603
+ * @covers WP_Block_Supports::get_block_wrapper_attributes()
+ */
+ public function test_block_wrapper_attributes_merge() {
+ $block_type_settings = array(
+ 'attributes' => array(),
+ 'supports' => array(
+ 'color' => true,
+ ),
+ 'render_callback' => true,
+ );
+ $this->register_block_type( 'core/example-merge', $block_type_settings );
+
+ $block = array(
+ 'blockName' => 'core/example-merge',
+ 'attrs' => array(
+ 'style' => array(
+ 'color' => array(
+ 'text' => '#000',
+ 'background' => '#fff',
+ ),
+ ),
+ ),
+ 'innerBlock' => array(),
+ 'innerContent' => array(),
+ 'innerHTML' => array(),
+ );
+
+ $expected_styles = 'test: style;color:#000;background-color:#fff;';
+ $expected_classes = 'foo-bar-class wp-block-example-merge has-text-color has-background';
+
+ $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles );
+ }
+
/**
* Tests color support for custom colors.
*/
@@ -728,6 +757,53 @@ public function test_aria_label_support() {
$this->assert_content_and_aria_label_match( $block, 'Label' );
}
+ /**
+ * Ensures that user-provided attributes override the attributes generated by block supports.
+ *
+ * @ticket 64603
+ * @covers WP_Block_Supports::get_block_wrapper_attributes()
+ */
+ public function test_block_wrapper_attributes_prefer_user_id_and_aria_label_over_generated() {
+ $block_type_settings = array(
+ 'attributes' => array(),
+ 'supports' => array(
+ 'ariaLabel' => true,
+ 'anchor' => true,
+ ),
+ );
+ $this->register_block_type( 'core/example-override', $block_type_settings );
+
+ $block = array(
+ 'blockName' => 'core/example-override',
+ 'attrs' => array(
+ 'ariaLabel' => 'Generated label',
+ 'anchor' => 'generated-id',
+ ),
+ 'innerBlock' => array(),
+ 'innerContent' => array(),
+ 'innerHTML' => array(),
+ );
+
+ $styled_block = $this->render_example_block(
+ $block,
+ array(
+ 'aria-label' => 'User label',
+ 'id' => 'user-id',
+ )
+ );
+
+ $this->assertSame(
+ 'User label',
+ $this->get_attribute_from_block( 'aria-label', $styled_block ),
+ 'Aria-label should prefer user-provided value over generated one'
+ );
+ $this->assertSame(
+ 'user-id',
+ $this->get_attribute_from_block( 'id', $styled_block ),
+ 'Id should prefer user-provided value over generated one'
+ );
+ }
+
/**
* Ensures libxml_internal_errors is being used instead of @ warning suppression
*/