From 3d7c9d28458b592618a31ea4edfe69f4115fcd69 Mon Sep 17 00:00:00 2001 From: USERSATOSHI Date: Mon, 8 Jun 2026 18:34:27 +0530 Subject: [PATCH 01/12] fix(editor): deduplicate wp-elements class names for identical blocks --- src/wp-includes/block-supports/elements.php | 13 +++- .../wpRenderElementsSupport.php | 68 +++++++++++++++++++ .../wpRenderElementsSupportStyles.php | 65 ++++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/block-supports/elements.php b/src/wp-includes/block-supports/elements.php index 374da09e8bc8c..5db91a2d0e945 100644 --- a/src/wp-includes/block-supports/elements.php +++ b/src/wp-includes/block-supports/elements.php @@ -16,7 +16,18 @@ * @return string The unique class name. */ function wp_get_elements_class_name( $block ) { - return 'wp-elements-' . md5( serialize( $block ) ); + static $seen_hashes = array(); + + $hash = md5( serialize( $block ) ); + + if ( isset( $seen_hashes[ $hash ] ) ) { + ++$seen_hashes[ $hash ]; + return 'wp-elements-' . md5( $hash . $seen_hashes[ $hash ] ); + } + + $seen_hashes[ $hash ] = 0; + + return 'wp-elements-' . $hash; } /** diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php index 9103fcba90b66..c035674685a48 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php @@ -105,6 +105,74 @@ public function test_elements_block_support_class( $color_settings, $elements_st ); } + /** + * Tests that duplicate blocks get distinct elements class names + * on their rendered markup to avoid CSS cascade conflicts. + * + * @ticket 65435 + * + * @covers ::wp_get_elements_class_name + */ + public function test_elements_block_support_class_with_duplicate_blocks() { + $this->test_block_name = 'test/element-block-supports'; + + register_block_type( + $this->test_block_name, + array( + 'api_version' => 3, + 'attributes' => array( + 'style' => array( + 'type' => 'object', + ), + ), + 'supports' => array( + 'color' => array( + 'link' => true, + ), + ), + ) + ); + + $block = array( + 'blockName' => $this->test_block_name, + 'attrs' => array( + 'style' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'var:preset|color|vivid-red', + ), + ), + ), + ), + ), + ); + + $block_markup = '

Hello WordPress!

'; + $block_one = wp_render_elements_support_styles( $block ); + $block_two = wp_render_elements_support_styles( $block ); + $markup_one = wp_render_elements_class_name( $block_markup, $block_one ); + $markup_two = wp_render_elements_class_name( $block_markup, $block_two ); + + $this->assertMatchesRegularExpression( + '/^

Hello WordPress<\/a>!<\/p>$/', + $markup_one, + 'First block should have wp-elements class applied' + ); + $this->assertMatchesRegularExpression( + '/^

Hello WordPress<\/a>!<\/p>$/', + $markup_two, + 'Second block should also have wp-elements class applied' + ); + + // Extract class names and verify they are different. + preg_match( '/wp-elements-([a-f0-9]{32})/', $markup_one, $match_one ); + preg_match( '/wp-elements-([a-f0-9]{32})/', $markup_two, $match_two ); + $this->assertNotEmpty( $match_one, 'First block class name should be extractable' ); + $this->assertNotEmpty( $match_two, 'Second block class name should be extractable' ); + $this->assertNotSame( $match_one[1], $match_two[1], 'Class names for identical blocks should be unique' ); + } + /** * Data provider. * diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php index 16ed26fc9c7bc..31213c59afa6c 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php @@ -68,6 +68,71 @@ public function test_elements_block_support_styles( $color_settings, $elements_s ); } + /** + * Tests that identical blocks with different elements styles + * generate distinct class names to avoid CSS cascade conflicts. + * + * @ticket 65435 + * + * @covers ::wp_get_elements_class_name + */ + public function test_elements_block_support_styles_with_duplicate_blocks() { + $this->test_block_name = 'test/element-block-supports'; + + register_block_type( + $this->test_block_name, + array( + 'api_version' => 3, + 'attributes' => array( + 'style' => array( + 'type' => 'object', + ), + ), + 'supports' => array( + 'color' => array( + 'link' => true, + ), + ), + ) + ); + + $block = array( + 'blockName' => $this->test_block_name, + 'attrs' => array( + 'style' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'blue', + ), + ), + ), + ), + ), + ); + + // Process two identical blocks with the same elements styles. + wp_render_elements_support_styles( $block ); + wp_render_elements_support_styles( $block ); + $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); + + // Both rules should be present with distinct class names. + $this->assertMatchesRegularExpression( + '/\.wp-elements-[a-f0-9]{32} a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', + $actual_stylesheet, + 'First block element style should be present' + ); + $this->assertMatchesRegularExpression( + '/\.wp-elements-[a-f0-9]{32} a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', + $actual_stylesheet, + 'Second block element style should also be present' + ); + // Count the number of distinct class names to confirm uniqueness. + preg_match_all( '/\.wp-elements-([a-f0-9]{32})/', $actual_stylesheet, $matches ); + $unique_classes = array_unique( $matches[1] ); + $this->assertCount( 2, $unique_classes, 'Both blocks should produce distinct class names' ); + } + /** * Data provider. * From e508d122ca3a3f53a7ca7ea3745017125f24f2e7 Mon Sep 17 00:00:00 2001 From: USERSATOSHI Date: Mon, 8 Jun 2026 18:50:39 +0530 Subject: [PATCH 02/12] chore: fix phpcs errors --- .../tests/block-supports/wpRenderElementsSupport.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php index c035674685a48..fc0636864928b 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php @@ -148,11 +148,11 @@ public function test_elements_block_support_class_with_duplicate_blocks() { ), ); - $block_markup = '

