Skip to content

Commit

Permalink
Fix duotone theme cache (#36236)
Browse files Browse the repository at this point in the history
Co-authored-by: André <[email protected]>
  • Loading branch information
2 people authored and Mamaduka committed Feb 16, 2022
1 parent b2e5f3f commit ee122f9
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 46 deletions.
102 changes: 62 additions & 40 deletions lib/block-supports/duotone.php
Original file line number Diff line number Diff line change
Expand Up @@ -290,50 +290,43 @@ function gutenberg_tinycolor_string_to_rgb( $color_str ) {
}
}


/**
* Registers the style and colors block attributes for block types that support it.
* Returns the prefixed id for the duotone filter for use as a CSS id.
*
* @param WP_Block_Type $block_type Block Type.
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone filter CSS id.
*/
function gutenberg_register_duotone_support( $block_type ) {
$has_duotone_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$has_duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
}

if ( $has_duotone_support ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}

if ( ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}
function gutenberg_get_duotone_filter_id( $preset ) {
return 'wp-duotone-' . $preset['slug'];
}

/**
* Renders the duotone filter SVG and returns the CSS filter property to
* reference the rendered SVG.
* Returns the CSS filter property url to reference the rendered SVG.
*
* @param array $preset Duotone preset value as seen in theme.json.
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone CSS filter property url value.
*/
function gutenberg_get_duotone_filter_property( $preset ) {
$filter_id = gutenberg_get_duotone_filter_id( $preset );
return "url('#" . $filter_id . "')";
}

