PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.36.0
MailPoet – Newsletters, Email Marketing, and Automation v5.36.0
5.36.0 5.35.1 5.35.0 5.34.3 5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / vendor / woocommerce / email-editor / src / Integrations / Utils / class-styles-helper.php
mailpoet / vendor / woocommerce / email-editor / src / Integrations / Utils Last commit date
class-dom-document-helper.php 2 weeks ago class-html-processing-helper.php 2 weeks ago class-social-links-helper.php 11 months ago class-styles-helper.php 6 months ago class-table-wrapper-helper.php 11 months ago index.php 11 months ago
class-styles-helper.php
219 lines
1 <?php
2 declare( strict_types = 1 );
3 namespace Automattic\WooCommerce\EmailEditor\Integrations\Utils;
4 if (!defined('ABSPATH')) exit;
5 use Automattic\WooCommerce\EmailEditor\Engine\Renderer\ContentRenderer\Rendering_Context;
6 use WP_Style_Engine;
7 class Styles_Helper {
8 public static $empty_block_styles = array(
9 'css' => '',
10 'declarations' => array(),
11 'classnames' => '',
12 );
13 public static function parse_value( $value ): float {
14 // Handle numeric values.
15 if ( is_numeric( $value ) ) {
16 return (float) $value;
17 }
18 // Handle string values.
19 if ( is_string( $value ) ) {
20 if ( preg_match( '/^\s*(-?\d+(?:\.\d+)?)/', $value, $m ) ) {
21 return (float) $m[1];
22 }
23 }
24 return 0.0;
25 }
26 public static function parse_styles_to_array( string $styles ): array {
27 $styles = explode( ';', $styles );
28 $parsed_styles = array();
29 foreach ( $styles as $style ) {
30 $style = explode( ':', $style, 2 );
31 if ( count( $style ) === 2 ) {
32 $parsed_styles[ trim( $style[0] ) ] = trim( $style[1] );
33 }
34 }
35 return $parsed_styles;
36 }
37 public static function get_normalized_block_styles( array $block_attributes, Rendering_Context $rendering_context ): array {
38 $normalized_colors = array_filter(
39 array(
40 'color' => array_filter(
41 array(
42 'background' => isset( $block_attributes['backgroundColor'] ) && $block_attributes['backgroundColor']
43 ? $rendering_context->translate_slug_to_color( $block_attributes['backgroundColor'] )
44 : null,
45 'text' => isset( $block_attributes['textColor'] ) && $block_attributes['textColor']
46 ? $rendering_context->translate_slug_to_color( $block_attributes['textColor'] )
47 : null,
48 )
49 ),
50 'border' => array_filter(
51 array(
52 'color' => isset( $block_attributes['borderColor'] ) && $block_attributes['borderColor']
53 ? $rendering_context->translate_slug_to_color( $block_attributes['borderColor'] )
54 : null,
55 )
56 ),
57 )
58 );
59 return array_replace_recursive(
60 $normalized_colors,
61 $block_attributes['style'] ?? array()
62 );
63 }
64 public static function get_styles_from_block( array $block_styles, $skip_convert_vars = false ) {
65 $unsupported_props = array(
66 'margin' => array( 'spacing', 'margin' ),
67 );
68 $unsupported_props = apply_filters( 'woocommerce_email_editor_styles_unsupported_props', $unsupported_props );
69 foreach ( $unsupported_props as $path ) {
70 if ( ! is_array( $path ) || count( $path ) === 0 ) {
71 continue;
72 }
73 $pointer = & $block_styles;
74 $last_key = array_pop( $path );
75 foreach ( $path as $segment ) {
76 if ( ! is_string( $segment ) && ! is_int( $segment ) ) {
77 continue 2;
78 }
79 if ( ! array_key_exists( $segment, $pointer ) || ! is_array( $pointer[ $segment ] ) ) {
80 continue 2;
81 }
82 $pointer = & $pointer[ $segment ];
83 }
84 if ( ( is_string( $last_key ) || is_int( $last_key ) ) && array_key_exists( $last_key, $pointer ) ) {
85 unset( $pointer[ $last_key ] );
86 }
87 }
88 return wp_parse_args(
89 wp_style_engine_get_styles( $block_styles, array( 'convert_vars_to_classnames' => $skip_convert_vars ) ),
90 self::$empty_block_styles
91 );
92 }
93 public static function extend_block_styles( array $block_styles, array $css_declarations ) {
94 // Ensure block_styles has the required WP_Style_Engine structure.
95 if ( ! isset( $block_styles['declarations'] ) || ! is_array( $block_styles['declarations'] ) ) {
96 $block_styles = self::$empty_block_styles;
97 }
98 $block_styles['declarations'] = array_merge( $block_styles['declarations'], $css_declarations );
99 $block_styles['css'] = WP_Style_Engine::compile_css( $block_styles['declarations'], '' );
100 return $block_styles;
101 }
102 public static function get_block_styles( array $block_attributes, Rendering_Context $rendering_context, array $properties ) {
103 $styles = self::get_normalized_block_styles( $block_attributes, $rendering_context );
104 $filtered_styles = array();
105 $style_mappings = array(
106 'spacing' => array( 'spacing' ),
107 'padding' => array( 'spacing', 'padding' ),
108 'margin' => array( 'spacing', 'margin' ),
109 'border' => array( 'border' ),
110 'border-width' => array( 'border', 'width' ),
111 'border-style' => array( 'border', 'style' ),
112 'border-radius' => array( 'border', 'radius' ),
113 'border-color' => array( 'border', 'color' ),
114 'background' => array( 'background' ),
115 'background-color' => array( 'color', 'background' ),
116 'color' => array( 'color', 'text' ),
117 'typography' => array( 'typography' ),
118 'font-size' => array( 'typography', 'fontSize' ),
119 'font-family' => array( 'typography', 'fontFamily' ),
120 'font-weight' => array( 'typography', 'fontWeight' ),
121 );
122 foreach ( $properties as $property ) {
123 if ( ! isset( $style_mappings[ $property ] ) ) {
124 continue;
125 }
126 $style_pointer = $styles;
127 foreach ( $style_mappings[ $property ] as $path_segment ) {
128 if ( ! isset( $style_pointer[ $path_segment ] ) ) {
129 continue 2;
130 }
131 $style_pointer = $style_pointer[ $path_segment ];
132 }
133 $filtered_styles_pointer = & $filtered_styles;
134 foreach ( $style_mappings[ $property ] as $path_index => $path_segment ) {
135 if ( count( $style_mappings[ $property ] ) - 1 === $path_index ) {
136 $filtered_styles_pointer[ $path_segment ] = $style_pointer;
137 break;
138 }
139 if ( ! isset( $filtered_styles_pointer[ $path_segment ] ) || ! is_array( $filtered_styles_pointer[ $path_segment ] ) ) {
140 $filtered_styles_pointer[ $path_segment ] = array();
141 }
142 $filtered_styles_pointer = & $filtered_styles_pointer[ $path_segment ];
143 }
144 }
145 $additional_css_declarations = array_filter(
146 array_intersect_key(
147 array(
148 'text-align' => $block_attributes['textAlign'] ?? null,
149 ),
150 array_flip( $properties )
151 )
152 );
153 $styles = count( $filtered_styles ) > 0 ? self::get_styles_from_block( $filtered_styles ) : self::$empty_block_styles;
154 return self::extend_block_styles( $styles, $additional_css_declarations );
155 }
156 public static function convert_to_px( string $input, bool $use_fallback = true, ?int $base_font_size = 16 ): ?string {
157 $fallback = $use_fallback ? $base_font_size . 'px' : null;
158 if ( ! $input ) {
159 return $fallback;
160 }
161 $input = trim( $input );
162 // Validate input against potentially malicious values.
163 if ( preg_match( '/[<>"\']/', $input ) ) {
164 return $fallback;
165 }
166 if ( str_ends_with( $input, 'px' ) ) {
167 // If already in px, return as is.
168 return $input;
169 }
170 if ( str_ends_with( $input, 'rem' ) || str_ends_with( $input, 'em' ) ) {
171 // Convert rem/em to px (assuming 16px base).
172 $value = (float) str_replace( array( 'rem', 'em' ), '', $input );
173 return round( $value * $base_font_size ) . 'px';
174 }
175 if ( str_ends_with( $input, '%' ) ) {
176 // Convert percentage to px (assuming 16px base).
177 $value = (float) str_replace( '%', '', $input );
178 return round( ( $value / 100 ) * $base_font_size ) . 'px';
179 }
180 if ( is_numeric( $input ) ) {
181 // If it's just a number, assume px.
182 return $input . 'px';
183 }
184 return $fallback;
185 }
186 public static function remove_css_unit( string $input ): string {
187 $units = array( 'px', 'pt', 'pc', 'rem', 'em', 'vmin', 'vmax', '%', 'vh', 'vw', 'ex', 'ch', 'fr' );
188 return str_ireplace( $units, '', $input );
189 }
190 public static function clamp_to_static_px( $clamp_str, $strategy = 'min' ): ?string {
191 if ( stripos( $clamp_str, 'clamp(' ) === false ) {
192 return $clamp_str;
193 }
194 $value_array = explode( ',', $clamp_str );
195 if ( count( $value_array ) < 2 ) {
196 return $clamp_str; // Invalid clamp format.
197 }
198 $first_element = $value_array[0];
199 $min = trim( str_ireplace( array( 'clamp(', 'min(', 'max(' ), '', $first_element ) );
200 $last_element = $value_array[ count( $value_array ) - 1 ];
201 $max = trim( rtrim( $last_element, ')' ) );
202 $min_px = self::convert_to_px( $min, false );
203 $max_px = self::convert_to_px( $max, false );
204 // Determine which value to use.
205 if ( 'min' === $strategy && ! is_null( $min_px ) ) {
206 return $min_px;
207 }
208 if ( 'max' === $strategy && ! is_null( $max_px ) ) {
209 return $max_px;
210 }
211 if ( 'avg' === $strategy && ! is_null( $min_px ) && ! is_null( $max_px ) ) {
212 $avg = ( self::parse_value( $min_px ) + self::parse_value( $max_px ) ) / 2;
213 return $avg . 'px';
214 }
215 // Default.
216 return $min_px ?? $max_px ?? $clamp_str;
217 }
218 }
219