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 */