Hello WordPress!

'; - $block_one = wp_render_elements_support_styles( $block ); - $block_two = wp_render_elements_support_styles( $block ); - $markup_one = wp_render_elements_class_name( $block_markup, $block_one ); - $markup_two = wp_render_elements_class_name( $block_markup, $block_two ); + $block_markup = '

Hello WordPress!

'; + $block_one = wp_render_elements_support_styles( $block ); + $block_two = wp_render_elements_support_styles( $block ); + $markup_one = wp_render_elements_class_name( $block_markup, $block_one ); + $markup_two = wp_render_elements_class_name( $block_markup, $block_two ); $this->assertMatchesRegularExpression( '/^

Hello WordPress<\/a>!<\/p>$/', From f457038a9ecd39a78a1dcaeca13f38dd94facfff Mon Sep 17 00:00:00 2001 From: USERSATOSHI Date: Wed, 10 Jun 2026 13:47:23 +0530 Subject: [PATCH 03/12] refactor: use wp_unique_prefixed_id for uniqueness instead --- src/wp-includes/block-supports/elements.php | 12 +-------- .../wpRenderElementsSupport.php | 18 ++++++------- .../wpRenderElementsSupportStyles.php | 26 +++++++++---------- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/wp-includes/block-supports/elements.php b/src/wp-includes/block-supports/elements.php index fa0e24c7aff8b..41fd62eaa5ff7 100644 --- a/src/wp-includes/block-supports/elements.php +++ b/src/wp-includes/block-supports/elements.php @@ -16,18 +16,8 @@ * @return string The unique class name. */ function wp_get_elements_class_name( $block ) { - static $seen_hashes = array(); - $hash = md5( serialize( $block ) ); - - if ( isset( $seen_hashes[ $hash ] ) ) { - ++$seen_hashes[ $hash ]; - return 'wp-elements-' . md5( $hash . $seen_hashes[ $hash ] ); - } - - $seen_hashes[ $hash ] = 0; - - return 'wp-elements-' . $hash; + return wp_unique_prefixed_id( 'wp-elements-' . $hash ); } /** diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php index 049dd516feb2b..831189b6af6fc 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php @@ -209,19 +209,19 @@ public function test_elements_block_support_class_with_duplicate_blocks() { $markup_two = wp_render_elements_class_name( $block_markup, $block_two ); $this->assertMatchesRegularExpression( - '/^

Hello WordPress<\/a>!<\/p>$/', + '/^

Hello WordPress<\/a>!<\/p>$/', $markup_one, 'First block should have wp-elements class applied' ); $this->assertMatchesRegularExpression( - '/^

Hello WordPress<\/a>!<\/p>$/', + '/^

