diff --git a/src/wp-includes/block-supports/duotone.php b/src/wp-includes/block-supports/duotone.php index b7964aa47809b..a90eb762ba8f0 100644 --- a/src/wp-includes/block-supports/duotone.php +++ b/src/wp-includes/block-supports/duotone.php @@ -40,12 +40,8 @@ ) ); -// Set up metadata prior to rendering any blocks. -add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_styles_presets' ), 10 ); -add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_style_block_names' ), 10 ); - // Add classnames to blocks using duotone support. -add_filter( 'render_block', array( 'WP_Duotone', 'render_duotone_support' ), 10, 2 ); +add_filter( 'render_block', array( 'WP_Duotone', 'render_duotone_support' ), 10, 3 ); // Enqueue styles. // Block styles (core-block-supports-inline-css) before the style engine (wp_enqueue_stored_styles). diff --git a/src/wp-includes/class-wp-duotone.php b/src/wp-includes/class-wp-duotone.php index b29f38acf5677..70d4798ba133b 100644 --- a/src/wp-includes/class-wp-duotone.php +++ b/src/wp-includes/class-wp-duotone.php @@ -54,7 +54,7 @@ class WP_Duotone { * * @var array */ - private static $global_styles_block_names = array(); + private static $global_styles_block_names; /** * An array of duotone filter data from global, theme, and custom presets. @@ -78,7 +78,7 @@ class WP_Duotone { * * @var array */ - private static $global_styles_presets = array(); + private static $global_styles_presets; /** * All of the duotone filter data from presets for CSS custom properties on @@ -575,7 +575,7 @@ private static function is_preset( $duotone_attr ) { $slug = self::get_slug_from_attribute( $duotone_attr ); $filter_id = self::get_filter_id( $slug ); - return array_key_exists( $filter_id, self::$global_styles_presets ); + return array_key_exists( $filter_id, self::get_all_global_styles_presets() ); } /** @@ -897,7 +897,8 @@ private static function enqueue_custom_filter( $filter_id, $duotone_selector, $f * @param string $filter_value The filter CSS value. e.g. 'url(#wp-duotone-blue-orange)' or 'unset'. */ private static function enqueue_global_styles_preset( $filter_id, $duotone_selector, $filter_value ) { - if ( ! array_key_exists( $filter_id, self::$global_styles_presets ) ) { + $global_styles_presets = self::get_all_global_styles_presets(); + if ( ! array_key_exists( $filter_id, $global_styles_presets ) ) { $error_message = sprintf( /* translators: %s: duotone filter ID */ __( 'The duotone id "%s" is not registered in theme.json settings' ), @@ -906,8 +907,8 @@ private static function enqueue_global_styles_preset( $filter_id, $duotone_selec _doing_it_wrong( __METHOD__, $error_message, '6.3.0' ); return; } - self::$used_global_styles_presets[ $filter_id ] = self::$global_styles_presets[ $filter_id ]; - self::enqueue_custom_filter( $filter_id, $duotone_selector, $filter_value, self::$global_styles_presets[ $filter_id ] ); + self::$used_global_styles_presets[ $filter_id ] = $global_styles_presets[ $filter_id ]; + self::enqueue_custom_filter( $filter_id, $duotone_selector, $filter_value, $global_styles_presets[ $filter_id ] ); } /** @@ -920,16 +921,11 @@ private static function enqueue_global_styles_preset( $filter_id, $duotone_selec * @param WP_Block_Type $block_type Block Type. */ public static function register_duotone_support( $block_type ) { - $has_duotone_support = false; - if ( property_exists( $block_type, 'supports' ) ) { - /* - * Previous `color.__experimentalDuotone` support flag is migrated - * to `filter.duotone` via `block_type_metadata_settings` filter. - */ - $has_duotone_support = _wp_array_get( $block_type->supports, array( 'filter', 'duotone' ), null ); - } - - if ( $has_duotone_support ) { + /* + * Previous `color.__experimentalDuotone` support flag is migrated + * to `filter.duotone` via `block_type_metadata_settings` filter. + */ + if ( block_has_support( $block_type, array( 'filter', 'duotone' ), null ) ) { if ( ! $block_type->attributes ) { $block_type->attributes = array(); } @@ -948,45 +944,43 @@ public static function register_duotone_support( $block_type ) { * This handles selectors defined in `color.__experimentalDuotone` support * if `filter.duotone` support is not defined. * - * @param string $block_name The block name. - * * @internal - * * @since 6.3.0 * - * @return string The CSS selector or null if there is no support. + * @param WP_Block_Type $block_type Block type to check for support. + * @return string|null The CSS selector or null if there is no support. */ - private static function get_selector( $block_name ) { - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name ); - - if ( $block_type && property_exists( $block_type, 'supports' ) ) { - /* - * Backwards compatibility with `supports.color.__experimentalDuotone` - * is provided via the `block_type_metadata_settings` filter. If - * `supports.filter.duotone` has not been set and the experimental - * property has been, the experimental property value is copied into - * `supports.filter.duotone`. - */ - $duotone_support = _wp_array_get( $block_type->supports, array( 'filter', 'duotone' ), false ); - if ( ! $duotone_support ) { - return null; - } + private static function get_selector( $block_type ) { + if ( ! ( $block_type instanceof WP_Block_Type ) ) { + return null; + } - /* - * If the experimental duotone support was set, that value is to be - * treated as a selector and requires scoping. - */ - $experimental_duotone = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false ); - if ( $experimental_duotone ) { - $root_selector = wp_get_block_css_selector( $block_type ); - return is_string( $experimental_duotone ) - ? WP_Theme_JSON::scope_selector( $root_selector, $experimental_duotone ) - : $root_selector; - } + /* + * Backward compatibility with `supports.color.__experimentalDuotone` + * is provided via the `block_type_metadata_settings` filter. If + * `supports.filter.duotone` has not been set and the experimental + * property has been, the experimental property value is copied into + * `supports.filter.duotone`. + */ + $duotone_support = block_has_support( $block_type, array( 'filter', 'duotone' ) ); + if ( ! $duotone_support ) { + return null; + } - // Regular filter.duotone support uses filter.duotone selectors with fallbacks. - return wp_get_block_css_selector( $block_type, array( 'filter', 'duotone' ), true ); + /* + * If the experimental duotone support was set, that value is to be + * treated as a selector and requires scoping. + */ + $experimental_duotone = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false ); + if ( $experimental_duotone ) { + $root_selector = wp_get_block_css_selector( $block_type ); + return is_string( $experimental_duotone ) + ? WP_Theme_JSON::scope_selector( $root_selector, $experimental_duotone ) + : $root_selector; } + + // Regular filter.duotone support uses filter.duotone selectors with fallbacks. + return wp_get_block_css_selector( $block_type, array( 'filter', 'duotone' ), true ); } /** @@ -997,12 +991,18 @@ private static function get_selector( $block_name ) { * use duotone preset filters. * * @since 6.3.0 + * + * @return array An array of global styles presets, keyed on the filter ID. */ - public static function set_global_styles_presets() { + private static function get_all_global_styles_presets() { + if ( isset( self::$global_styles_presets ) ) { + return self::$global_styles_presets; + } // Get the per block settings from the theme.json. $tree = wp_get_global_settings(); $presets_by_origin = _wp_array_get( $tree, array( 'color', 'duotone' ), array() ); + self::$global_styles_presets = array(); foreach ( $presets_by_origin as $presets ) { foreach ( $presets as $preset ) { $filter_id = self::get_filter_id( _wp_to_kebab_case( $preset['slug'] ) ); @@ -1010,6 +1010,8 @@ public static function set_global_styles_presets() { self::$global_styles_presets[ $filter_id ] = $preset; } } + + return self::$global_styles_presets; } /** @@ -1019,13 +1021,20 @@ public static function set_global_styles_presets() { * duotone filters defined in the theme.json global styles. * * @since 6.3.0 + * + * @return string[] An array of global style block slugs, keyed on the block name. */ - public static function set_global_style_block_names() { + private static function get_all_global_style_block_names() { + if ( isset( self::$global_styles_block_names ) ) { + return self::$global_styles_block_names; + } // Get the per block settings from the theme.json. $tree = WP_Theme_JSON_Resolver::get_merged_data(); $block_nodes = $tree->get_styles_block_nodes(); $theme_json = $tree->get_raw_data(); + self::$global_styles_block_names = array(); + foreach ( $block_nodes as $block_node ) { // This block definition doesn't include any duotone settings. Skip it. if ( empty( $block_node['duotone'] ) ) { @@ -1046,6 +1055,7 @@ public static function set_global_style_block_names() { self::$global_styles_block_names[ $block_node['name'] ] = $slug; } } + return self::$global_styles_block_names; } /** @@ -1056,22 +1066,28 @@ public static function set_global_style_block_names() { * * @since 6.3.0 * - * @param string $block_content Rendered block content. - * @param array $block Block object. - * @return string Filtered block content. + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @param WP_Block $wp_block The block instance. + * @return string Filtered block content. */ - public static function render_duotone_support( $block_content, $block ) { - $duotone_selector = self::get_selector( $block['blockName'] ); + public static function render_duotone_support( $block_content, $block, $wp_block ) { + if ( empty( $block_content ) || ! $block['blockName'] ) { + return $block_content; + } + $duotone_selector = self::get_selector( $wp_block->block_type ); + + if ( ! $duotone_selector ) { + return $block_content; + } + + $global_styles_block_names = self::get_all_global_style_block_names(); // The block should have a duotone attribute or have duotone defined in its theme.json to be processed. $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); - $has_global_styles_duotone = array_key_exists( $block['blockName'], self::$global_styles_block_names ); + $has_global_styles_duotone = array_key_exists( $block['blockName'], $global_styles_block_names ); - if ( - empty( $block_content ) || - ! $duotone_selector || - ( ! $has_duotone_attribute && ! $has_global_styles_duotone ) - ) { + if ( ! $has_duotone_attribute && ! $has_global_styles_duotone ) { return $block_content; } @@ -1119,7 +1135,7 @@ public static function render_duotone_support( $block_content, $block ) { self::enqueue_custom_filter( $filter_id, $duotone_selector, $filter_value, $filter_data ); } } elseif ( $has_global_styles_duotone ) { - $slug = self::$global_styles_block_names[ $block['blockName'] ]; // e.g. 'blue-orange'. + $slug = $global_styles_block_names[ $block['blockName'] ]; // e.g. 'blue-orange'. $filter_id = self::get_filter_id( $slug ); // e.g. 'wp-duotone-filter-blue-orange'. $filter_value = self::get_css_var( $slug ); // e.g. 'var(--wp--preset--duotone--blue-orange)'. @@ -1206,14 +1222,15 @@ public static function output_footer_assets() { * @return array The editor settings with duotone SVGs and CSS custom properties. */ public static function add_editor_settings( $settings ) { - if ( ! empty( self::$global_styles_presets ) ) { + $global_styles_presets = self::get_all_global_styles_presets(); + if ( ! empty( $global_styles_presets ) ) { if ( ! isset( $settings['styles'] ) ) { $settings['styles'] = array(); } $settings['styles'][] = array( // For the editor we can add all of the presets by default. - 'assets' => self::get_svg_definitions( self::$global_styles_presets ), + 'assets' => self::get_svg_definitions( $global_styles_presets ), // The 'svgs' type is new in 6.3 and requires the corresponding JS changes in the EditorStyles component to work. '__unstableType' => 'svgs', // These styles not generated by global styles, so this must be false or they will be stripped out in wp_get_block_editor_settings. @@ -1222,7 +1239,7 @@ public static function add_editor_settings( $settings ) { $settings['styles'][] = array( // For the editor we can add all of the presets by default. - 'css' => self::get_global_styles_presets( self::$global_styles_presets ), + 'css' => self::get_global_styles_presets( $global_styles_presets ), // This must be set and must be something other than 'theme' or they will be stripped out in the post editor component. '__unstableType' => 'presets', // These styles are no longer generated by global styles, so this must be false or they will be stripped out in wp_get_block_editor_settings. @@ -1242,7 +1259,6 @@ public static function add_editor_settings( $settings ) { * * @param array $settings Current block type settings. * @param array $metadata Block metadata as read in via block.json. - * * @return array Filtered block type settings. */ public static function migrate_experimental_duotone_support_flag( $settings, $metadata ) { diff --git a/src/wp-includes/deprecated.php b/src/wp-includes/deprecated.php index 812bf54f23188..169b4cc227227 100644 --- a/src/wp-includes/deprecated.php +++ b/src/wp-includes/deprecated.php @@ -5215,7 +5215,8 @@ function wp_register_duotone_support( $block_type ) { */ function wp_render_duotone_support( $block_content, $block ) { _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Duotone::render_duotone_support()' ); - return WP_Duotone::render_duotone_support( $block_content, $block ); + $wp_block = new WP_Block( $block ); + return WP_Duotone::render_duotone_support( $block_content, $block, $wp_block ); } /** diff --git a/tests/phpunit/tests/block-supports/duotone.php b/tests/phpunit/tests/block-supports/duotone.php index 672e91c00bc6a..2077ef705b19a 100644 --- a/tests/phpunit/tests/block-supports/duotone.php +++ b/tests/phpunit/tests/block-supports/duotone.php @@ -27,9 +27,10 @@ public function test_render_duotone_support_preset() { 'blockName' => 'core/image', 'attrs' => array( 'style' => array( 'color' => array( 'duotone' => 'var:preset|duotone|blue-orange' ) ) ), ); + $wp_block = new WP_Block( $block ); $block_content = '
'; $expected = '
'; - $this->assertSame( $expected, WP_Duotone::render_duotone_support( $block_content, $block ) ); + $this->assertSame( $expected, WP_Duotone::render_duotone_support( $block_content, $block, $wp_block ) ); } /** @@ -44,9 +45,10 @@ public function test_render_duotone_support_css() { 'blockName' => 'core/image', 'attrs' => array( 'style' => array( 'color' => array( 'duotone' => 'unset' ) ) ), ); + $wp_block = new WP_Block( $block ); $block_content = '
'; $expected = '/
<\\/figure>/'; - $this->assertMatchesRegularExpression( $expected, WP_Duotone::render_duotone_support( $block_content, $block ) ); + $this->assertMatchesRegularExpression( $expected, WP_Duotone::render_duotone_support( $block_content, $block, $wp_block ) ); } /** @@ -59,9 +61,10 @@ public function test_render_duotone_support_custom() { 'blockName' => 'core/image', 'attrs' => array( 'style' => array( 'color' => array( 'duotone' => array( '#FFFFFF', '#000000' ) ) ) ), ); + $wp_block = new WP_Block( $block ); $block_content = '
'; $expected = '/
<\\/figure>/'; - $this->assertMatchesRegularExpression( $expected, WP_Duotone::render_duotone_support( $block_content, $block ) ); + $this->assertMatchesRegularExpression( $expected, WP_Duotone::render_duotone_support( $block_content, $block, $wp_block ) ); } /** diff --git a/tests/phpunit/tests/blocks/supportedStyles.php b/tests/phpunit/tests/blocks/supportedStyles.php index d3b1a191de242..95c5326b4542f 100644 --- a/tests/phpunit/tests/blocks/supportedStyles.php +++ b/tests/phpunit/tests/blocks/supportedStyles.php @@ -695,13 +695,14 @@ public function test_render_block_suppresses_warnings_without_at_suppression() { ); $this->register_block_type( 'core/example', $block_type_settings ); - $block = array( + $block = array( 'blockName' => 'core/example', 'attrs' => array(), 'innerBlock' => array(), 'innerContent' => array(), 'innerHTML' => array(), ); + $wp_block = new WP_Block( $block ); // Custom error handler's see Warnings even if they are suppressed by the @ symbol. $errors = array(); @@ -714,7 +715,7 @@ static function ( $errno = 0, $errstr = '' ) use ( &$errors ) { // HTML5 elements like