/**
* Returns the duotone filter SVG string for the preset.
*
* @return string Duotone CSS filter property.
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone SVG filter.
*/
function gutenberg_render_duotone_filter_preset( $preset ) {
$duotone_id = $preset['slug'];
$duotone_colors = $preset['colors'];
$filter_id = 'wp-duotone-' . $duotone_id;
function gutenberg_get_duotone_filter_svg( $preset ) {
$filter_id = gutenberg_get_duotone_filter_id( $preset );

$duotone_values = array(
'r' => array(),
'g' => array(),
'b' => array(),
'a' => array(),
);
foreach ( $duotone_colors as $color_str ) {
foreach ( $preset['colors'] as $color_str ) {
$color = gutenberg_tinycolor_string_to_rgb( $color_str );

$duotone_values['r'][] = $color['r'] / 255;
Expand Down Expand Up @@ -389,17 +382,31 @@ function gutenberg_render_duotone_filter_preset( $preset ) {
$svg = trim( $svg );
}

add_action(
// SVG filters won't render at all in the head of a document and
// Safari incorrectly renders SVG filters in the footer, so the
// beginning of the body seems to be the safest place to render.
'wp_body_open',
function () use ( $svg ) {
echo $svg;
return $svg;
}

/**
* Registers the style and colors block attributes for block types that support it.
*
* @param WP_Block_Type $block_type Block Type.
*/
function gutenberg_register_duotone_support( $block_type ) {
$has_duotone_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$has_duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
}

if ( $has_duotone_support ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
);

return "url('#" . $filter_id . "')";
if ( ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}
}

/**
Expand Down Expand Up @@ -430,8 +437,9 @@ function gutenberg_render_duotone_support( $block_content, $block ) {
'slug' => uniqid(),
'colors' => $block['attrs']['style']['color']['duotone'],
);
$filter_property = gutenberg_render_duotone_filter_preset( $filter_preset );
$filter_id = 'wp-duotone-' . $filter_preset['slug'];
$filter_property = gutenberg_get_duotone_filter_property( $filter_preset );
$filter_id = gutenberg_get_duotone_filter_id( $filter_preset );
$filter_svg = gutenberg_get_duotone_filter_svg( $filter_preset );

$scope = '.' . $filter_id;
$selectors = explode( ',', $duotone_support );
Expand All @@ -451,6 +459,20 @@ function gutenberg_render_duotone_support( $block_content, $block ) {
wp_add_inline_style( $filter_id, $filter_style );
wp_enqueue_style( $filter_id );

// Render any custom filter the user may have added.
add_action(
// There are a couple of known rendering quirks in Safari.
// 1. Filters won't render at all when the SVG is in the head of
// the document.
// 2. Filters display incorrectly when the SVG is defined after
// where the filter is used in the document, so the footer does
// not work.
'wp_body_open',
function () use ( $filter_svg ) {
echo $filter_svg;
}
);

// Like the layout hook, this assumes the hook only applies to blocks with a single wrapper.
return preg_replace(
'/' . preg_quote( 'class="', '/' ) . '/',
Expand Down
35 changes: 34 additions & 1 deletion lib/compat/wordpress-5.9/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class WP_Theme_JSON_Gutenberg {
'path' => array( 'color', 'duotone' ),
'override' => true,
'use_default_names' => false,
'value_func' => 'gutenberg_render_duotone_filter_preset',
'value_func' => 'gutenberg_get_duotone_filter_property',
'css_vars' => '--wp--preset--duotone--$slug',
'classes' => array(),
'properties' => array( 'filter' ),
Expand Down Expand Up @@ -1494,6 +1494,39 @@ public function merge( $incoming ) {
}
}

/**
* Converts all filter (duotone) presets into SVGs.
*
* @param array $origins List of origins to process.
*
* @return string SVG filters.
*/
public function get_svg_filters( $origins ) {
$blocks_metadata = self::get_blocks_metadata();
$setting_nodes = self::get_setting_nodes( $this->theme_json, $blocks_metadata );

foreach ( $setting_nodes as $metadata ) {
$node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
if ( empty( $node['color']['duotone'] ) ) {
continue;
}

$duotone_presets = $node['color']['duotone'];

$filters = '';
foreach ( $origins as $origin ) {
if ( ! isset( $duotone_presets[ $origin ] ) ) {
continue;
}
foreach ( $duotone_presets[ $origin ] as $duotone_preset ) {
$filters .= gutenberg_get_duotone_filter_svg( $duotone_preset );
}
}
}

return $filters;
}

/**
* Returns whether a presets should be overriden or not.
*
Expand Down
52 changes: 47 additions & 5 deletions lib/compat/wordpress-5.9/get-global-styles-and-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ function wp_get_global_stylesheet( $types = array() ) {
// Return cached value if it can be used and exists.
// It's cached by theme to make sure that theme switching clears the cache.
$can_use_cached = (
( empty( $types ) ) &&
( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) &&
( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) &&
( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) &&
! is_admin()
( empty( $types ) ) &&
( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) &&
( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) &&
( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) &&
! is_admin()
);
$transient_name = 'gutenberg_global_styles_' . get_stylesheet();
if ( $can_use_cached ) {
Expand Down Expand Up @@ -132,3 +132,45 @@ function wp_get_global_stylesheet( $types = array() ) {
return $stylesheet;
}
}

if ( ! function_exists( 'wp_get_global_styles_svg_filters' ) ) {
/**
* Returns a string containing the SVGs to be referenced as filters (duotone).
*
* @return string
*/
function wp_get_global_styles_svg_filters() {
// Return cached value if it can be used and exists.
// It's cached by theme to make sure that theme switching clears the cache.
$transient_name = 'gutenberg_global_styles_svg_filters_' . get_stylesheet();
$can_use_cached = (
( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) &&
( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) &&
( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) &&
! is_admin()
);
if ( $can_use_cached ) {
$cached = get_transient( $transient_name );
if ( $cached ) {
return $cached;
}
}

$supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support();

$origins = array( 'default', 'theme' );
if ( ! $supports_theme_json ) {
$origins = array( 'default' );
}

$tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
$svgs = $tree->get_svg_filters( $origins );

if ( $can_use_cached ) {
// Cache for a minute, same as gutenberg_get_global_stylesheet.
set_transient( $transient_name, $svgs, MINUTE_IN_SECONDS );
}

return $svgs;
}
}
26 changes: 26 additions & 0 deletions lib/compat/wordpress-5.9/render-svg-filters.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
/**
* Renders the SVG filters for duotone.
*
* @package gutenberg
*/

/**
* Render the SVG filters supplied by theme.json.
*
* Note that this doesn't render the per-block user-defined
* filters which are handled by duotone.php, but it should
* be rendered in the same location as those to satisfy
* Safari's rendering quirks.
*/
function gutenberg_experimental_global_styles_render_svg_filters() {
$filters = wp_get_global_styles_svg_filters();
if ( ! empty( $filters ) ) {
echo $filters;
}
}

add_action(
'wp_body_open',
'gutenberg_experimental_global_styles_render_svg_filters'
);
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-5.9/default-editor-styles.php';
require __DIR__ . '/compat/wordpress-5.9/register-global-styles-cpt.php';
require __DIR__ . '/compat/wordpress-5.9/get-global-styles-and-settings.php';
require __DIR__ . '/compat/wordpress-5.9/render-svg-filters.php';
require __DIR__ . '/compat/wordpress-5.9/json-file-decode.php';
require __DIR__ . '/compat/wordpress-5.9/translate-settings-using-i18n-schema.php';
require __DIR__ . '/compat/wordpress-5.9/theme-templates.php';
Expand Down

0 comments on commit ee122f9

Please sign in to comment.