Hello WordPress<\/a>!<\/p>$/', $markup_two, 'Second block should also have wp-elements class applied' ); // Extract class names and verify they are different. - preg_match( '/wp-elements-([a-f0-9]{32})/', $markup_one, $match_one ); - preg_match( '/wp-elements-([a-f0-9]{32})/', $markup_two, $match_two ); + preg_match( '/wp-elements-([a-f0-9]{32}[0-9]+)/', $markup_one, $match_one ); + preg_match( '/wp-elements-([a-f0-9]{32}[0-9]+)/', $markup_two, $match_two ); $this->assertNotEmpty( $match_one, 'First block class name should be extractable' ); $this->assertNotEmpty( $match_two, 'Second block class name should be extractable' ); $this->assertNotSame( $match_one[1], $match_two[1], 'Class names for identical blocks should be unique' ); @@ -306,7 +306,7 @@ public function data_elements_block_support_class() { 'button' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), 'link element styles apply class to wrapper' => array( 'color_settings' => array( 'link' => true ), @@ -314,7 +314,7 @@ public function data_elements_block_support_class() { 'link' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), 'heading element styles apply class to wrapper' => array( 'color_settings' => array( 'heading' => true ), @@ -322,7 +322,7 @@ public function data_elements_block_support_class() { 'heading' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), 'element styles apply class to wrapper when it has other classes' => array( 'color_settings' => array( 'link' => true ), @@ -330,7 +330,7 @@ public function data_elements_block_support_class() { 'link' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), 'element styles apply class to wrapper when it has other attributes' => array( 'color_settings' => array( 'link' => true ), @@ -338,7 +338,7 @@ public function data_elements_block_support_class() { 'link' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), ); } diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php index 31213c59afa6c..7707afee962fa 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php @@ -118,17 +118,17 @@ public function test_elements_block_support_styles_with_duplicate_blocks() { // Both rules should be present with distinct class names. $this->assertMatchesRegularExpression( - '/\.wp-elements-[a-f0-9]{32} a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', + '/\.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', $actual_stylesheet, 'First block element style should be present' ); $this->assertMatchesRegularExpression( - '/\.wp-elements-[a-f0-9]{32} a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', + '/\.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', $actual_stylesheet, 'Second block element style should also be present' ); // Count the number of distinct class names to confirm uniqueness. - preg_match_all( '/\.wp-elements-([a-f0-9]{32})/', $actual_stylesheet, $matches ); + preg_match_all( '/\.wp-elements-([a-f0-9]{32}[0-9]+)/', $actual_stylesheet, $matches ); $unique_classes = array_unique( $matches[1] ); $this->assertCount( 2, $unique_classes, 'Both blocks should produce distinct class names' ); } @@ -192,7 +192,7 @@ public function data_elements_block_support_styles() { 'elements_styles' => array( 'button' => array( 'color' => $color_styles ), ), - 'expected_styles' => '/^.wp-elements-[a-f0-9]{32} .wp-element-button, .wp-elements-[a-f0-9]{32} .wp-block-button__link' . $color_css_rules . '$/', + 'expected_styles' => '/^.wp-elements-[a-f0-9]{32}[0-9]+ .wp-element-button, .wp-elements-[a-f0-9]{32}[0-9]+ .wp-block-button__link' . $color_css_rules . '$/', ), 'link element styles are applied' => array( 'color_settings' => array( 'link' => true ), @@ -204,15 +204,15 @@ public function data_elements_block_support_styles() { ), ), ), - 'expected_styles' => '/^.wp-elements-[a-f0-9]{32} a:where\(:not\(.wp-element-button\)\)' . $color_css_rules . - '.wp-elements-[a-f0-9]{32} a:where\(:not\(.wp-element-button\)\):hover' . $color_css_rules . '$/', + 'expected_styles' => '/^.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(.wp-element-button\)\)' . $color_css_rules . + '.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(.wp-element-button\)\):hover' . $color_css_rules . '$/', ), 'generic heading element styles are applied' => array( 'color_settings' => array( 'heading' => true ), 'elements_styles' => array( 'heading' => array( 'color' => $color_styles ), ), - 'expected_styles' => '/^.wp-elements-[a-f0-9]{32} h1, .wp-elements-[a-f0-9]{32} h2, .wp-elements-[a-f0-9]{32} h3, .wp-elements-[a-f0-9]{32} h4, .wp-elements-[a-f0-9]{32} h5, .wp-elements-[a-f0-9]{32} h6' . $color_css_rules . '$/', + 'expected_styles' => '/^.wp-elements-[a-f0-9]{32}[0-9]+ h1, .wp-elements-[a-f0-9]{32}[0-9]+ h2, .wp-elements-[a-f0-9]{32}[0-9]+ h3, .wp-elements-[a-f0-9]{32}[0-9]+ h4, .wp-elements-[a-f0-9]{32}[0-9]+ h5, .wp-elements-[a-f0-9]{32}[0-9]+ h6' . $color_css_rules . '$/', ), 'individual heading element styles are applied' => array( 'color_settings' => array( 'heading' => true ), @@ -224,12 +224,12 @@ public function data_elements_block_support_styles() { 'h5' => array( 'color' => $color_styles ), 'h6' => array( 'color' => $color_styles ), ), - 'expected_styles' => '/^.wp-elements-[a-f0-9]{32} h1' . $color_css_rules . - '.wp-elements-[a-f0-9]{32} h2' . $color_css_rules . - '.wp-elements-[a-f0-9]{32} h3' . $color_css_rules . - '.wp-elements-[a-f0-9]{32} h4' . $color_css_rules . - '.wp-elements-[a-f0-9]{32} h5' . $color_css_rules . - '.wp-elements-[a-f0-9]{32} h6' . $color_css_rules . '$/', + 'expected_styles' => '/^.wp-elements-[a-f0-9]{32}[0-9]+ h1' . $color_css_rules . + '.wp-elements-[a-f0-9]{32}[0-9]+ h2' . $color_css_rules . + '.wp-elements-[a-f0-9]{32}[0-9]+ h3' . $color_css_rules . + '.wp-elements-[a-f0-9]{32}[0-9]+ h4' . $color_css_rules . + '.wp-elements-[a-f0-9]{32}[0-9]+ h5' . $color_css_rules . + '.wp-elements-[a-f0-9]{32}[0-9]+ h6' . $color_css_rules . '$/', ), ); } From 51313d82da1daa4d2cfcdd9fa2739ca54861b7f1 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 10 Jun 2026 11:01:44 -0700 Subject: [PATCH 04/12] Add return type hints --- src/wp-includes/block-supports/elements.php | 2 +- tests/phpunit/tests/block-supports/wpRenderElementsSupport.php | 2 +- .../tests/block-supports/wpRenderElementsSupportStyles.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/block-supports/elements.php b/src/wp-includes/block-supports/elements.php index 41fd62eaa5ff7..f429210db5a3e 100644 --- a/src/wp-includes/block-supports/elements.php +++ b/src/wp-includes/block-supports/elements.php @@ -15,7 +15,7 @@ * @param array $block Block object. * @return string The unique class name. */ -function wp_get_elements_class_name( $block ) { +function wp_get_elements_class_name( $block ): string { $hash = md5( serialize( $block ) ); return wp_unique_prefixed_id( 'wp-elements-' . $hash ); } diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php index 831189b6af6fc..0ad68606b2f01 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php @@ -167,7 +167,7 @@ public function test_elements_block_support_class_with_invalid_elements_prefix() * * @covers ::wp_get_elements_class_name */ - public function test_elements_block_support_class_with_duplicate_blocks() { + public function test_elements_block_support_class_with_duplicate_blocks(): void { $this->test_block_name = 'test/element-block-supports'; register_block_type( diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php index 7707afee962fa..02377898b7440 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php @@ -76,7 +76,7 @@ public function test_elements_block_support_styles( $color_settings, $elements_s * * @covers ::wp_get_elements_class_name */ - public function test_elements_block_support_styles_with_duplicate_blocks() { + public function test_elements_block_support_styles_with_duplicate_blocks(): void { $this->test_block_name = 'test/element-block-supports'; register_block_type( From 64124d04430855a83847ebe45d4d147fda6fd3e4 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 10 Jun 2026 11:07:26 -0700 Subject: [PATCH 05/12] Clarify types for $parsed_block being passed around --- src/wp-includes/block-supports/elements.php | 29 ++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/block-supports/elements.php b/src/wp-includes/block-supports/elements.php index f429210db5a3e..6f47b1fdc49a0 100644 --- a/src/wp-includes/block-supports/elements.php +++ b/src/wp-includes/block-supports/elements.php @@ -12,11 +12,19 @@ * @since 6.0.0 * @access private * - * @param array $block Block object. + * @param array $parsed_block Block object. * @return string The unique class name. + * + * @phpstan-param array{ + * attrs: array{ + * className?: string, + * ... + * }, + * ... + * } $parsed_block */ -function wp_get_elements_class_name( $block ): string { - $hash = md5( serialize( $block ) ); +function wp_get_elements_class_name( $parsed_block ): string { + $hash = md5( serialize( $parsed_block ) ); return wp_unique_prefixed_id( 'wp-elements-' . $hash ); } @@ -110,6 +118,21 @@ function wp_should_add_elements_class_name( $block, $options ) { * * @param array $parsed_block The parsed block. * @return array The same parsed block with elements classname added if appropriate. + * + * @phpstan-param array{ + * attrs: array{ + * className?: string, + * ... + * }, + * ... + * } $parsed_block + * @phpstan-return array{ + * attrs: array{ + * className?: string, + * ... + * }, + * ... + * } */ function wp_render_elements_support_styles( $parsed_block ) { /* From 78388e75d96baccf4cbff19d338acb953a19d460 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 10 Jun 2026 11:37:36 -0700 Subject: [PATCH 06/12] Fix type issues with wp_render_elements_support_styles() --- src/wp-includes/block-supports/elements.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/block-supports/elements.php b/src/wp-includes/block-supports/elements.php index 6f47b1fdc49a0..892a515ba0ff0 100644 --- a/src/wp-includes/block-supports/elements.php +++ b/src/wp-includes/block-supports/elements.php @@ -120,13 +120,21 @@ function wp_should_add_elements_class_name( $block, $options ) { * @return array The same parsed block with elements classname added if appropriate. * * @phpstan-param array{ + * blockName: string, * attrs: array{ * className?: string, + * style?: array{ + * elements?: array, + * ... + * }>, + * }, * ... * }, * ... * } $parsed_block * @phpstan-return array{ + * blockName: string, * attrs: array{ * className?: string, * ... @@ -153,9 +161,12 @@ function wp_render_elements_support_styles( $parsed_block ) { ); } - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] ); - $element_block_styles = $parsed_block['attrs']['style']['elements'] ?? null; + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] ); + if ( ! $block_type ) { + return $parsed_block; + } + $element_block_styles = $parsed_block['attrs']['style']['elements'] ?? null; if ( ! $element_block_styles ) { return $parsed_block; } @@ -221,7 +232,7 @@ function wp_render_elements_support_styles( $parsed_block ) { ) ); - if ( isset( $element_style_object[':hover'] ) ) { + if ( isset( $element_style_object[':hover'], $element_config['hover_selector'] ) ) { wp_style_engine_get_styles( $element_style_object[':hover'], array( From 4e0f35ccd38256dfdbb552183eab4ea6c52a2c3a Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 10 Jun 2026 11:52:25 -0700 Subject: [PATCH 07/12] Refactor test_elements_block_support_class_with_duplicate_blocks() to use WP_HTML_Tag_Processor and eliminate duplication --- .../wpRenderElementsSupport.php | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php index 0ad68606b2f01..22c11c1dc9155 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php @@ -202,29 +202,25 @@ public function test_elements_block_support_class_with_duplicate_blocks(): void ), ); - $block_markup = '

