Commit 7ad71ce4112 for woocommerce
commit 7ad71ce4112fb30c1b3a02594945f137e1d0fc79
Author: Albert Juhé Lluveras <contact@albertjuhe.com>
Date: Mon Sep 7 16:23:11 2026 +0200
Optimize StyleAttributesUtils so unused styles aren't computed (#68345)
* Add changelog
* Optimize StyleAttributesUtils so unused styles aren't computed
* Fix method return type
* Simplify get_align_class_and_style() method
* Harden checks
* Simplify checks
* Use call_user_func() to call the methods dynamically
* Update PHPStan
* Add tests to StyleAttributesUtils
* Cover the selected-and-excluded overlap
diff --git a/plugins/woocommerce/changelog/fix-style-attributes-utils-optimizations b/plugins/woocommerce/changelog/fix-style-attributes-utils-optimizations
new file mode 100644
index 00000000000..48009f8ac07
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-style-attributes-utils-optimizations
@@ -0,0 +1,5 @@
+Significance: patch
+Type: performance
+Comment: Optimize StyleAttributesUtils so unused styles aren't computed
+
+
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 594918b0b8a..b0323bab2f7 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -54039,12 +54039,6 @@ parameters:
count: 1
path: src/Blocks/Utils/StyleAttributesUtils.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\Utils\\StyleAttributesUtils\:\:join_styles\(\) should return array but returns string\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/Utils/StyleAttributesUtils.php
-
-
message: '#^Parameter \#1 \$version1 of function version_compare expects string, string\|null given\.$#'
identifier: argument.type
diff --git a/plugins/woocommerce/src/Blocks/Utils/StyleAttributesUtils.php b/plugins/woocommerce/src/Blocks/Utils/StyleAttributesUtils.php
index 8314c0c964d..8ce4df2330b 100644
--- a/plugins/woocommerce/src/Blocks/Utils/StyleAttributesUtils.php
+++ b/plugins/woocommerce/src/Blocks/Utils/StyleAttributesUtils.php
@@ -88,37 +88,9 @@ class StyleAttributesUtils {
public static function get_align_class_and_style( $attributes ) {
$align_attribute = $attributes['align'] ?? null;
- if ( 'wide' === $align_attribute ) {
+ if ( in_array( $align_attribute, array( 'wide', 'full', 'left', 'right', 'center' ), true ) ) {
return array(
- 'class' => 'alignwide',
- 'style' => null,
- );
- }
-
- if ( 'full' === $align_attribute ) {
- return array(
- 'class' => 'alignfull',
- 'style' => null,
- );
- }
-
- if ( 'left' === $align_attribute ) {
- return array(
- 'class' => 'alignleft',
- 'style' => null,
- );
- }
-
- if ( 'right' === $align_attribute ) {
- return array(
- 'class' => 'alignright',
- 'style' => null,
- );
- }
-
- if ( 'center' === $align_attribute ) {
- return array(
- 'class' => 'aligncenter',
+ 'class' => 'align' . $align_attribute,
'style' => null,
);
}
@@ -169,7 +141,7 @@ class StyleAttributesUtils {
* Join classes and styles while removing duplicates and null values.
*
* @param array $rules Array of classes or styles.
- * @return array
+ * @return string
*/
protected static function join_styles( $rules ) {
return implode( ' ', array_unique( array_filter( $rules ) ) );
@@ -274,13 +246,13 @@ class StyleAttributesUtils {
public static function get_border_width_class_and_style( $attributes ) {
$custom_border = $attributes['style']['border'] ?? '';
- if ( '' === $custom_border ) {
+ if ( ! is_array( $custom_border ) ) {
return self::EMPTY_STYLE;
}
$style = '';
- if ( array_key_exists( 'width', ( $custom_border ) ) && ! empty( $custom_border['width'] ) ) {
+ if ( ! empty( $custom_border['width'] ) ) {
// Linked sides.
$style = 'border-width:' . $custom_border['width'] . ';';
} else {
@@ -307,13 +279,13 @@ class StyleAttributesUtils {
public static function get_border_style_class_and_style( $attributes ) {
$custom_border = $attributes['style']['border'] ?? '';
- if ( '' === $custom_border ) {
+ if ( ! is_array( $custom_border ) ) {
return self::EMPTY_STYLE;
}
$style = '';
- if ( array_key_exists( 'style', ( $custom_border ) ) && ! empty( $custom_border['style'] ) ) {
+ if ( ! empty( $custom_border['style'] ) ) {
$style = 'border-style:' . $custom_border['style'] . ';';
} else {
foreach ( $custom_border as $side => $value ) {
@@ -374,16 +346,14 @@ class StyleAttributesUtils {
$custom_font_size = $attributes['style']['typography']['fontSize'] ?? '';
- if ( ! $font_size && '' === $custom_font_size ) {
- return self::EMPTY_STYLE;
- }
-
if ( $font_size ) {
return array(
'class' => sprintf( 'has-font-size has-%s-font-size', $font_size ),
'style' => null,
);
- } elseif ( '' !== $custom_font_size ) {
+ }
+
+ if ( '' !== $custom_font_size ) {
return array(
'class' => null,
'style' => sprintf( 'font-size: %s;', $custom_font_size ),
@@ -663,17 +633,15 @@ class StyleAttributesUtils {
$custom_text_color = $attributes['style']['color']['text'] ?? '';
- if ( ! $text_color && ! $custom_text_color ) {
- return self::EMPTY_STYLE;
- }
-
if ( $text_color ) {
return array(
'class' => sprintf( 'has-text-color has-%s-color', $text_color ),
'style' => null,
'value' => self::get_preset_value( $text_color ),
);
- } elseif ( $custom_text_color ) {
+ }
+
+ if ( $custom_text_color ) {
return array(
'class' => null,
'style' => sprintf( 'color: %s;', $custom_text_color ),
@@ -754,43 +722,40 @@ class StyleAttributesUtils {
* @return array
*/
public static function get_classes_and_styles_by_attributes( $attributes, $properties = array(), $exclude = array() ) {
- $classes_and_styles = array(
- 'align' => self::get_align_class_and_style( $attributes ),
- 'background_color' => self::get_background_color_class_and_style( $attributes ),
- 'border_color' => self::get_border_color_class_and_style( $attributes ),
- 'border_radius' => self::get_border_radius_class_and_style( $attributes ),
- 'border_width' => self::get_border_width_class_and_style( $attributes ),
- 'border_style' => self::get_border_style_class_and_style( $attributes ),
- 'font_family' => self::get_font_family_class_and_style( $attributes ),
- 'font_size' => self::get_font_size_class_and_style( $attributes ),
- 'font_style' => self::get_font_style_class_and_style( $attributes ),
- 'font_weight' => self::get_font_weight_class_and_style( $attributes ),
- 'letter_spacing' => self::get_letter_spacing_class_and_style( $attributes ),
- 'line_height' => self::get_line_height_class_and_style( $attributes ),
- 'margin' => self::get_margin_class_and_style( $attributes ),
- 'padding' => self::get_padding_class_and_style( $attributes ),
- 'shadow' => self::get_shadow_class_and_style( $attributes ),
- 'text_align' => self::get_text_align_class_and_style( $attributes ),
- 'text_color' => self::get_text_color_class_and_style( $attributes ),
- 'text_decoration' => self::get_text_decoration_class_and_style( $attributes ),
- 'text_transform' => self::get_text_transform_class_and_style( $attributes ),
- 'extra_classes' => self::get_classes_from_attributes( $attributes ),
+ $class_style_map = array(
+ 'align' => 'get_align_class_and_style',
+ 'background_color' => 'get_background_color_class_and_style',
+ 'border_color' => 'get_border_color_class_and_style',
+ 'border_radius' => 'get_border_radius_class_and_style',
+ 'border_width' => 'get_border_width_class_and_style',
+ 'border_style' => 'get_border_style_class_and_style',
+ 'font_family' => 'get_font_family_class_and_style',
+ 'font_size' => 'get_font_size_class_and_style',
+ 'font_style' => 'get_font_style_class_and_style',
+ 'font_weight' => 'get_font_weight_class_and_style',
+ 'letter_spacing' => 'get_letter_spacing_class_and_style',
+ 'line_height' => 'get_line_height_class_and_style',
+ 'margin' => 'get_margin_class_and_style',
+ 'padding' => 'get_padding_class_and_style',
+ 'shadow' => 'get_shadow_class_and_style',
+ 'text_align' => 'get_text_align_class_and_style',
+ 'text_color' => 'get_text_color_class_and_style',
+ 'text_decoration' => 'get_text_decoration_class_and_style',
+ 'text_transform' => 'get_text_transform_class_and_style',
+ 'extra_classes' => 'get_classes_from_attributes',
);
if ( ! empty( $properties ) ) {
- foreach ( $classes_and_styles as $key => $value ) {
- if ( ! in_array( $key, $properties, true ) ) {
- unset( $classes_and_styles[ $key ] );
- }
- }
+ $class_style_map = array_intersect_key( $class_style_map, array_flip( $properties ) );
}
if ( ! empty( $exclude ) ) {
- foreach ( $classes_and_styles as $key => $value ) {
- if ( in_array( $key, $exclude, true ) ) {
- unset( $classes_and_styles[ $key ] );
- }
- }
+ $class_style_map = array_diff_key( $class_style_map, array_flip( $exclude ) );
+ }
+
+ $classes_and_styles = array();
+ foreach ( $class_style_map as $key => $method ) {
+ $classes_and_styles[ $key ] = call_user_func( array( self::class, $method ), $attributes );
}
$classes_and_styles = array_filter( $classes_and_styles );
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Utils/StyleAttributesUtilsTest.php b/plugins/woocommerce/tests/php/src/Blocks/Utils/StyleAttributesUtilsTest.php
new file mode 100644
index 00000000000..3cd8e256647
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Blocks/Utils/StyleAttributesUtilsTest.php
@@ -0,0 +1,60 @@
+<?php
+declare( strict_types = 1 );
+
+namespace Automattic\WooCommerce\Tests\Blocks\Utils;
+
+use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
+use WC_Unit_Test_Case;
+
+/**
+ * Tests for StyleAttributesUtils.
+ */
+class StyleAttributesUtilsTest extends WC_Unit_Test_Case {
+
+ /**
+ * @testdox get_classes_and_styles_by_attributes() includes or excludes the requested handlers.
+ *
+ * @dataProvider provider_style_handler_dispatch
+ *
+ * @param array<int, string> $properties Properties to request.
+ * @param array<int, string> $exclude Properties to exclude.
+ * @param string $expected_classes Expected class output.
+ * @param string $expected_styles Expected style output.
+ */
+ public function test_get_classes_and_styles_by_attributes_dispatches_expected_handlers( array $properties, array $exclude, string $expected_classes, string $expected_styles ): void {
+ $attributes = array(
+ 'className' => 'extra',
+ 'fontSize' => 'large',
+ 'textColor' => 'vivid-red',
+ 'style' => array(
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '8px',
+ ),
+ ),
+ ),
+ );
+
+ $result = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes, $properties, $exclude );
+
+ $this->assertSame( $expected_classes, $result['classes'] );
+ $this->assertSame( $expected_styles, $result['styles'] );
+ }
+
+ /**
+ * @return array<string, array{array<int, string>, array<int, string>, string, string}>
+ */
+ public function provider_style_handler_dispatch(): array {
+ $all_classes = 'has-font-size has-large-font-size has-text-color has-vivid-red-color extra';
+ $padding = 'padding-top:8px;';
+
+ return array(
+ 'empty properties' => array( array(), array(), $all_classes, $padding ),
+ 'requested properties' => array( array( 'font_size', 'extra_classes' ), array(), 'has-font-size has-large-font-size extra', '' ),
+ 'exclude extra_classes' => array( array(), array( 'extra_classes' ), 'has-font-size has-large-font-size has-text-color has-vivid-red-color', $padding ),
+ 'exclude font_size' => array( array(), array( 'font_size' ), 'has-text-color has-vivid-red-color extra', $padding ),
+ 'exclude padding' => array( array(), array( 'padding' ), $all_classes, '' ),
+ 'requested and excluded font_size' => array( array( 'font_size' ), array( 'font_size' ), '', '' ),
+ );
+ }
+}