Make WordPress Core

Changeset 55172


Ignore:
Timestamp:
02/01/2023 01:41:16 PM (4 years ago)
Author:
hellofromTonya
Message:

Editor: Add support for editing block style variations in global styles.

To allow editing of block style variations in global styles, this changeset adds the following for server side support:

  • building of block style schema into WP_Theme_JSON::sanitize().
  • appending of style variation selectors to block metadata in WP_Theme_JSON::get_blocks_metadata().
  • building of selectors and variations for nodes in WP_Theme_JSON::get_block_nodes().

Tests for happy and unhappy paths are included.

Reference:

Follow-up to [54118], [50973], [50959].

Props isabel_brison,
Fixes #57583.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-theme-json.php

    r55142 r55172  
    666666                $schema_settings_blocks = array();
    667667                foreach ( $valid_block_names as $block ) {
    668                         $schema_settings_blocks[ $block ]           = static::VALID_SETTINGS;
    669                         $schema_styles_blocks[ $block ]             = $styles_non_top_level;
    670                         $schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements;
     668                        // Build the schema for each block style variation.
     669                        $style_variation_names = array();
     670                        if (
     671                                ! empty( $input['styles']['blocks'][ $block ]['variations'] ) &&
     672                                is_array( $input['styles']['blocks'][ $block ]['variations'] )
     673                        ) {
     674                                $style_variation_names = array_keys( $input['styles']['blocks'][ $block ]['variations'] );
     675                        }
     676
     677                        $schema_styles_variations = array();
     678                        if ( ! empty( $style_variation_names ) ) {
     679                                $schema_styles_variations = array_fill_keys( $style_variation_names, $styles_non_top_level );
     680                        }
     681
     682                        $schema_settings_blocks[ $block ]             = static::VALID_SETTINGS;
     683                        $schema_styles_blocks[ $block ]               = $styles_non_top_level;
     684                        $schema_styles_blocks[ $block ]['elements']   = $schema_styles_elements;
     685                        $schema_styles_blocks[ $block ]['variations'] = $schema_styles_variations;
    671686                }
    672687
    … …  
    814829                                }
    815830                                static::$blocks_metadata[ $block_name ]['elements'][ $el_name ] = implode( ',', $element_selector );
     831                        }
     832                        // If the block has style variations, append their selectors to the block metadata.
     833                        if ( ! empty( $block_type->styles ) ) {
     834                                $style_selectors = array();
     835                                foreach ( $block_type->styles as $style ) {
     836                                        // The style variation classname is duplicated in the selector to ensure that it overrides core block styles.
     837                                        $style_selectors[ $style['name'] ] = static::append_to_selector( '.is-style-' . $style['name'] . '.is-style-' . $style['name'], static::$blocks_metadata[ $block_name ]['selector'] );
     838                                }
     839                                static::$blocks_metadata[ $block_name ]['styleVariations'] = $style_selectors;
    816840                        }
    817841                }
    … …  
    20402064                        }
    20412065
     2066                        $variation_selectors = array();
     2067                        if ( isset( $node['variations'] ) ) {
     2068                                foreach ( $node['variations'] as $variation => $node ) {
     2069                                        $variation_selectors[] = array(
     2070                                                'path'     => array( 'styles', 'blocks', $name, 'variations', $variation ),
     2071                                                'selector' => $selectors[ $name ]['styleVariations'][ $variation ],
     2072                                        );
     2073                                }
     2074                        }
     2075
    20422076                        $nodes[] = array(
    2043                                 'name'     => $name,
    2044                                 'path'     => array( 'styles', 'blocks', $name ),
    2045                                 'selector' => $selector,
    2046                                 'duotone'  => $duotone_selector,
    2047                                 'features' => $feature_selectors,
     2077                                'name'       => $name,
     2078                                'path'       => array( 'styles', 'blocks', $name ),
     2079                                'selector'   => $selector,
     2080                                'duotone'    => $duotone_selector,
     2081                                'features'   => $feature_selectors,
     2082                                'variations' => $variation_selectors,
    20482083                        );
    20492084
    … …  
    21252160                }
    21262161
     2162                // If there are style variations, generate the declarations for them, including any feature selectors the block may have.
     2163                $style_variation_declarations = array();
     2164                if ( ! empty( $block_metadata['variations'] ) ) {
     2165                        foreach ( $block_metadata['variations'] as $style_variation ) {
     2166                                $style_variation_node     = _wp_array_get( $this->theme_json, $style_variation['path'], array() );
     2167                                $style_variation_selector = $style_variation['selector'];
     2168
     2169                                // If the block has feature selectors, generate the declarations for them within the current style variation.
     2170                                if ( ! empty( $block_metadata['features'] ) ) {
     2171                                        $clean_style_variation_selector = trim( $style_variation_selector );
     2172                                        foreach ( $block_metadata['features'] as $feature_name => $feature_selector ) {
     2173                                                if ( empty( $style_variation_node[ $feature_name ] ) ) {
     2174                                                        continue;
     2175                                                }
     2176                                                // Prepend the variation selector to the feature selector.
     2177                                                $split_feature_selectors    = explode( ',', $feature_selector );
     2178                                                $feature_selectors          = array_map(
     2179                                                        static function( $split_feature_selector ) use ( $clean_style_variation_selector ) {
     2180                                                                return $clean_style_variation_selector . trim( $split_feature_selector );
     2181                                                        },
     2182                                                        $split_feature_selectors
     2183                                                );
     2184                                                $combined_feature_selectors = implode( ',', $feature_selectors );
     2185
     2186                                                // Compute declarations for the feature.
     2187                                                $new_feature_declarations = static::compute_style_properties( array( $feature_name => $style_variation_node[ $feature_name ] ), $settings, null, $this->theme_json );
     2188
     2189                                                /*
     2190                                                 * Merge new declarations with any that already exist for
     2191                                                 * the feature selector. This may occur when multiple block
     2192                                                 * support features use the same custom selector.
     2193                                                 */
     2194                                                if ( isset( $style_variation_declarations[ $combined_feature_selectors ] ) ) {
     2195                                                        $style_variation_declarations[ $combined_feature_selectors ] = array_merge( $style_variation_declarations[ $combined_feature_selectors ], $new_feature_declarations );
     2196                                                } else {
     2197                                                        $style_variation_declarations[ $combined_feature_selectors ] = $new_feature_declarations;
     2198                                                }
     2199                                                /*
     2200                                                 * Remove the feature from the variation's node now the
     2201                                                 * styles will be included under the feature level selector.
     2202                                                 */
     2203                                                unset( $style_variation_node[ $feature_name ] );
     2204                                        }
     2205                                }
     2206                                // Compute declarations for remaining styles not covered by feature level selectors.
     2207                                $style_variation_declarations[ $style_variation_selector ] = static::compute_style_properties( $style_variation_node, $settings, null, $this->theme_json );
     2208                        }
     2209                }
    21272210                /*
    21282211                 * Get a reference to element name from path.
    … …  
    22132296                foreach ( $feature_declarations as $feature_selector => $individual_feature_declarations ) {
    22142297                        $block_rules .= static::to_ruleset( $feature_selector, $individual_feature_declarations );
     2298                }
     2299
     2300                // 6. Generate and append the style variation rulesets.
     2301                foreach ( $style_variation_declarations as $style_variation_selector => $individual_style_variation_declarations ) {
     2302                        $block_rules .= static::to_ruleset( $style_variation_selector, $individual_style_variation_declarations );
    22152303                }
    22162304
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r55146 r55172  
    35973597
    35983598        /**
     3599         * @ticket 57583
     3600         *
     3601         * @dataProvider data_sanitize_for_block_with_style_variations
     3602         *
     3603         * @param array $theme_json_variations Theme.json variations to test.
     3604         * @param array $expected_sanitized    Expected results after sanitizing.
     3605         */
     3606        public function test_sanitize_for_block_with_style_variations( $theme_json_variations, $expected_sanitized ) {
     3607                $theme_json = new WP_Theme_JSON(
     3608                        array(
     3609                                'version' => 2,
     3610                                'styles'  => array(
     3611                                        'blocks' => array(
     3612                                                'core/quote' => $theme_json_variations,
     3613                                        ),
     3614                                ),
     3615                        )
     3616                );
     3617
     3618                // Validate structure is sanitized.
     3619                $sanitized_theme_json = $theme_json->get_raw_data();
     3620                $this->assertIsArray( $sanitized_theme_json, 'Sanitized theme.json is not an array data type' );
     3621                $this->assertArrayHasKey( 'styles', $sanitized_theme_json, 'Sanitized theme.json does not have an "styles" key' );
     3622                $this->assertSameSetsWithIndex( $expected_sanitized, $sanitized_theme_json['styles'], 'Sanitized theme.json styles does not match' );
     3623        }
     3624
     3625        /**
     3626         * Data provider.
     3627         *
     3628         * @return array
     3629         */
     3630        public function data_sanitize_for_block_with_style_variations() {
     3631                return array(
     3632                        '1 variation with 1 invalid property'   => array(
     3633                                'theme_json_variations' => array(
     3634                                        'variations' => array(
     3635                                                'plain' => array(
     3636                                                        'color' => array(
     3637                                                                'background' => 'hotpink',
     3638                                                        ),
     3639                                                ),
     3640                                        ),
     3641                                ),
     3642                                'expected_sanitized'    => array(
     3643                                        'blocks' => array(
     3644                                                'core/quote' => array(
     3645                                                        'variations' => array(
     3646                                                                'plain' => array(
     3647                                                                        'color' => array(
     3648                                                                                'background' => 'hotpink',
     3649                                                                        ),
     3650                                                                ),
     3651                                                        ),
     3652                                                ),
     3653                                        ),
     3654                                ),
     3655                        ),
     3656                        '1 variation with 2 invalid properties' => array(
     3657                                'theme_json_variations' => array(
     3658                                        'variations' => array(
     3659                                                'plain' => array(
     3660                                                        'color'            => array(
     3661                                                                'background' => 'hotpink',
     3662                                                        ),
     3663                                                        'invalidProperty1' => 'value1',
     3664                                                        'invalidProperty2' => 'value2',
     3665                                                ),
     3666                                        ),
     3667                                ),
     3668                                'expected_sanitized'    => array(
     3669                                        'blocks' => array(
     3670                                                'core/quote' => array(
     3671                                                        'variations' => array(
     3672                                                                'plain' => array(
     3673                                                                        'color' => array(
     3674                                                                                'background' => 'hotpink',
     3675                                                                        ),
     3676                                                                ),
     3677                                                        ),
     3678                                                ),
     3679                                        ),
     3680                                ),
     3681                        ),
     3682                        '2 variations with 1 invalid property'  => array(
     3683                                'theme_json_variations' => array(
     3684                                        'variations' => array(
     3685                                                'plain' => array(
     3686                                                        'color'            => array(
     3687                                                                'background' => 'hotpink',
     3688                                                        ),
     3689                                                        'invalidProperty1' => 'value1',
     3690                                                ),
     3691                                                'basic' => array(
     3692                                                        'color' => array(
     3693                                                                'background' => '#ffffff',
     3694                                                                'text'       => '#000000',
     3695                                                        ),
     3696                                                        'foo'   => 'bar',
     3697                                                ),
     3698                                        ),
     3699                                ),
     3700                                'expected_sanitized'    => array(
     3701                                        'blocks' => array(
     3702                                                'core/quote' => array(
     3703                                                        'variations' => array(
     3704                                                                'plain' => array(
     3705                                                                        'color' => array(
     3706                                                                                'background' => 'hotpink',
     3707                                                                        ),
     3708                                                                ),
     3709                                                                'basic' => array(
     3710                                                                        'color' => array(
     3711                                                                                'background' => '#ffffff',
     3712                                                                                'text'       => '#000000',
     3713                                                                        ),
     3714                                                                ),
     3715                                                        ),
     3716                                                ),
     3717                                        ),
     3718                                ),
     3719                        ),
     3720                );
     3721        }
     3722
     3723        /**
     3724         * @ticket 57583
     3725         *
     3726         * @dataProvider data_sanitize_with_invalid_style_variation
     3727         *
     3728         * @param array $theme_json_variations The theme.json variations to test.
     3729         */
     3730        public function test_sanitize_with_invalid_style_variation( $theme_json_variations ) {
     3731                $theme_json = new WP_Theme_JSON(
     3732                        array(
     3733                                'version' => 2,
     3734                                'styles'  => array(
     3735                                        'blocks' => array(
     3736                                                'core/quote' => $theme_json_variations,
     3737                                        ),
     3738                                ),
     3739                        )
     3740                );
     3741
     3742                // Validate structure is sanitized.
     3743                $sanitized_theme_json = $theme_json->get_raw_data();
     3744                $this->assertIsArray( $sanitized_theme_json, 'Sanitized theme.json is not an array data type' );
     3745                $this->assertArrayNotHasKey( 'styles', $sanitized_theme_json, 'Sanitized theme.json should not have a "styles" key' );
     3746
     3747        }
     3748
     3749        /**
     3750         * Data provider.
     3751         *
     3752         * @return array
     3753         */
     3754        public function data_sanitize_with_invalid_style_variation() {
     3755                return array(
     3756                        'empty string variation' => array(
     3757                                array(
     3758                                        'variations' => '',
     3759                                ),
     3760                        ),
     3761                        'boolean variation'      => array(
     3762                                array(
     3763                                        'variations' => false,
     3764                                ),
     3765                        ),
     3766                );
     3767        }
     3768
     3769        /**
     3770         * @ticket 57583
     3771         *
     3772         * @dataProvider data_get_styles_for_block_with_style_variations
     3773         *
     3774         * @param array  $theme_json_variations Theme.json variations to test.
     3775         * @param string $metadata_variations   Style variations to test.
     3776         * @param string $expected              Expected results for styling.
     3777         */
     3778        public function test_get_styles_for_block_with_style_variations( $theme_json_variations, $metadata_variations, $expected ) {
     3779                $theme_json = new WP_Theme_JSON(
     3780                        array(
     3781                                'version' => 2,
     3782                                'styles'  => array(
     3783                                        'blocks' => array(
     3784                                                'core/quote' => $theme_json_variations,
     3785                                        ),
     3786                                ),
     3787                        )
     3788                );
     3789
     3790                // Validate styles are generated properly.
     3791                $metadata      = array(
     3792                        'path'       => array( 'styles', 'blocks', 'core/quote' ),
     3793                        'selector'   => '.wp-block-quote',
     3794                        'variations' => $metadata_variations,
     3795                );
     3796                $actual_styles = $theme_json->get_styles_for_block( $metadata );
     3797                $this->assertSame( $expected, $actual_styles );
     3798        }
     3799
     3800        /**
     3801         * Data provider.
     3802         *
     3803         * @return array
     3804         */
     3805        public function data_get_styles_for_block_with_style_variations() {
     3806                $plain = array(
     3807                        'metadata' => array(
     3808                                'path'     => array( 'styles', 'blocks', 'core/quote', 'variations', 'plain' ),
     3809                                'selector' => '.is-style-plain.is-style-plain.wp-block-quote',
     3810                        ),
     3811                        'styles'   => '.is-style-plain.is-style-plain.wp-block-quote{background-color: hotpink;}',
     3812                );
     3813                $basic = array(
     3814                        'metadata' => array(
     3815                                'path'     => array( 'styles', 'blocks', 'core/quote', 'variations', 'basic' ),
     3816                                'selector' => '.is-style-basic.is-style-basic.wp-block-quote',
     3817                        ),
     3818                        'styles'   => '.is-style-basic.is-style-basic.wp-block-quote{background-color: #ffffff;color: #000000;}',
     3819                );
     3820
     3821                return array(
     3822                        '1 variation with 1 invalid property'   => array(
     3823                                'theme_json_variations' => array(
     3824                                        'variations' => array(
     3825                                                'plain' => array(
     3826                                                        'color' => array(
     3827                                                                'background' => 'hotpink',
     3828                                                        ),
     3829                                                ),
     3830                                        ),
     3831                                ),
     3832                                'metadata_variation'    => array( $plain['metadata'] ),
     3833                                'expected'              => $plain['styles'],
     3834                        ),
     3835                        '1 variation with 2 invalid properties' => array(
     3836                                'theme_json_variations' => array(
     3837                                        'variations' => array(
     3838                                                'plain' => array(
     3839                                                        'color'            => array(
     3840                                                                'background' => 'hotpink',
     3841                                                        ),
     3842                                                        'invalidProperty1' => 'value1',
     3843                                                        'invalidProperty2' => 'value2',
     3844                                                ),
     3845                                        ),
     3846                                ),
     3847                                'metadata_variation'    => array( $plain['metadata'] ),
     3848                                'expected'              => $plain['styles'],
     3849                        ),
     3850                        '2 variations with 1 invalid property'  => array(
     3851                                'theme_json_variations' => array(
     3852                                        'variations' => array(
     3853                                                'plain' => array(
     3854                                                        'color'            => array(
     3855                                                                'background' => 'hotpink',
     3856                                                        ),
     3857                                                        'invalidProperty1' => 'value1',
     3858                                                ),
     3859                                                'basic' => array(
     3860                                                        'color' => array(
     3861                                                                'background' => '#ffffff',
     3862                                                                'text'       => '#000000',
     3863                                                        ),
     3864                                                        'foo'   => 'bar',
     3865                                                ),
     3866                                        ),
     3867                                ),
     3868                                'metadata_variation'    => array( $plain['metadata'], $basic['metadata'] ),
     3869                                'expected_styles'       => $plain['styles'] . $basic['styles'],
     3870                        ),
     3871                        '2 variations with multiple invalid properties' => array(
     3872                                'theme_json_variations' => array(
     3873                                        'variations' => array(
     3874                                                'plain' => array(
     3875                                                        'color'            => array(
     3876                                                                'background' => 'hotpink',
     3877                                                        ),
     3878                                                        'invalidProperty1' => 'value1',
     3879                                                        'invalidProperty2' => 'value2',
     3880                                                ),
     3881                                                'basic' => array(
     3882                                                        'foo'   => 'foo',
     3883                                                        'color' => array(
     3884                                                                'background' => '#ffffff',
     3885                                                                'text'       => '#000000',
     3886                                                        ),
     3887                                                        'bar'   => 'bar',
     3888                                                        'baz'   => 'baz',
     3889                                                ),
     3890                                        ),
     3891                                ),
     3892                                'metadata_variation'    => array( $plain['metadata'], $basic['metadata'] ),
     3893                                'expected_styles'       => $plain['styles'] . $basic['styles'],
     3894                        ),
     3895                );
     3896        }
     3897
     3898        /**
    35993899         * @ticket 56611
    36003900         */
Note: See TracChangeset for help on using the changeset viewer.