Hello WordPress!

'; - $block_one = wp_render_elements_support_styles( $block ); - $block_two = wp_render_elements_support_styles( $block ); - $markup_one = wp_render_elements_class_name( $block_markup, $block_one ); - $markup_two = wp_render_elements_class_name( $block_markup, $block_two ); + $block_markup = '

Hello WordPress!

'; + $elements_class_names = array(); + $count = 2; + for ( $i = 0; $i < $count; $i++ ) { + $rendered_block = wp_render_elements_class_name( $block_markup, wp_render_elements_support_styles( $block ) ); - $this->assertMatchesRegularExpression( - '/^

Hello WordPress<\/a>!<\/p>$/', - $markup_one, - 'First block should have wp-elements class applied' - ); - $this->assertMatchesRegularExpression( - '/^

Hello WordPress<\/a>!<\/p>$/', - $markup_two, - 'Second block should also have wp-elements class applied' - ); + $processor = new WP_HTML_Tag_Processor( $rendered_block ); + $this->assertTrue( $processor->next_tag( 'P' ), "Expected paragraph in block #$i." ); + $elements_class_name = array_first( + array_filter( + iterator_to_array( $processor->class_list() ), + fn( string $class_name ) => (bool) preg_match( '/^wp-elements-[a-f0-9]{32}[0-9]+$/', $class_name ) + ) + ); + $this->assertIsString( $elements_class_name, "Expected wp-elements class in block #$i." ); + $elements_class_names[] = $elements_class_name; + } - // Extract class names and verify they are different. - preg_match( '/wp-elements-([a-f0-9]{32}[0-9]+)/', $markup_one, $match_one ); - preg_match( '/wp-elements-([a-f0-9]{32}[0-9]+)/', $markup_two, $match_two ); - $this->assertNotEmpty( $match_one, 'First block class name should be extractable' ); - $this->assertNotEmpty( $match_two, 'Second block class name should be extractable' ); - $this->assertNotSame( $match_one[1], $match_two[1], 'Class names for identical blocks should be unique' ); + $this->assertSame( $count, count( array_unique( $elements_class_names ) ), 'Expected each rendered block to have a unique wp-elements class name.' ); } /** From f944d1301e6194082f96b371d511d19d7aed8c5d Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 11 Jun 2026 11:54:23 -0700 Subject: [PATCH 08/12] Remove redundant assertMatchesRegularExpression and deduplicate --- .../wpRenderElementsSupportStyles.php | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php index 02377898b7440..538ae8e81c7f2 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php @@ -112,25 +112,16 @@ public function test_elements_block_support_styles_with_duplicate_blocks(): void ); // Process two identical blocks with the same elements styles. - wp_render_elements_support_styles( $block ); - wp_render_elements_support_styles( $block ); + $count = 2; + for ( $i = 0; $i < $count; $i++ ) { + wp_render_elements_support_styles( $block ); + } $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); - // Both rules should be present with distinct class names. - $this->assertMatchesRegularExpression( - '/\.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', - $actual_stylesheet, - 'First block element style should be present' - ); - $this->assertMatchesRegularExpression( - '/\.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', - $actual_stylesheet, - 'Second block element style should also be present' - ); // Count the number of distinct class names to confirm uniqueness. - preg_match_all( '/\.wp-elements-([a-f0-9]{32}[0-9]+)/', $actual_stylesheet, $matches ); + $this->assertSame( $count, preg_match_all( '/\.wp-elements-([a-f0-9]{32}[0-9]+)/', $actual_stylesheet, $matches ) ); $unique_classes = array_unique( $matches[1] ); - $this->assertCount( 2, $unique_classes, 'Both blocks should produce distinct class names' ); + $this->assertCount( $count, $unique_classes, 'Both blocks should produce distinct class names' ); } /** From 1cc29385f4a6593037d4ff406d39157e6d43ff4a Mon Sep 17 00:00:00 2001 From: USERSATOSHI Date: Mon, 15 Jun 2026 11:56:06 +0530 Subject: [PATCH 09/12] Refactor: streamline duplicate block processing in element styles test --- .../wpRenderElementsSupportStyles.php | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php index 7707afee962fa..c21e3b619cb27 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php @@ -112,25 +112,16 @@ public function test_elements_block_support_styles_with_duplicate_blocks() { ); // Process two identical blocks with the same elements styles. - wp_render_elements_support_styles( $block ); - wp_render_elements_support_styles( $block ); + $count = 2; + for ( $i = 0; $i < $count; $i++ ) { + wp_render_elements_support_styles( $block ); + } $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); - // Both rules should be present with distinct class names. - $this->assertMatchesRegularExpression( - '/\.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', - $actual_stylesheet, - 'First block element style should be present' - ); - $this->assertMatchesRegularExpression( - '/\.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(\.wp-element-button\)\)\{color:blue;\}/', - $actual_stylesheet, - 'Second block element style should also be present' - ); // Count the number of distinct class names to confirm uniqueness. - preg_match_all( '/\.wp-elements-([a-f0-9]{32}[0-9]+)/', $actual_stylesheet, $matches ); + $this->assertSame( $count, preg_match_all( '/\.wp-elements-([a-f0-9]{32}[0-9]+)/', $actual_stylesheet, $matches ) ); $unique_classes = array_unique( $matches[1] ); - $this->assertCount( 2, $unique_classes, 'Both blocks should produce distinct class names' ); + $this->assertCount( $count, $unique_classes, 'Both blocks should produce distinct class names' ); } /** From e40c491cf98b40adefe4ed19fd9e01c4678bf8c8 Mon Sep 17 00:00:00 2001 From: USERSATOSHI Date: Mon, 15 Jun 2026 14:57:07 +0530 Subject: [PATCH 10/12] refactor: simplify wp_get_elements_class_name() by removing hash generation --- src/wp-includes/block-supports/elements.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wp-includes/block-supports/elements.php b/src/wp-includes/block-supports/elements.php index 892a515ba0ff0..a60dfa177cc9c 100644 --- a/src/wp-includes/block-supports/elements.php +++ b/src/wp-includes/block-supports/elements.php @@ -24,8 +24,7 @@ * } $parsed_block */ function wp_get_elements_class_name( $parsed_block ): string { - $hash = md5( serialize( $parsed_block ) ); - return wp_unique_prefixed_id( 'wp-elements-' . $hash ); + return wp_unique_prefixed_id( 'wp-elements-' ); } /** From 012f1f5a6547a0c6465b3106a0a66fc40e07c3e1 Mon Sep 17 00:00:00 2001 From: USERSATOSHI Date: Mon, 15 Jun 2026 15:45:18 +0530 Subject: [PATCH 11/12] revert: the hash removal --- src/wp-includes/block-supports/elements.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/block-supports/elements.php b/src/wp-includes/block-supports/elements.php index a60dfa177cc9c..892a515ba0ff0 100644 --- a/src/wp-includes/block-supports/elements.php +++ b/src/wp-includes/block-supports/elements.php @@ -24,7 +24,8 @@ * } $parsed_block */ function wp_get_elements_class_name( $parsed_block ): string { - return wp_unique_prefixed_id( 'wp-elements-' ); + $hash = md5( serialize( $parsed_block ) ); + return wp_unique_prefixed_id( 'wp-elements-' . $hash ); } /** From cdb79221155672d0cd86893eace0652dd3a84673 Mon Sep 17 00:00:00 2001 From: USERSATOSHI Date: Wed, 17 Jun 2026 16:22:12 +0530 Subject: [PATCH 12/12] refactor: update wp_get_elements_class_name() to remove hash generation and simplify class name structure --- src/wp-includes/block-supports/elements.php | 16 +++----------- .../wpRenderElementsSupport.php | 12 +++++----- .../wpRenderElementsSupportStyles.php | 22 +++++++++---------- 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/src/wp-includes/block-supports/elements.php b/src/wp-includes/block-supports/elements.php index 892a515ba0ff0..d765a2c2b4b5a 100644 --- a/src/wp-includes/block-supports/elements.php +++ b/src/wp-includes/block-supports/elements.php @@ -12,20 +12,10 @@ * @since 6.0.0 * @access private * - * @param array $parsed_block Block object. * @return string The unique class name. - * - * @phpstan-param array{ - * attrs: array{ - * className?: string, - * ... - * }, - * ... - * } $parsed_block */ -function wp_get_elements_class_name( $parsed_block ): string { - $hash = md5( serialize( $parsed_block ) ); - return wp_unique_prefixed_id( 'wp-elements-' . $hash ); +function wp_get_elements_class_name(): string { + return wp_unique_prefixed_id( 'wp-elements-' ); } /** @@ -192,7 +182,7 @@ function wp_render_elements_support_styles( $parsed_block ) { return $parsed_block; } - $class_name = wp_get_elements_class_name( $parsed_block ); + $class_name = wp_get_elements_class_name(); $updated_class_name = isset( $parsed_block['attrs']['className'] ) ? $parsed_block['attrs']['className'] . " $class_name" : $class_name; _wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name ); diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php index 22c11c1dc9155..ad60844813188 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupport.php @@ -213,7 +213,7 @@ public function test_elements_block_support_class_with_duplicate_blocks(): void $elements_class_name = array_first( array_filter( iterator_to_array( $processor->class_list() ), - fn( string $class_name ) => (bool) preg_match( '/^wp-elements-[a-f0-9]{32}[0-9]+$/', $class_name ) + fn( string $class_name ) => (bool) preg_match( '/^wp-elements-\d+$/', $class_name ) ) ); $this->assertIsString( $elements_class_name, "Expected wp-elements class in block #$i." ); @@ -302,7 +302,7 @@ public function data_elements_block_support_class() { 'button' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), 'link element styles apply class to wrapper' => array( 'color_settings' => array( 'link' => true ), @@ -310,7 +310,7 @@ public function data_elements_block_support_class() { 'link' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), 'heading element styles apply class to wrapper' => array( 'color_settings' => array( 'heading' => true ), @@ -318,7 +318,7 @@ public function data_elements_block_support_class() { 'heading' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), 'element styles apply class to wrapper when it has other classes' => array( 'color_settings' => array( 'link' => true ), @@ -326,7 +326,7 @@ public function data_elements_block_support_class() { 'link' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), 'element styles apply class to wrapper when it has other attributes' => array( 'color_settings' => array( 'link' => true ), @@ -334,7 +334,7 @@ public function data_elements_block_support_class() { 'link' => array( 'color' => $color_styles ), ), 'block_markup' => '

