Make WordPress Core


Ignore:
Timestamp:
07/13/2023 11:32:19 AM (3 years ago)
Author:
spacedmonkey
Message:

Editor: Lazily load Duotone settings only when needed.

Introduced in [56101] the WP_Duotone class, hooks into the wp_loaded action to load duotone style data from global styles. Hooking in early in the bootstrap process caused a number of problems. This hook, triggered an error on installing, as this lookup for global styles, would result in a global post trying to be created, even before the table existed. Additionally, this implementation caused a severe performance regression, as duotone styling data was loaded unnecessarily for requests that did not require such data, such as REST API calls or actions within the wp-admin interface.

In this change, refactor the WP_Duotone to lazily load the global styles and theme.json data, only when a block that supports duotone is encountered. The method render_duotone_support was change to take a third parameter to reuse the existing WP_Block_Type object passed to the filter, to save it being looked up again. The code has also got improved type checking and the use of the util function block_has_support. Furthermore, the code's readability has been improved, along with enhancements to the documentation blocks.

Props Chouby, spacedmonkey, SergeyBiryukov, swissspidy, costdev, joemcgill, flixos90, mukesh27, nazmul111, ajlende, isabel_brison.
Fixes #58673.

File:
1 edited

Legend:

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

    r56225 r56226  
    5555         * @var array
    5656         */
    57         private static $global_styles_block_names = array();
     57        private static $global_styles_block_names;
    5858
    5959        /**
     
    7979         * @var array
    8080         */
    81         private static $global_styles_presets = array();
     81        private static $global_styles_presets;
    8282
    8383        /**
     
    576576                $filter_id = self::get_filter_id( $slug );
    577577
    578                 return array_key_exists( $filter_id, self::$global_styles_presets );
     578                return array_key_exists( $filter_id, self::get_all_global_styles_presets() );
    579579        }
    580580
     
    898898         */
    899899        private static function enqueue_global_styles_preset( $filter_id, $duotone_selector, $filter_value ) {
    900                 if ( ! array_key_exists( $filter_id, self::$global_styles_presets ) ) {
     900                $global_styles_presets = self::get_all_global_styles_presets();
     901                if ( ! array_key_exists( $filter_id, $global_styles_presets ) ) {
    901902                        $error_message = sprintf(
    902903                                /* translators: %s: duotone filter ID */
     
    907908                        return;
    908909                }
    909                 self::$used_global_styles_presets[ $filter_id ] = self::$global_styles_presets[ $filter_id ];
    910                 self::enqueue_custom_filter( $filter_id, $duotone_selector, $filter_value, self::$global_styles_presets[ $filter_id ] );
     910                self::$used_global_styles_presets[ $filter_id ] = $global_styles_presets[ $filter_id ];
     911                self::enqueue_custom_filter( $filter_id, $duotone_selector, $filter_value, $global_styles_presets[ $filter_id ] );
    911912        }
    912913
     
    921922         */
    922923        public static function register_duotone_support( $block_type ) {
    923                 $has_duotone_support = false;
    924                 if ( property_exists( $block_type, 'supports' ) ) {
    925                         /*
    926                          * Previous `color.__experimentalDuotone` support flag is migrated
    927                          * to `filter.duotone` via `block_type_metadata_settings` filter.
    928                          */
    929                         $has_duotone_support = _wp_array_get( $block_type->supports, array( 'filter', 'duotone' ), null );
    930                 }
    931 
    932                 if ( $has_duotone_support ) {
     924                /*
     925                 * Previous `color.__experimentalDuotone` support flag is migrated
     926                 * to `filter.duotone` via `block_type_metadata_settings` filter.
     927                 */
     928                if ( block_has_support( $block_type, array( 'filter', 'duotone' ), null ) ) {
    933929                        if ( ! $block_type->attributes ) {
    934930                                $block_type->attributes = array();
     
    949945         * if `filter.duotone` support is not defined.
    950946         *
    951          * @param string $block_name The block name.
    952          *
    953          * @internal
    954          *
    955          * @since 6.3.0
    956          *
    957          * @return string The CSS selector or null if there is no support.
    958          */
    959         private static function get_selector( $block_name ) {
    960                 $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name );
    961 
    962                 if ( $block_type && property_exists( $block_type, 'supports' ) ) {
    963                         /*
    964                          * Backwards compatibility with `supports.color.__experimentalDuotone`
    965                          * is provided via the `block_type_metadata_settings` filter. If
    966                          * `supports.filter.duotone` has not been set and the experimental
    967                          * property has been, the experimental property value is copied into
    968                          * `supports.filter.duotone`.
    969                          */
    970                         $duotone_support = _wp_array_get( $block_type->supports, array( 'filter', 'duotone' ), false );
    971                         if ( ! $duotone_support ) {
    972                                 return null;
    973                         }
    974 
    975                         /*
    976                          * If the experimental duotone support was set, that value is to be
    977                          * treated as a selector and requires scoping.
    978                          */
    979                         $experimental_duotone = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
    980                         if ( $experimental_duotone ) {
    981                                 $root_selector = wp_get_block_css_selector( $block_type );
    982                                 return is_string( $experimental_duotone )
    983                                         ? WP_Theme_JSON::scope_selector( $root_selector, $experimental_duotone )
    984                                         : $root_selector;
    985                         }
    986 
    987                         // Regular filter.duotone support uses filter.duotone selectors with fallbacks.
    988                         return wp_get_block_css_selector( $block_type, array( 'filter', 'duotone' ), true );
    989                 }
     947         * @internal
     948         * @since 6.3.0
     949         *
     950         * @param WP_Block_Type $block_type Block type to check for support.
     951         * @return string|null The CSS selector or null if there is no support.
     952         */
     953        private static function get_selector( $block_type ) {
     954                if ( ! ( $block_type instanceof WP_Block_Type ) ) {
     955                        return null;
     956                }
     957
     958                /*
     959                 * Backward compatibility with `supports.color.__experimentalDuotone`
     960                 * is provided via the `block_type_metadata_settings` filter. If
     961                 * `supports.filter.duotone` has not been set and the experimental
     962                 * property has been, the experimental property value is copied into
     963                 * `supports.filter.duotone`.
     964                 */
     965                $duotone_support = block_has_support( $block_type, array( 'filter', 'duotone' ) );
     966                if ( ! $duotone_support ) {
     967                        return null;
     968                }
     969
     970                /*
     971                 * If the experimental duotone support was set, that value is to be
     972                 * treated as a selector and requires scoping.
     973                 */
     974                $experimental_duotone = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
     975                if ( $experimental_duotone ) {
     976                        $root_selector = wp_get_block_css_selector( $block_type );
     977                        return is_string( $experimental_duotone )
     978                                ? WP_Theme_JSON::scope_selector( $root_selector, $experimental_duotone )
     979                                : $root_selector;
     980                }
     981
     982                // Regular filter.duotone support uses filter.duotone selectors with fallbacks.
     983                return wp_get_block_css_selector( $block_type, array( 'filter', 'duotone' ), true );
    990984        }
    991985
     
    998992         *
    999993         * @since 6.3.0
    1000          */
    1001         public static function set_global_styles_presets() {
     994         *
     995         * @return array An array of global styles presets, keyed on the filter ID.
     996         */
     997        private static function get_all_global_styles_presets() {
     998                if ( isset( self::$global_styles_presets ) ) {
     999                        return self::$global_styles_presets;
     1000                }
    10021001                // Get the per block settings from the theme.json.
    10031002                $tree              = wp_get_global_settings();
    10041003                $presets_by_origin = _wp_array_get( $tree, array( 'color', 'duotone' ), array() );
    10051004
     1005                self::$global_styles_presets = array();
    10061006                foreach ( $presets_by_origin as $presets ) {
    10071007                        foreach ( $presets as $preset ) {
     
    10111011                        }
    10121012                }
     1013
     1014                return self::$global_styles_presets;
    10131015        }
    10141016
     
    10201022         *
    10211023         * @since 6.3.0
    1022          */
    1023         public static function set_global_style_block_names() {
     1024         *
     1025         * @return string[] An array of global style block slugs, keyed on the block name.
     1026         */
     1027        private static function get_all_global_style_block_names() {
     1028                if ( isset( self::$global_styles_block_names ) ) {
     1029                        return self::$global_styles_block_names;
     1030                }
    10241031                // Get the per block settings from the theme.json.
    10251032                $tree        = WP_Theme_JSON_Resolver::get_merged_data();
    10261033                $block_nodes = $tree->get_styles_block_nodes();
    10271034                $theme_json  = $tree->get_raw_data();
     1035
     1036                self::$global_styles_block_names = array();
    10281037
    10291038                foreach ( $block_nodes as $block_node ) {
     
    10471056                        }
    10481057                }
     1058                return self::$global_styles_block_names;
    10491059        }
    10501060
     
    10571067         * @since 6.3.0
    10581068         *
    1059          * @param  string $block_content Rendered block content.
    1060          * @param  array  $block         Block object.
    1061          * @return string                Filtered block content.
    1062          */
    1063         public static function render_duotone_support( $block_content, $block ) {
    1064                 $duotone_selector = self::get_selector( $block['blockName'] );
     1069         * @param  string   $block_content Rendered block content.
     1070         * @param  array    $block         Block object.
     1071         * @param  WP_Block $wp_block      The block instance.
     1072         * @return string Filtered block content.
     1073         */
     1074        public static function render_duotone_support( $block_content, $block, $wp_block ) {
     1075                if ( empty( $block_content ) || ! $block['blockName'] ) {
     1076                        return $block_content;
     1077                }
     1078                $duotone_selector = self::get_selector( $wp_block->block_type );
     1079
     1080                if ( ! $duotone_selector ) {
     1081                        return $block_content;
     1082                }
     1083
     1084                $global_styles_block_names = self::get_all_global_style_block_names();
    10651085
    10661086                // The block should have a duotone attribute or have duotone defined in its theme.json to be processed.
    10671087                $has_duotone_attribute     = isset( $block['attrs']['style']['color']['duotone'] );
    1068                 $has_global_styles_duotone = array_key_exists( $block['blockName'], self::$global_styles_block_names );
    1069 
    1070                 if (
    1071                         empty( $block_content ) ||
    1072                         ! $duotone_selector ||
    1073                         ( ! $has_duotone_attribute && ! $has_global_styles_duotone )
    1074                 ) {
     1088                $has_global_styles_duotone = array_key_exists( $block['blockName'], $global_styles_block_names );
     1089
     1090                if ( ! $has_duotone_attribute && ! $has_global_styles_duotone ) {
    10751091                        return $block_content;
    10761092                }
     
    11201136                        }
    11211137                } elseif ( $has_global_styles_duotone ) {
    1122                         $slug         = self::$global_styles_block_names[ $block['blockName'] ]; // e.g. 'blue-orange'.
     1138                        $slug         = $global_styles_block_names[ $block['blockName'] ]; // e.g. 'blue-orange'.
    11231139                        $filter_id    = self::get_filter_id( $slug ); // e.g. 'wp-duotone-filter-blue-orange'.
    11241140                        $filter_value = self::get_css_var( $slug ); // e.g. 'var(--wp--preset--duotone--blue-orange)'.
     
    12071223         */
    12081224        public static function add_editor_settings( $settings ) {
    1209                 if ( ! empty( self::$global_styles_presets ) ) {
     1225                $global_styles_presets = self::get_all_global_styles_presets();
     1226                if ( ! empty( $global_styles_presets ) ) {
    12101227                        if ( ! isset( $settings['styles'] ) ) {
    12111228                                $settings['styles'] = array();
     
    12141231                        $settings['styles'][] = array(
    12151232                                // For the editor we can add all of the presets by default.
    1216                                 'assets'         => self::get_svg_definitions( self::$global_styles_presets ),
     1233                                'assets'         => self::get_svg_definitions( $global_styles_presets ),
    12171234                                // The 'svgs' type is new in 6.3 and requires the corresponding JS changes in the EditorStyles component to work.
    12181235                                '__unstableType' => 'svgs',
     
    12231240                        $settings['styles'][] = array(
    12241241                                // For the editor we can add all of the presets by default.
    1225                                 'css'            => self::get_global_styles_presets( self::$global_styles_presets ),
     1242                                'css'            => self::get_global_styles_presets( $global_styles_presets ),
    12261243                                // This must be set and must be something other than 'theme' or they will be stripped out in the post editor <Editor> component.
    12271244                                '__unstableType' => 'presets',
     
    12431260         * @param array $settings Current block type settings.
    12441261         * @param array $metadata Block metadata as read in via block.json.
    1245          *
    12461262         * @return array Filtered block type settings.
    12471263         */
Note: See TracChangeset for help on using the changeset viewer.