diff --git a/packages/style-engine/class-wp-style-engine-block-style-metadata.php b/packages/style-engine/class-wp-style-engine-block-style-metadata.php index 47fa4005c75d64..b8bde570f5861f 100644 --- a/packages/style-engine/class-wp-style-engine-block-style-metadata.php +++ b/packages/style-engine/class-wp-style-engine-block-style-metadata.php @@ -59,6 +59,12 @@ public function add_metadata( $metadata = array() ) { } foreach ( $definition_group_style as $style_definition_key => $style_definition ) { + // Bails early if merging metadata is attempting to overwrite existing, original style metadata. + if ( array_key_exists( $definition_group_key, $this->base_metadata ) + && array_key_exists( $style_definition_key, $this->base_metadata[ $definition_group_key ] ) ) { + continue; + } + if ( ! is_array( $style_definition ) || empty( $style_definition ) ) { continue; } @@ -120,13 +126,9 @@ protected function merge_custom_style_definitions_metadata( $style_definition, $ return; } - // Only allow specific value_func. - if ( isset( $custom_definition['value_func'] ) && 'WP_Style_Engine::get_individual_property_css_declarations' !== $custom_definition['value_func'] ) { - return; - } - $custom_definition['property_keys']['default'] = sanitize_key( $custom_definition['property_keys']['default'] ); + // A white list of keys that may be merged. Note the absence of the callable `value_func`. $valid_keys = array( 'path', 'property_keys', 'css_vars', 'classnames' ); foreach ( $valid_keys as $key ) { if ( isset( $custom_definition[ $key ] ) && is_array( $custom_definition[ $key ] ) ) { diff --git a/phpunit/style-engine/class-wp-style-engine-block-style-metadata-test.php b/phpunit/style-engine/class-wp-style-engine-block-style-metadata-test.php index 4dcc639b4de7a0..1d225e4263aa59 100644 --- a/phpunit/style-engine/class-wp-style-engine-block-style-metadata-test.php +++ b/phpunit/style-engine/class-wp-style-engine-block-style-metadata-test.php @@ -72,37 +72,6 @@ public function test_should_add_new_top_level_metadata() { $block_style_metadata->add_metadata( $new_metadata )->get_metadata( array( 'layout' ) ), 'A new style definition for `layout` should be registered' ); - - $block_styles = array( - 'layout' => array( - 'float' => 'var:preset|layout|left', - 'width' => array( - 'max' => '100px', - 'min' => '20px', - ), - ), - ); - $expected_styles = array( - 'css' => 'float:var(--wp--preset--float--left);max-width:100px;min-width:20px;', - 'declarations' => array( - 'float' => 'var(--wp--preset--float--left)', - 'max-width' => '100px', - 'min-width' => '20px', - ), - 'classnames' => 'has-float-layout has-left-float', - ); - $generated_styles = gutenberg_style_engine_get_styles( - $block_styles, - array( - 'metadata' => $new_metadata, - ) - ); - - $this->assertSame( - $expected_styles, - $generated_styles, - 'CSS should be generated using the newly-added metadata' - ); } /** @@ -110,7 +79,7 @@ public function test_should_add_new_top_level_metadata() { * * @covers ::add_metadata */ - public function test_should_add_new_style_property_metadata() { + public function test_should_add_new_style_property_metadata_keys() { $block_style_metadata = new WP_Style_Engine_Block_Style_Metadata_Gutenberg( WP_Style_Engine_Gutenberg::BLOCK_STYLE_DEFINITIONS_METADATA ); $new_metadata = array( 'typography' => array( @@ -118,54 +87,37 @@ public function test_should_add_new_style_property_metadata() { 'property_keys' => array( 'default' => 'text-indent', ), + 'css_vars' => array( + 'spacing' => '--wp--preset--spacing--$slug', + ), 'path' => array( 'typography', 'textIndent' ), 'classnames' => array( 'has-text-indent' => true, ), + 'value_func' => 'Test::function', ), ), ); $block_style_metadata->add_metadata( $new_metadata ); + + // Remove ignored property keys. + unset( $new_metadata['typography']['textIndent']['value_func'] ); + $this->assertEquals( $new_metadata['typography']['textIndent'], $block_style_metadata->get_metadata( array( 'typography', 'textIndent' ) ), 'The new style property should match expected.' ); - - $block_styles = array( - 'typography' => array( - 'textIndent' => '1rem', - ), - ); - $expected_styles = array( - 'css' => 'text-indent:1rem;', - 'declarations' => array( - 'text-indent' => '1rem', - ), - 'classnames' => 'has-text-indent', - ); - $generated_styles = gutenberg_style_engine_get_styles( - $block_styles, - array( - 'metadata' => $new_metadata, - ) - ); - - $this->assertSame( - $expected_styles, - $generated_styles, - 'CSS should be generated using the newly-added property metadata' - ); } /** - * Tests merging metadata to the block styles definition. + * Tests that merging style metadata to the block styles definitions does not work. * * @covers ::add_metadata */ - public function test_should_overwrite_style_property_metadata() { - $block_style_metadata = new WP_Style_Engine_Block_Style_Metadata_Gutenberg( WP_Style_Engine_Gutenberg::BLOCK_STYLE_DEFINITIONS_METADATA ); - $new_metadata = array( + public function test_should_not_overwrite_style_property_metadata() { + $block_style_metadata = new WP_Style_Engine_Block_Style_Metadata_Gutenberg( WP_Style_Engine_Gutenberg::BLOCK_STYLE_DEFINITIONS_METADATA ); + $new_metadata = array( 'spacing' => array( 'padding' => array( 'property_keys' => array( @@ -177,51 +129,13 @@ public function test_should_overwrite_style_property_metadata() { ), ), ); - $expected_merged_metadata = array( - 'spacing' => array( - 'padding' => array( - 'property_keys' => array( - 'default' => 'columns', - 'individual' => 'padding-%s', - ), - 'path' => array( 'spacing', 'padding' ), - 'css_vars' => array( - 'spacing' => '--wp--preset--column--$slug', - ), - ), - ), - ); $block_style_metadata->add_metadata( $new_metadata ); $this->assertEquals( - $expected_merged_metadata['spacing']['padding'], + WP_Style_Engine_Gutenberg::BLOCK_STYLE_DEFINITIONS_METADATA['spacing']['padding'], $block_style_metadata->get_metadata( array( 'spacing', 'padding' ) ), 'The newly-merged property metadata should be present' ); - - $block_styles = array( - 'spacing' => array( - 'padding' => '1rem', - ), - ); - $expected_styles = array( - 'css' => 'columns:1rem;', - 'declarations' => array( - 'columns' => '1rem', - ), - ); - $generated_styles = gutenberg_style_engine_get_styles( - $block_styles, - array( - 'metadata' => $new_metadata, - ) - ); - - $this->assertSame( - $expected_styles, - $generated_styles, - 'CSS should be generated using the newly-merged property metadata' - ); } /** @@ -230,44 +144,32 @@ public function test_should_overwrite_style_property_metadata() { * @covers ::reset_metadata */ public function test_should_reset_metadata() { - $block_style_metadata = new WP_Style_Engine_Block_Style_Metadata_Gutenberg( WP_Style_Engine_Gutenberg::BLOCK_STYLE_DEFINITIONS_METADATA ); - $new_metadata = array( - 'spacing' => array( - 'padding' => array( - 'property_keys' => array( - 'default' => 'columns', - ), - 'css_vars' => array( - 'spacing' => '--wp--preset--column--$slug', - ), - ), - ), - ); - $expected_merged_metadata = array( + $block_style_metadata = new WP_Style_Engine_Block_Style_Metadata_Gutenberg( WP_Style_Engine_Gutenberg::BLOCK_STYLE_DEFINITIONS_METADATA ); + $new_metadata = array( 'spacing' => array( - 'padding' => array( + 'gap' => array( 'property_keys' => array( - 'default' => 'columns', - 'individual' => 'padding-%s', + 'default' => 'gap', + 'individual' => 'gap-%', ), - 'path' => array( 'spacing', 'padding' ), + 'path' => array( 'spacing', 'gap' ), 'css_vars' => array( - 'spacing' => '--wp--preset--column--$slug', + 'spacing' => '--wp--preset--spacing--$slug', ), ), ), ); $this->assertEquals( - $expected_merged_metadata['spacing']['padding'], - $block_style_metadata->add_metadata( $new_metadata )->get_metadata( array( 'spacing', 'padding' ) ), - 'Should merge' + $new_metadata['spacing']['gap'], + $block_style_metadata->add_metadata( $new_metadata )->get_metadata( array( 'spacing', 'gap' ) ), + 'Should successfully merge metadata' ); $block_style_metadata->reset_metadata(); $this->assertEquals( - WP_Style_Engine_Gutenberg::BLOCK_STYLE_DEFINITIONS_METADATA['spacing']['padding'], - $block_style_metadata->get_metadata( array( 'spacing', 'padding' ) ), + WP_Style_Engine_Gutenberg::BLOCK_STYLE_DEFINITIONS_METADATA['spacing'], + $block_style_metadata->get_metadata( array( 'spacing' ) ), 'Should be equal to original' ); } diff --git a/phpunit/style-engine/style-engine-test.php b/phpunit/style-engine/style-engine-test.php index 5f4c57453e8a8f..1fd11a70a703c4 100644 --- a/phpunit/style-engine/style-engine-test.php +++ b/phpunit/style-engine/style-engine-test.php @@ -489,6 +489,71 @@ public function data_wp_style_engine_get_styles() { ), ), ), + + 'extend_block_style_definitions_with_metadata' => array( + 'block_styles' => array( + 'layout' => array( + 'float' => 'var:preset|layout|left', + 'width' => array( + 'max' => '100px', + 'min' => '20px', + ), + ), + 'typography' => array( + 'textIndent' => '1rem', + ), + ), + 'options' => array( + 'metadata' => array( + 'layout' => array( + 'float' => array( + 'property_keys' => array( + 'default' => 'float', + ), + 'path' => array( 'layout', 'float' ), + 'css_vars' => array( + 'layout' => '--wp--preset--float--$slug', + ), + 'classnames' => array( + 'has-float-layout' => true, + 'has-$slug-float' => 'layout', + ), + ), + 'width' => array( + 'property_keys' => array( + 'default' => 'width', + 'individual' => '%s-width', + ), + 'path' => array( 'layout', 'width' ), + 'classnames' => array( + 'has-$slug-width' => 'layout', + ), + ), + ), + 'typography' => array( + 'textIndent' => array( + 'property_keys' => array( + 'default' => 'text-indent', + ), + 'path' => array( 'typography', 'textIndent' ), + 'classnames' => array( + 'has-text-indent' => true, + ), + ), + ), + ), + ), + 'expected_output' => array( + 'css' => 'text-indent:1rem;float:var(--wp--preset--float--left);max-width:100px;min-width:20px;', + 'declarations' => array( + 'text-indent' => '1rem', + 'float' => 'var(--wp--preset--float--left)', + 'max-width' => '100px', + 'min-width' => '20px', + ), + 'classnames' => 'has-text-indent has-float-layout has-left-float', + ), + ), ); }