Hello WordPress!

', - 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', + 'expected_markup' => '/^

Hello WordPress<\/a>!<\/p>$/', ), ); } diff --git a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php index 538ae8e81c7f2..5c9fc8af5819d 100644 --- a/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php +++ b/tests/phpunit/tests/block-supports/wpRenderElementsSupportStyles.php @@ -119,7 +119,7 @@ public function test_elements_block_support_styles_with_duplicate_blocks(): void $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); // Count the number of distinct class names to confirm uniqueness. - $this->assertSame( $count, preg_match_all( '/\.wp-elements-([a-f0-9]{32}[0-9]+)/', $actual_stylesheet, $matches ) ); + $this->assertSame( $count, preg_match_all( '/\.wp-elements-(\d+)/', $actual_stylesheet, $matches ) ); $unique_classes = array_unique( $matches[1] ); $this->assertCount( $count, $unique_classes, 'Both blocks should produce distinct class names' ); } @@ -183,7 +183,7 @@ public function data_elements_block_support_styles() { 'elements_styles' => array( 'button' => array( 'color' => $color_styles ), ), - 'expected_styles' => '/^.wp-elements-[a-f0-9]{32}[0-9]+ .wp-element-button, .wp-elements-[a-f0-9]{32}[0-9]+ .wp-block-button__link' . $color_css_rules . '$/', + 'expected_styles' => '/^.wp-elements-\d+ .wp-element-button, .wp-elements-\d+ .wp-block-button__link' . $color_css_rules . '$/', ), 'link element styles are applied' => array( 'color_settings' => array( 'link' => true ), @@ -195,15 +195,15 @@ public function data_elements_block_support_styles() { ), ), ), - 'expected_styles' => '/^.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(.wp-element-button\)\)' . $color_css_rules . - '.wp-elements-[a-f0-9]{32}[0-9]+ a:where\(:not\(.wp-element-button\)\):hover' . $color_css_rules . '$/', + 'expected_styles' => '/^.wp-elements-\d+ a:where\(:not\(.wp-element-button\)\)' . $color_css_rules . + '.wp-elements-\d+ a:where\(:not\(.wp-element-button\)\):hover' . $color_css_rules . '$/', ), 'generic heading element styles are applied' => array( 'color_settings' => array( 'heading' => true ), 'elements_styles' => array( 'heading' => array( 'color' => $color_styles ), ), - 'expected_styles' => '/^.wp-elements-[a-f0-9]{32}[0-9]+ h1, .wp-elements-[a-f0-9]{32}[0-9]+ h2, .wp-elements-[a-f0-9]{32}[0-9]+ h3, .wp-elements-[a-f0-9]{32}[0-9]+ h4, .wp-elements-[a-f0-9]{32}[0-9]+ h5, .wp-elements-[a-f0-9]{32}[0-9]+ h6' . $color_css_rules . '$/', + 'expected_styles' => '/^.wp-elements-\d+ h1, .wp-elements-\d+ h2, .wp-elements-\d+ h3, .wp-elements-\d+ h4, .wp-elements-\d+ h5, .wp-elements-\d+ h6' . $color_css_rules . '$/', ), 'individual heading element styles are applied' => array( 'color_settings' => array( 'heading' => true ), @@ -215,12 +215,12 @@ public function data_elements_block_support_styles() { 'h5' => array( 'color' => $color_styles ), 'h6' => array( 'color' => $color_styles ), ), - 'expected_styles' => '/^.wp-elements-[a-f0-9]{32}[0-9]+ h1' . $color_css_rules . - '.wp-elements-[a-f0-9]{32}[0-9]+ h2' . $color_css_rules . - '.wp-elements-[a-f0-9]{32}[0-9]+ h3' . $color_css_rules . - '.wp-elements-[a-f0-9]{32}[0-9]+ h4' . $color_css_rules . - '.wp-elements-[a-f0-9]{32}[0-9]+ h5' . $color_css_rules . - '.wp-elements-[a-f0-9]{32}[0-9]+ h6' . $color_css_rules . '$/', + 'expected_styles' => '/^.wp-elements-\d+ h1' . $color_css_rules . + '.wp-elements-\d+ h2' . $color_css_rules . + '.wp-elements-\d+ h3' . $color_css_rules . + '.wp-elements-\d+ h4' . $color_css_rules . + '.wp-elements-\d+ h5' . $color_css_rules . + '.wp-elements-\d+ h6' . $color_css_rules . '$/', ), ); }