| @@ -15,9 +15,9 @@ | ||
| 15 | 15 | * @param int $max Upper value of the range to bound to. |
| 16 | 16 | * @return float Value in the range [0,1]. |
| 17 | 17 | */ |
| 18 | 18 | function gutenberg_tinycolor_bound01( $n, $max ) { |
| 19 | - if ( 'string' === gettype( $n ) && false !== strpos( $n, '.' ) && 1 === (float) $n ) { | |
| 19 | + if ( 'string' === gettype( $n ) && str_contains( $n, '.' ) && 1 === (float) $n ) { | |
| 20 | 20 | $n = '100%'; |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | $n = min( $max, max( 0, (float) $n ) ); |
| @@ -22,9 +22,9 @@ | ||
| 22 | 22 | |
| 23 | 23 | $n = min( $max, max( 0, (float) $n ) ); |
| 24 | 24 | |
| 25 | 25 | // Automatically convert percentage into number. |
| 26 | - if ( 'string' === gettype( $n ) && false !== strpos( $n, '%' ) ) { | |
| 26 | + if ( 'string' === gettype( $n ) && str_contains( $n, '%' ) ) { | |
| 27 | 27 | $n = (int) ( $n * $max ) / 100; |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | 30 | // Handle floating point rounding errors. |
| @@ -82,12 +82,12 @@ | ||
| 82 | 82 | * @return float R, G, or B component. |
| 83 | 83 | */ |
| 84 | 84 | function gutenberg_tinycolor_hue_to_rgb( $p, $q, $t ) { |
| 85 | 85 | if ( $t < 0 ) { |
| 86 | - $t += 1; | |
| 86 | + ++$t; | |
| 87 | 87 | } |
| 88 | 88 | if ( $t > 1 ) { |
| 89 | - $t -= 1; | |
| 89 | + --$t; | |
| 90 | 90 | } |
| 91 | 91 | if ( $t < 1 / 6 ) { |
| 92 | 92 | return $p + ( $q - $p ) * 6 * $t; |
| 93 | 93 | } |
| @@ -296,8 +296,12 @@ | ||
| 296 | 296 | * @param array $preset Duotone preset value as seen in theme.json. |
| 297 | 297 | * @return string Duotone filter CSS id. |
| 298 | 298 | */ |
| 299 | 299 | function gutenberg_get_duotone_filter_id( $preset ) { |
| 300 | + if ( ! isset( $preset['slug'] ) ) { | |
| 301 | + return ''; | |
| 302 | + } | |
| 303 | + | |
| 300 | 304 | return 'wp-duotone-' . $preset['slug']; |
| 301 | 305 | } |
| 302 | 306 | |
| 303 | 307 | /** |
| @@ -306,8 +310,11 @@ | ||
| 306 | 310 | * @param array $preset Duotone preset value as seen in theme.json. |
| 307 | 311 | * @return string Duotone CSS filter property url value. |
| 308 | 312 | */ |
| 309 | 313 | function gutenberg_get_duotone_filter_property( $preset ) { |
| 314 | + if ( isset( $preset['colors'] ) && 'unset' === $preset['colors'] ) { | |
| 315 | + return 'none'; | |
| 316 | + } | |
| 310 | 317 | $filter_id = gutenberg_get_duotone_filter_id( $preset ); |
| 311 | 318 | return "url('#" . $filter_id . "')"; |
| 312 | 319 | } |
| 313 | 320 | |
| @@ -325,8 +332,13 @@ | ||
| 325 | 332 | 'g' => array(), |
| 326 | 333 | 'b' => array(), |
| 327 | 334 | 'a' => array(), |
| 328 | 335 | ); |
| 336 | + | |
| 337 | + if ( ! isset( $preset['colors'] ) || ! is_array( $preset['colors'] ) ) { | |
| 338 | + $preset['colors'] = array(); | |
| 339 | + } | |
| 340 | + | |
| 329 | 341 | foreach ( $preset['colors'] as $color_str ) { |
| 330 | 342 | $color = gutenberg_tinycolor_string_to_rgb( $color_str ); |
| 331 | 343 | |
| 332 | 344 | $duotone_values['r'][] = $color['r'] / 255; |
| @@ -377,9 +389,9 @@ | ||
| 377 | 389 | |
| 378 | 390 | if ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) { |
| 379 | 391 | // Clean up the whitespace. |
| 380 | 392 | $svg = preg_replace( "/[\r\n\t ]+/", ' ', $svg ); |
| 381 | - $svg = preg_replace( '/> </', '><', $svg ); | |
| 393 | + $svg = str_replace( '> <', '><', $svg ); | |
| 382 | 394 | $svg = trim( $svg ); |
| 383 | 395 | } |
| 384 | 396 | |
| 385 | 397 | return $svg; |
| @@ -432,15 +444,16 @@ | ||
| 432 | 444 | ) { |
| 433 | 445 | return $block_content; |
| 434 | 446 | } |
| 435 | 447 | |
| 448 | + $colors = $block['attrs']['style']['color']['duotone']; | |
| 449 | + $filter_key = is_array( $colors ) ? implode( '-', $colors ) : $colors; | |
| 436 | 450 | $filter_preset = array( |
| 437 | - 'slug' => uniqid(), | |
| 438 | - 'colors' => $block['attrs']['style']['color']['duotone'], | |
| 451 | + 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), | |
| 452 | + 'colors' => $colors, | |
| 439 | 453 | ); |
| 440 | 454 | $filter_property = gutenberg_get_duotone_filter_property( $filter_preset ); |
| 441 | 455 | $filter_id = gutenberg_get_duotone_filter_id( $filter_preset ); |
| 442 | - $filter_svg = gutenberg_get_duotone_filter_svg( $filter_preset ); | |
| 443 | 456 | |
| 444 | 457 | $scope = '.' . $filter_id; |
| 445 | 458 | $selectors = explode( ',', $duotone_support ); |
| 446 | 459 | $scoped = array(); |
| @@ -458,27 +471,34 @@ | ||
| 458 | 471 | wp_register_style( $filter_id, false, array(), true, true ); |
| 459 | 472 | wp_add_inline_style( $filter_id, $filter_style ); |
| 460 | 473 | wp_enqueue_style( $filter_id ); |
| 461 | 474 | |
| 462 | - add_action( | |
| 463 | - 'wp_footer', | |
| 464 | - function () use ( $filter_svg, $selector ) { | |
| 465 | - echo $filter_svg; | |
| 475 | + if ( 'unset' !== $colors ) { | |
| 476 | + $filter_svg = gutenberg_get_duotone_filter_svg( $filter_preset ); | |
| 477 | + add_action( | |
| 478 | + 'wp_footer', | |
| 479 | + static function () use ( $filter_svg, $selector ) { | |
| 480 | + echo $filter_svg; | |
| 466 | 481 | |
| 467 | - // Safari renders elements incorrectly on first paint when the SVG | |
| 468 | - // filter comes after the content that it is filtering, so we force | |
| 469 | - // a repaint with a WebKit hack which solves the issue. | |
| 470 | - global $is_safari; | |
| 471 | - if ( $is_safari ) { | |
| 472 | - printf( | |
| 473 | - // Simply accessing el.offsetHeight flushes layout and style | |
| 474 | - // changes in WebKit without having to wait for setTimeout. | |
| 475 | - '<script>( function() { var el = document.querySelector( %s ); var display = el.style.display; el.style.display = "none"; el.offsetHeight; el.style.display = display; } )();</script>', | |
| 476 | - wp_json_encode( $selector ) | |
| 477 | - ); | |
| 482 | + /* | |
| 483 | + * Safari renders elements incorrectly on first paint when the | |
| 484 | + * SVG filter comes after the content that it is filtering, so | |
| 485 | + * we force a repaint with a WebKit hack which solves the issue. | |
| 486 | + */ | |
| 487 | + global $is_safari; | |
| 488 | + if ( $is_safari ) { | |
| 489 | + /* | |
| 490 | + * Simply accessing el.offsetHeight flushes layout and style | |
| 491 | + * changes in WebKit without having to wait for setTimeout. | |
| 492 | + */ | |
| 493 | + printf( | |
| 494 | + '<script>( function() { var el = document.querySelector( %s ); var display = el.style.display; el.style.display = "none"; el.offsetHeight; el.style.display = display; } )();</script>', | |
| 495 | + wp_json_encode( $selector ) | |
| 496 | + ); | |
| 497 | + } | |
| 478 | 498 | } |
| 479 | - } | |
| 480 | - ); | |
| 499 | + ); | |
| 500 | + } | |
| 481 | 501 | |
| 482 | 502 | // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper. |
| 483 | 503 | return preg_replace( |
| 484 | 504 | '/' . preg_quote( 'class="', '/' ) . '/', |