PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/helpers/FrmStylesHelper.php +702 -138 6.5.2 → trunk View file →
@@ -4,10 +4,14 @@
4 4 }
5 5
6 6 class FrmStylesHelper {
7 7
8 + /**
9 + * @return array
10 + */
8 11 public static function get_upload_base() {
9 12 $uploads = wp_upload_dir();
13 +
10 14 if ( is_ssl() && ! preg_match( '/^https:\/\/.*\..*$/', $uploads['baseurl'] ) ) {
11 15 $uploads['baseurl'] = str_replace( 'http://', 'https://', $uploads['baseurl'] );
12 16 }
13 17
@@ -17,17 +21,23 @@
17 21 /**
18 22 * Called from the admin header.
19 23 *
20 24 * @since 4.0
25 + *
26 + * @return void
21 27 */
22 28 public static function save_button() {
29 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
23 30 ?>
24 31 <input type="submit" name="submit" class="button button-primary frm-button-primary" value="<?php esc_attr_e( 'Update', 'formidable' ); ?>" />
25 32 <?php
33 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
26 34 }
27 35
28 36 /**
29 37 * @since 2.05
38 + *
39 + * @return array
30 40 */
31 41 public static function get_css_label_positions() {
32 42 return array(
33 43 'none' => __( 'top', 'formidable' ),
@@ -37,10 +47,17 @@
37 47 'inside' => __( 'inside', 'formidable' ),
38 48 );
39 49 }
40 50
41 - public static function get_single_label_positions() {
42 - return array(
51 + /**
52 + * @since 6.11 Added $field param.
53 + *
54 + * @param array|object $field
55 + *
56 + * @return array
57 + */
58 + public static function get_single_label_positions( $field = array() ) {
59 + $label_positions = array(
43 60 'top' => __( 'Top', 'formidable' ),
44 61 'left' => __( 'Left', 'formidable' ),
45 62 'right' => __( 'Right', 'formidable' ),
46 63 'inline' => __( 'Inline (left without a set width)', 'formidable' ),
@@ -47,10 +64,23 @@
47 64 'none' => __( 'None', 'formidable' ),
48 65 'hidden' => __( 'Hidden (but leave the space)', 'formidable' ),
49 66 'inside' => __( 'Placeholder inside the field', 'formidable' ),
50 67 );
68 +
69 + /**
70 + * Allows updating label positions in field settings.
71 + *
72 + * @since 6.11
73 + *
74 + * @param array $label_positions
75 + * @param array|object $field
76 + */
77 + return apply_filters( 'frm_single_label_positions', $label_positions, $field );
51 78 }
52 79
80 + /**
81 + * @return array
82 + */
53 83 public static function minus_icons() {
54 84 return array(
55 85 0 => array(
56 86 '-' => '62e',
@@ -74,8 +104,11 @@
74 104 ),
75 105 );
76 106 }
77 107
108 + /**
109 + * @return array
110 + */
78 111 public static function arrow_icons() {
79 112 $minus_icons = self::minus_icons();
80 113
81 114 return array(
@@ -116,13 +149,18 @@
116 149 }
117 150
118 151 /**
119 152 * @since 2.0
153 + *
154 + * @param int|string $key Icon key.
155 + * @param string $icon Icon state, `+` or `-`.
156 + * @param string $type Icon type, such as `arrow`.
157 + *
120 158 * @return string The class for this icon.
121 159 */
122 160 public static function icon_key_to_class( $key, $icon = '+', $type = 'arrow' ) {
123 161 if ( 'arrow' === $type && is_numeric( $key ) ) {
124 - //frm_arrowup6_icon
162 + // frm_arrowup6_icon.
125 163 $arrow = array(
126 164 '-' => 'down',
127 165 '+' => 'up',
128 166 );
@@ -127,9 +165,9 @@
127 165 '+' => 'up',
128 166 );
129 167 $class = 'frm_arrow' . $arrow[ $icon ];
130 168 } else {
131 - //frm_minus1_icon
169 + // frm_minus1_icon.
132 170 $key = str_replace( 'p', '', $key );
133 171 $plus = array(
134 172 '-' => 'minus',
135 173 '+' => 'plus',
@@ -139,11 +177,10 @@
139 177
140 178 if ( $key ) {
141 179 $class .= $key;
142 180 }
143 - $class .= '_icon';
144 181
145 - return $class;
182 + return $class . '_icon';
146 183 }
147 184
148 185 /**
149 186 * @param WP_Post $style
@@ -148,8 +185,9 @@
148 185 /**
149 186 * @param WP_Post $style
150 187 * @param FrmStyle $frm_style
151 188 * @param string $type
189 + *
152 190 * @return void
153 191 */
154 192 public static function bs_icon_select( $style, $frm_style, $type = 'arrow' ) {
155 193 $function_name = $type . '_icons';
@@ -156,8 +194,9 @@
156 194 $icons = self::$function_name();
157 195 unset( $function_name );
158 196
159 197 $name = 'arrow' === $type ? 'collapse_icon' : 'repeat_icon';
198 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
160 199 ?>
161 200 <div class="btn-group" id="frm_<?php echo esc_attr( $name ); ?>_select">
162 201 <button class="multiselect dropdown-toggle btn btn-default" data-toggle="dropdown" type="button">
163 202 <?php FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $style->post_content[ $name ], '+', $type ) ); ?>
@@ -165,12 +204,12 @@
165 204 <b class="caret"></b>
166 205 </button>
167 206 <ul class="multiselect-container frm-dropdown-menu">
168 207 <?php foreach ( $icons as $key => $icon ) { ?>
169 - <li <?php echo ( $style->post_content['collapse_icon'] == $key ) ? 'class="active"' : ''; ?>>
208 + <li <?php echo $style->post_content['collapse_icon'] == $key ? 'class="active"' : ''; // phpcs:ignore Universal.Operators.StrictComparisons ?>>
170 209 <a href="javascript:void(0);">
171 210 <label>
172 - <input type="radio" value="<?php echo esc_attr( $key ); ?>" name="<?php echo esc_attr( $frm_style->get_field_name( $name ) ); ?>" <?php checked( $style->post_content[ $name ], $key ); ?> />
211 + <input type="radio" value="<?php echo esc_attr( $key ); ?>" name="<?php echo esc_attr( $frm_style->get_field_name( $name ) ); ?>" <?php checked( $style->post_content[ $name ], $key ); ?> /><?php // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong ?>
173 212 <span>
174 213 <?php
175 214 FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $key, '+', $type ) );
176 215 FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $key, '-', $type ) );
@@ -182,26 +221,71 @@
182 221 <?php } ?>
183 222 </ul>
184 223 </div>
185 224 <?php
225 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
186 226 }
187 227
188 - public static function hex2rgb( $hex ) {
189 - $hex = str_replace( '#', '', $hex );
228 + /**
229 + * Convert a color setting to a RGB CSV (without the rgb()/rgba() wrapper).
230 + *
231 + * @since 2.0
232 + *
233 + * @param string $color Color setting value. This could be hex or rgb.
234 + *
235 + * @return string RGB value without the rgb() wrapper.
236 + */
237 + public static function hex2rgb( $color ) {
238 + $rgb = str_starts_with( $color, 'rgb' ) ? self::get_rgb_array_from_rgb( $color ) : self::get_rgb_array_from_hex( $color );
239 + return implode( ',', $rgb );
240 + }
190 241
191 - list( $r, $g, $b ) = sscanf( $hex, '%02x%02x%02x' );
242 + /**
243 + * Remove the rgb()/rgba() wrapper from a RGB color and return its R, G and B values as an array.
244 + *
245 + * @since 6.8.3
246 + *
247 + * @param string $rgb RGB value including the rgb() or rgba() wrapper.
248 + *
249 + * @return array<string> including three numeric values for R, G, and B.
250 + */
251 + private static function get_rgb_array_from_rgb( $rgb ) {
252 + $rgb = str_replace( array( 'rgb(', 'rgba(', ')' ), '', $rgb );
253 + $rgb = explode( ',', $rgb );
192 254
193 - $rgb = array( $r, $g, $b );
255 + if ( 4 === count( $rgb ) ) {
256 + // Drop the alpha. The function is expected to only return r,g,b with no alpha.
257 + array_pop( $rgb );
258 + }
194 259
195 - return implode( ',', $rgb );
260 + return $rgb;
196 261 }
197 262
198 263 /**
264 + * Get the R, G, and B array values from a Hex color code.
265 + *
266 + * @since 6.8.3
267 + *
268 + * @param string $hex A hex color string.
269 + *
270 + * @return array<string> Including three numeric values for R, G, and B.
271 + */
272 + private static function get_rgb_array_from_hex( $hex ) {
273 + $hex = str_replace( '#', '', $hex );
274 + list( $r, $g, $b ) = sscanf( $hex, '%02x%02x%02x' );
275 + return array( $r, $g, $b );
276 + }
277 +
278 + /**
199 279 * @since 4.0
280 + *
281 + * @param string $hex Hex color string.
282 + * @param float|int|string $a Alpha channel value.
283 + *
284 + * @return string
200 285 */
201 286 public static function hex2rgba( $hex, $a ) {
202 287 $rgb = self::hex2rgb( $hex );
203 -
204 288 return 'rgba(' . $rgb . ',' . $a . ')';
205 289 }
206 290
207 291 /**
@@ -206,13 +290,15 @@
206 290
207 291 /**
208 292 * @since 6.0
209 293 *
210 - * @param string $rgba
211 - * @return string
294 + * @param string $rgba Color setting value. This could be hex or rgb.
295 + *
296 + * @return string Hex color value.
212 297 */
213 298 private static function rgb_to_hex( $rgba ) {
214 - if ( strpos( $rgba, '#' ) === 0 ) {
299 + if ( str_starts_with( $rgba, '#' ) ) {
300 + // Color is already hex.
215 301 return $rgba;
216 302 }
217 303 preg_match( '/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i', $rgba, $by_color );
218 304 return sprintf( '%02x%02x%02x', $by_color[1], $by_color[2], $by_color[3] );
@@ -218,17 +304,80 @@
218 304 return sprintf( '%02x%02x%02x', $by_color[1], $by_color[2], $by_color[3] );
219 305 }
220 306
221 307 /**
222 - * @param $hex string - The original color in hex format #ffffff
223 - * @param $steps integer - should be between -255 and 255. Negative = darker, positive = lighter
308 + * @since 6.8
224 309 *
310 + * @param string $hsl
311 + *
312 + * @return string|null Null if it fails to parse the HSL string.
313 + */
314 + private static function hsl_to_hex( $hsl ) {
315 + // Convert hsla to hsl.
316 + $hsl = preg_replace( '/hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/', 'hsl($1, $2%, $3%)', $hsl );
317 +
318 + // Extract HSL components from the color string.
319 + preg_match( '/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/', $hsl, $matches );
320 +
321 + if ( count( $matches ) !== 4 ) {
322 + // Invalid HSL string format.
323 + return null;
324 + }
325 +
326 + // Extract HSL values.
327 + $h = (int) $matches[1];
328 + $s = (int) $matches[2] / 100;
329 + $l = (int) $matches[3] / 100;
330 +
331 + // Calculate RGB values.
332 + $c = ( 1 - abs( 2 * $l - 1 ) ) * $s;
333 + $x = $c * ( 1 - abs( ( (int) ( $h / 60 ) % 2 ) - 1 ) );
334 + $m = $l - $c / 2;
335 + $r = 0;
336 + $g = 0;
337 + $b = 0;
338 +
339 + if ( $h >= 0 && $h < 60 ) {
340 + $r = $c;
341 + $g = $x;
342 + } elseif ( $h >= 60 && $h < 120 ) {
343 + $r = $x;
344 + $g = $c;
345 + } elseif ( $h >= 120 && $h < 180 ) {
346 + $g = $c;
347 + $b = $x;
348 + } elseif ( $h >= 180 && $h < 240 ) {
349 + $g = $x;
350 + $b = $c;
351 + } elseif ( $h >= 240 && $h < 300 ) {
352 + $r = $x;
353 + $b = $c;
354 + } elseif ( $h >= 300 && $h < 360 ) {
355 + $r = $c;
356 + $b = $x;
357 + }//end if
358 +
359 + // Convert RGB to 8-bit values
360 + $r = round( ( $r + $m ) * 255 );
361 + $g = round( ( $g + $m ) * 255 );
362 + $b = round( ( $b + $m ) * 255 );
363 +
364 + // Convert RGB to hex
365 + return sprintf( '%02x%02x%02x', $r, $g, $b );
366 + }
367 +
368 + /**
225 369 * @since 2.3
370 + *
371 + * @param string $hex string The original color in hex format #ffffff.
372 + * @param int $steps integer Should be between -255 and 255. Negative = darker, positive = lighter.
373 + *
374 + * @return string
226 375 */
227 376 public static function adjust_brightness( $hex, $steps ) {
228 377 $steps = max( - 255, min( 255, $steps ) );
229 378
230 - if ( 0 === strpos( $hex, 'rgba(' ) ) {
379 + if ( str_starts_with( $hex, 'rgba(' ) ) {
231 380 $rgba = str_replace( ')', '', str_replace( 'rgba(', '', $hex ) );
232 381 list ( $r, $g, $b, $a ) = array_map( 'trim', explode( ',', $rgba ) );
233 382 $r = max( 0, min( 255, $r + $steps ) );
234 383 $g = max( 0, min( 255, $g + $steps ) );
@@ -244,11 +393,15 @@
244 393 $color_parts = str_split( $hex, 2 );
245 394 $return = '#';
246 395
247 396 foreach ( $color_parts as $color ) {
248 - $color = hexdec( $color ); // Convert to decimal
249 - $color = max( 0, min( 255, $color + $steps ) ); // Adjust color
250 - $return .= str_pad( dechex( $color ), 2, '0', STR_PAD_LEFT ); // Make two char hex code
397 + // Convert to decimal.
398 + $color = hexdec( $color );
399 + // Adjust color.
400 + $color = max( 0, min( 255, $color + $steps ) );
401 +
402 + // Make two char hex code.
403 + $return .= str_pad( dechex( $color ), 2, '0', STR_PAD_LEFT );
251 404 }
252 405
253 406 return $return;
254 407 }
@@ -256,23 +409,34 @@
256 409 /**
257 410 * @since 6.0
258 411 *
259 412 * @param string $color
413 + *
260 414 * @return int
261 415 */
262 416 public static function get_color_brightness( $color ) {
263 - if ( 0 === strpos( $color, 'rgb' ) ) {
417 + if ( str_starts_with( $color, 'rgb' ) ) {
264 418 $color = self::rgb_to_hex( $color );
265 419 }
266 420
421 + if ( str_starts_with( $color, 'hsl' ) ) {
422 + $hsl_to_hex = self::hsl_to_hex( $color );
423 +
424 + if ( is_null( $hsl_to_hex ) ) {
425 + // Fallback if we cannot convert the HSL value.
426 + return 0;
427 + }
428 +
429 + $color = $hsl_to_hex;
430 + }
431 +
267 432 self::fill_hex( $color );
268 433
269 - $c_r = hexdec( substr( $color, 0, 2 ) );
270 - $c_g = hexdec( substr( $color, 2, 2 ) );
271 - $c_b = hexdec( substr( $color, 4, 2 ) );
272 - $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
434 + $c_r = hexdec( substr( $color, 0, 2 ) );
435 + $c_g = hexdec( substr( $color, 2, 2 ) );
436 + $c_b = hexdec( substr( $color, 4, 2 ) );
273 437
274 - return $brightness;
438 + return ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
275 439 }
276 440
277 441 /**
278 442 * Change a 3 character hex color to a 6 character one.
@@ -278,9 +442,11 @@
278 442 * Change a 3 character hex color to a 6 character one.
279 443 *
280 444 * @since 6.0
281 445 *
282 - * @return array
446 + * @param string $color Color value, passed by reference.
447 + *
448 + * @return void
283 449 */
284 450 private static function fill_hex( &$color ) {
285 451 if ( 3 === strlen( $color ) ) {
286 452 $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
@@ -288,8 +454,12 @@
288 454 }
289 455
290 456 /**
291 457 * @since 4.05.02
458 + *
459 + * @param array $vars CSS variable keys.
460 + *
461 + * @return array
292 462 */
293 463 public static function get_css_vars( $vars = array() ) {
294 464 $vars = apply_filters( 'frm_css_vars', $vars );
295 465 return array_unique( $vars );
@@ -296,51 +466,233 @@
296 466 }
297 467
298 468 /**
299 469 * @since 4.05.02
470 + *
471 + * @param array $settings Style settings.
472 + * @param array $defaults Default style settings.
473 + * @param array $vars CSS variable keys to output.
474 + *
475 + * @return void
300 476 */
301 477 public static function output_vars( $settings, $defaults = array(), $vars = array() ) {
302 - if ( empty( $vars ) ) {
478 + if ( ! $vars ) {
303 479 $vars = self::get_css_vars( array_keys( $settings ) );
304 480 }
305 - $remove = array( 'remove_box_shadow', 'remove_box_shadow_active', 'theme_css', 'theme_name', 'theme_selector', 'important_style', 'submit_style', 'collapse_icon', 'center_form', 'custom_css', 'style_class', 'submit_bg_img', 'change_margin', 'repeat_icon' );
306 - $vars = array_diff( $vars, $remove );
307 481
482 + $vars = array_diff( $vars, self::get_style_keys_to_remove_from_output_vars() );
483 +
308 484 foreach ( $vars as $var ) {
309 - if ( ! isset( $settings[ $var ] ) ) {
485 + if ( ! isset( $settings[ $var ] ) || ! self::css_key_is_valid( $var ) ) {
310 486 continue;
311 487 }
488 +
312 489 if ( ! isset( $defaults[ $var ] ) ) {
313 490 $defaults[ $var ] = '';
314 491 }
315 - $show = empty( $defaults ) || ( $settings[ $var ] !== '' && $settings[ $var ] !== $defaults[ $var ] );
316 - if ( $show ) {
317 - echo '--' . esc_html( str_replace( '_', '-', $var ) ) . ':' . ( $var === 'font' ? FrmAppHelper::kses( $settings[ $var ] ) : esc_html( $settings[ $var ] ) ) . ';'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
492 +
493 + $prepared_value = '';
494 +
495 + if ( self::should_add_css_var( $settings, $defaults, $var, $prepared_value ) ) {
496 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
497 + echo '--' . esc_html( self::clean_var_name( str_replace( '_', '-', $var ) ) ) . ':' . $prepared_value . ';';
318 498 }
319 499 }
320 500 }
321 501
322 502 /**
503 + * None of these style settings are used as CSS variables, so we want to exclude them to keep the CSS output clean.
504 + *
505 + * @since 6.26.1
506 + *
507 + * @return array<string>
508 + */
509 + private static function get_style_keys_to_remove_from_output_vars() {
510 + return array(
511 + 'remove_box_shadow',
512 + 'remove_box_shadow_active',
513 + 'theme_css',
514 + 'theme_name',
515 + 'theme_selector',
516 + 'important_style',
517 + 'submit_style',
518 + 'collapse_icon',
519 + 'center_form',
520 + 'custom_css',
521 + 'style_class',
522 + 'submit_bg_img',
523 + 'change_margin',
524 + 'repeat_icon',
525 + 'use_base_font_size',
526 + 'field_shape_type',
527 + 'bg_image_id',
528 + 'single_style_custom_css',
529 + 'enable_style_custom_css',
530 + );
531 + }
532 +
533 + /**
534 + * Check if a CSS variable setting is not blank, doesn't match the default, and doesn't include invalid substrings.
535 + *
536 + * @since 6.24
537 + *
538 + * @param array $settings Array of setting values.
539 + * @param array $defaults Array of default values.
540 + * @param string $var The setting key name.
541 + * @param string $prepared_value The value from calling css_var_prepare_value. This is set by reference so it can be used after this function is called.
542 + *
543 + * @return bool True if the CSS value should be printed.
544 + */
545 + private static function should_add_css_var( $settings, $defaults, $var, &$prepared_value ) {
546 + $prepared_value = self::css_var_prepare_value( $settings, $var );
547 +
548 + if ( $prepared_value === '' ) {
549 + return false;
550 + }
551 +
552 + if ( $defaults && $defaults[ $var ] === $prepared_value ) {
553 + return false;
554 + }
555 +
556 + return self::css_value_is_valid( $prepared_value );
557 + }
558 +
559 + /**
560 + * Prevent invalid CSS keys from getting added to the generated CSS.
561 + *
562 + * @since 6.20
563 + *
564 + * @param string $key
565 + *
566 + * @return bool
567 + */
568 + private static function css_key_is_valid( $key ) {
569 + // Any key that is abnormally large is not valid.
570 + // Any key that contains a '{' is not valid.
571 + return strlen( $key ) < 100 && ! str_contains( $key, '{' );
572 + }
573 +
574 + /**
575 + * Confirm a CSS value is valid.
576 + * If it appears to contain JavaScript, it will not be added.
577 + *
578 + * @since 6.20
579 + *
580 + * @param string $var
581 + *
582 + * @return bool
583 + */
584 + private static function css_value_is_valid( $var ) {
585 + if ( is_numeric( $var ) ) {
586 + return true;
587 + }
588 +
589 + // None of these substrings should be present in any CSS value.
590 + $invalid_substrings = array(
591 + 'function(',
592 + ';userAgent',
593 + ';stopPropagation',
594 + '{const',
595 + 'window[',
596 + 'navigator[',
597 + 'Array;',
598 + );
599 +
600 + foreach ( $invalid_substrings as $substring ) {
601 + if ( str_contains( $var, $substring ) ) {
602 + return false;
603 + }
604 + }
605 +
606 + return true;
607 + }
608 +
609 + /**
610 + * Remove anything that isn't used as a CSS variable name.
611 + *
612 + * @param string $var_name
613 + *
614 + * @return string
615 + */
616 + private static function clean_var_name( $var_name ) {
617 + return preg_replace( '/[^a-zA-Z0-9_-]/', '', $var_name );
618 + }
619 +
620 + /**
621 + * Prepare the value for a CSS variable.
622 + *
623 + * @since 6.14
624 + *
625 + * @param array $settings An array of css style.
626 + * @param string $key
627 + *
628 + * @return string
629 + */
630 + private static function css_var_prepare_value( $settings, $key ) {
631 + $value = $settings[ $key ];
632 +
633 + if ( ! is_string( $value ) && ! is_numeric( $value ) ) {
634 + return '';
635 + }
636 +
637 + switch ( $key ) {
638 + case 'font':
639 + return safecss_filter_attr( $value );
640 +
641 + case 'border_width_error':
642 + case 'field_border_width':
643 + if ( ! empty( $settings['field_shape_type'] ) && 'underline' === $settings['field_shape_type'] ) {
644 + return safecss_filter_attr( '0px 0px ' . $value . ' 0px' );
645 + }
646 + break;
647 +
648 + case 'box_shadow':
649 + if ( ! empty( $settings['field_shape_type'] ) && 'underline' === $settings['field_shape_type'] ) {
650 + return safecss_filter_attr( 'none' );
651 + }
652 + break;
653 +
654 + case 'border_radius':
655 + if ( ! empty( $settings['field_shape_type'] ) ) {
656 + switch ( $settings['field_shape_type'] ) {
657 + case 'underline':
658 + case 'regular':
659 + return safecss_filter_attr( '0px' );
660 + case 'circle':
661 + return safecss_filter_attr( '30px' );
662 + }
663 + }
664 + break;
665 + }//end switch
666 +
667 + return esc_html( $value );
668 + }
669 +
670 + /**
323 671 * @since 2.3
324 672 *
325 673 * @param WP_Post $style
674 + *
326 675 * @return array
327 676 */
328 677 public static function get_settings_for_output( $style ) {
329 678 if ( self::previewing_style() ) {
330 679 $frm_style = new FrmStyle();
680 +
331 681 if ( isset( $_POST['frm_style_setting'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
332 682
333 683 // Sanitizing is done later.
334 - $posted = wp_unslash( $_POST['frm_style_setting'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
335 - if ( ! is_array( $posted ) ) {
684 + //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
685 + $posted = wp_unslash( $_POST['frm_style_setting'] );
686 +
687 + if ( is_array( $posted ) ) {
688 + $settings = $frm_style->sanitize_post_content( $posted['post_content'] );
689 + $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_title' );
690 + } else {
336 691 $posted = json_decode( $posted, true );
337 692 FrmAppHelper::format_form_data( $posted );
338 693 $settings = $frm_style->sanitize_post_content( $posted['frm_style_setting']['post_content'] );
339 694 $style_name = sanitize_title( $posted['style_name'] );
340 - } else {
341 - $settings = $frm_style->sanitize_post_content( $posted['post_content'] );
342 - $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_title' );
343 695 }
344 696 } else {
345 697 $settings = $frm_style->sanitize_post_content( wp_unslash( $_GET ) );
346 698 $style_name = FrmAppHelper::get_param( 'style_name', '', 'get', 'sanitize_title' );
@@ -345,11 +697,14 @@
345 697 $settings = $frm_style->sanitize_post_content( wp_unslash( $_GET ) );
346 698 $style_name = FrmAppHelper::get_param( 'style_name', '', 'get', 'sanitize_title' );
347 699 }
348 700
701 + $settings = self::update_base_font_size( $settings, $frm_style->get_defaults() );
702 +
349 703 FrmAppHelper::sanitize_value( 'sanitize_text_field', $settings );
350 704
351 705 $settings['style_class'] = '';
706 +
352 707 if ( ! empty( $style_name ) ) {
353 708 $settings['style_class'] = $style_name . '.';
354 709 }
355 710 } else {
@@ -354,9 +709,9 @@
354 709 }
355 710 } else {
356 711 $settings = $style->post_content;
357 712 $settings['style_class'] = 'frm_style_' . $style->post_name . '.';
358 - }
713 + }//end if
359 714
360 715 $settings['style_class'] .= 'with_frm_style';
361 716 $settings['font'] = stripslashes( $settings['font'] );
362 717 $settings['change_margin'] = self::description_margin_for_screensize( $settings['width'] );
@@ -361,8 +716,9 @@
361 716 $settings['font'] = stripslashes( $settings['font'] );
362 717 $settings['change_margin'] = self::description_margin_for_screensize( $settings['width'] );
363 718
364 719 $checkbox_opts = array( 'important_style', 'auto_width', 'submit_style', 'collapse_icon', 'center_form' );
720 +
365 721 foreach ( $checkbox_opts as $opt ) {
366 722 if ( ! isset( $settings[ $opt ] ) ) {
367 723 $settings[ $opt ] = 0;
368 724 }
@@ -372,9 +728,9 @@
372 728
373 729 $settings['field_height'] = $settings['field_height'] === '' ? 'auto' : $settings['field_height'];
374 730 $settings['field_width'] = $settings['field_width'] === '' ? 'auto' : $settings['field_width'];
375 731 $settings['auto_width'] = $settings['auto_width'] ? 'auto' : $settings['field_width'];
376 - $settings['box_shadow'] = ! empty( $settings['remove_box_shadow'] ) ? 'none' : '0 1px 1px rgba(0, 0, 0, 0.075) inset';
732 + $settings['box_shadow'] = ! empty( $settings['remove_box_shadow'] ) ? 'none' : '0 1px 2px 0 rgba(18, 18, 23, 0.05)';
377 733
378 734 if ( ! isset( $settings['repeat_icon'] ) ) {
379 735 $settings['repeat_icon'] = 1;
380 736 }
@@ -382,16 +738,85 @@
382 738 return $settings;
383 739 }
384 740
385 741 /**
742 + * Update the "Base Font Size" value from "Quick Settings across multiple settings values".
743 + *
744 + * @since 6.14
745 + *
746 + * @param array $settings An array of css style.
747 + * @param array $defaults Default style settings.
748 + *
749 + * @return array
750 + */
751 + public static function update_base_font_size( $settings, $defaults ) {
752 + if ( empty( $settings['base_font_size'] ) || empty( $settings['use_base_font_size'] ) || 'false' === $settings['use_base_font_size'] ) {
753 + return $settings;
754 + }
755 +
756 + $base_font_size = (int) $settings['base_font_size'];
757 + $font_size = $defaults['font_size'];
758 + $font_sizes_to_update = array(
759 + 'font_size',
760 + 'field_font_size',
761 + 'check_font_size',
762 + 'title_size',
763 + 'form_desc_size',
764 + 'description_font_size',
765 + 'section_font_size',
766 + 'submit_font_size',
767 + 'success_font_size',
768 + 'error_font_size',
769 + 'progress_size',
770 + );
771 +
772 + array_map(
773 + function ( $key ) use ( $defaults, $font_size, $base_font_size, &$settings ) {
774 + if ( isset( $settings[ $key ] ) ) {
775 + $settings[ $key ] = round( self::get_base_font_size_scale( $key, $font_size, $defaults ) * $base_font_size ) . 'px';
776 + }
777 + },
778 + $font_sizes_to_update
779 + );
780 +
781 + return $settings;
782 + }
783 +
784 + /**
785 + * Get style font size scale value.
786 + *
787 + * @since 6.14
788 + *
789 + * @param string $key Setting key.
790 + * @param int|string $value Base font size value.
791 + * @param array $defaults Default style settings.
792 + *
793 + * @return float
794 + */
795 + private static function get_base_font_size_scale( $key, $value, $defaults ) {
796 + if ( empty( $defaults[ $key ] ) || ! is_numeric( (int) $defaults[ $key ] ) || ! is_numeric( (int) $value ) || 0 === (int) $value ) {
797 + return 1;
798 + }
799 +
800 + return round( (int) $defaults[ $key ] / (int) $value, 2 );
801 + }
802 +
803 + /**
386 804 * @since 2.3
805 + *
806 + * @param array $settings Style settings, passed by reference.
807 + * @param bool $allow_transparent Whether transparent colors are allowed.
808 + *
809 + * @return void
387 810 */
388 811 public static function prepare_color_output( &$settings, $allow_transparent = true ) {
389 812 $colors = self::allow_color_override();
813 +
390 814 foreach ( $colors as $css => $opts ) {
391 815 if ( $css === 'transparent' && ! $allow_transparent ) {
392 816 $css = '';
393 817 }
818 +
394 819 foreach ( $opts as $opt ) {
395 820 self::get_color_output( $css, $settings[ $opt ] );
396 821 }
397 822 }
@@ -431,30 +856,66 @@
431 856 }
432 857
433 858 /**
434 859 * @since 2.3
860 + *
861 + * @param string $default Default color value.
862 + * @param string $color Color value, passed by reference.
863 + *
864 + * @return void
435 865 */
436 866 private static function get_color_output( $default, &$color ) {
437 867 $color = trim( $color );
438 - if ( empty( $color ) ) {
868 +
869 + if ( ! $color ) {
439 870 $color = $default;
440 - } elseif ( false !== strpos( $color, 'rgb(' ) ) {
441 - $color = str_replace( 'rgb(', 'rgba(', $color );
442 - $color = str_replace( ')', ',1)', $color );
443 - } elseif ( strpos( $color, '#' ) === false && false === strpos( $color, 'rgba(' ) ) {
871 + } elseif ( ! str_contains( $color, '#' ) && self::is_hex( $color ) ) {
444 872 $color = '#' . $color;
445 873 }
446 874 }
447 875
448 876 /**
877 + * If a color looks like a hex code without the #, prepend the #.
878 + * A color looks like a hex code if it does not contain the substrings "rgb", "rgba", "hsl", "hsla", or "hwb".
879 + *
880 + * @since 6.8
881 + *
882 + * @param string $color
883 + *
884 + * @return bool
885 + */
886 + private static function is_hex( $color ) {
887 + $non_hex_substrings = array(
888 + 'rgb(',
889 + 'rgba(',
890 + 'hsl(',
891 + 'hsla(',
892 + 'hwb(',
893 + );
894 +
895 + foreach ( $non_hex_substrings as $substring ) {
896 + if ( str_contains( $color, $substring ) ) {
897 + return false;
898 + }
899 + }
900 +
901 + return true;
902 + }
903 +
904 + /**
449 905 * If left/right label is over a certain size,
450 906 * adjust the field description margin at a different screen size
451 907 *
452 908 * @since 2.3
909 + *
910 + * @param string $width Label width value.
911 + *
912 + * @return false|string
453 913 */
454 914 private static function description_margin_for_screensize( $width ) {
455 915 $temp_label_width = str_replace( 'px', '', $width );
456 916 $change_margin = false;
917 +
457 918 if ( $temp_label_width >= 230 ) {
458 919 $change_margin = '800px';
459 920 } elseif ( $width >= 215 ) {
460 921 $change_margin = '700px';
@@ -465,48 +926,33 @@
465 926 return $change_margin;
466 927 }
467 928
468 929 /**
469 - * @since 2.3
930 + * Get the raw alignment value stored in the active style for a radio or checkbox field.
470 931 *
471 - * @return bool
932 + * @since 6.32
933 + *
934 + * @param array|int $field The 'field' array.
935 + *
936 + * @return string
472 937 */
473 - public static function previewing_style() {
474 - $ajax_change = isset( $_POST['action'] ) && $_POST['action'] === 'frm_change_styling' && isset( $_POST['frm_style_setting'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
938 + public static function get_align_from_active_style( $field ) {
939 + $field_type = FrmField::is_checkbox( $field ) ? 'checkbox' : 'radio';
940 + $key = FrmStylesController::get_align_key_for_style_settings( $field_type );
475 941
476 - return $ajax_change || isset( $_GET['flat'] );
942 + return FrmStylesController::get_active_style( $field )->post_content[ $key ] ?? '';
477 943 }
478 944
479 945 /**
480 - * @since 5.5.1
481 - * @return void
946 + * @since 2.3
947 + *
948 + * @return bool
482 949 */
483 - public static function maybe_include_font_icon_css() {
484 - $signature_add_on_is_active = class_exists( 'FrmSigAppHelper', false );
950 + public static function previewing_style() {
951 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
952 + $ajax_change = isset( $_POST['action'] ) && $_POST['action'] === 'frm_change_styling' && isset( $_POST['frm_style_setting'] );
485 953
486 - if ( ! FrmAppHelper::pro_is_installed() && ! $signature_add_on_is_active ) {
487 - // If Pro and Signatures are both not active, there is no need to include the font icon CSS in lite.
488 - return;
489 - }
490 -
491 - $pro_version_will_handle_loading = false;
492 -
493 - if ( class_exists( 'FrmProDb', false ) ) {
494 - $pro_version_that_includes_font_icons_css = '5.5.1';
495 -
496 - // Include font icons in Lite for backward compatibility with older version of Pro.
497 - $pro_version_will_handle_loading = version_compare( FrmProDb::$plug_version, $pro_version_that_includes_font_icons_css, '>=' );
498 - }
499 -
500 - $load_it_here = false;
501 - if ( ! $pro_version_will_handle_loading ) {
502 - // If Pro is not handling it, we still need to include it for the Signature add on.
503 - $load_it_here = $signature_add_on_is_active;
504 - }
505 -
506 - if ( $load_it_here ) {
507 - readfile( FrmAppHelper::plugin_path() . '/css/font_icons.css' );
508 - }
954 + return $ajax_change || isset( $_GET['flat'] );
509 955 }
510 956
511 957 /**
512 958 * Get the URL for the Styler page list view (where you can assign styles to a form and view style templates) for a target form.
@@ -512,9 +958,10 @@
512 958 * Get the URL for the Styler page list view (where you can assign styles to a form and view style templates) for a target form.
513 959 *
514 960 * @since 6.0
515 961 *
516 - * @param string|int $form_id
962 + * @param int|string $form_id
963 + *
517 964 * @return string
518 965 */
519 966 public static function get_list_url( $form_id ) {
520 967 return admin_url( 'admin.php?page=formidable-styles&form=' . absint( $form_id ) );
@@ -520,19 +967,45 @@
520 967 return admin_url( 'admin.php?page=formidable-styles&form=' . absint( $form_id ) );
521 968 }
522 969
523 970 /**
971 + * Get the back button args from Style settings.
972 + *
973 + * @since 6.14
974 + *
975 + * @param stdClass|WP_Post $style
976 + * @param int $form_id
977 + *
978 + * @return array
979 + */
980 + public static function get_style_options_back_button_args( $style, $form_id ) {
981 + if ( self::is_advanced_settings() ) {
982 + return array(
983 + 'title' => __( 'Quick Settings', 'formidable' ),
984 + 'id' => 'frm_style_back_to_quick_settings',
985 + );
986 + }
987 + return array(
988 + 'href' => self::get_list_url( $form_id ),
989 + 'title' => $style->post_title,
990 + );
991 + }
992 +
993 + /**
524 994 * Get a link to edit a target style post object in the visual styler.
525 995 *
526 - * @param WP_Post|stdClass $style
527 - * @param string|int $form_id Used for the back button and preview form target.
996 + * @param stdClass|WP_Post $style
997 + * @param int|string $form_id Used for the back button and preview form target.
998 + * @param string $section The url param section.
999 + *
528 1000 * @return string
529 1001 */
530 - public static function get_edit_url( $style, $form_id = 0 ) {
1002 + public static function get_edit_url( $style, $form_id = 0, $section = '' ) {
531 1003 $query_args = array(
532 1004 'page' => 'formidable-styles',
533 1005 'frm_action' => 'edit',
534 1006 'id' => $style->ID,
1007 + 'section' => $section,
535 1008 );
536 1009
537 1010 if ( $form_id ) {
538 1011 // We include &form_id for the back button to know where to point to.
@@ -547,15 +1020,17 @@
547 1020 * All unassigned forms are included in the count for the default style.
548 1021 *
549 1022 * @since 6.0
550 1023 *
551 - * @param string|int $style_id
1024 + * @param int|string $style_id
552 1025 * @param bool $is_default
1026 + *
553 1027 * @return int
554 1028 */
555 1029 public static function get_form_count_for_style( $style_id, $is_default ) {
556 - $serialized = serialize( array( 'custom_style' => (string) $style_id ) );
557 - $substring = substr( $serialized, 5, -1 ); // Chop off the "a:1:{" from the front and the "}" from the back.
1030 + $serialized = serialize( array( 'custom_style' => (string) $style_id ) );
1031 + // Chop off the "a:1:{" from the front and the "}" from the back.
1032 + $substring = substr( $serialized, 5, -1 );
558 1033 $number_of_forms = FrmDb::get_count(
559 1034 'frm_forms',
560 1035 array(
561 1036 'status' => 'published',
@@ -568,11 +1043,10 @@
568 1043 return $number_of_forms;
569 1044 }
570 1045
571 1046 $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' );
572 - $number_of_forms += self::get_default_style_count( $style_id, $conversational_style_id );
573 1047
574 - return $number_of_forms;
1048 + return $number_of_forms + self::get_default_style_count( $style_id, $conversational_style_id );
575 1049 }
576 1050
577 1051 /**
578 1052 * Get the number of forms that use the default style.
@@ -578,21 +1052,22 @@
578 1052 * Get the number of forms that use the default style.
579 1053 *
580 1054 * @since 6.0
581 1055 *
582 - * @param string|int $style_id
1056 + * @param int|string $style_id
583 1057 * @param mixed $conversational_style_id
1058 + *
584 1059 * @return int
585 1060 */
586 1061 private static function get_default_style_count( $style_id, $conversational_style_id ) {
587 1062 $substrings = array_map(
588 - function( $value ) {
1063 + function ( $value ) {
589 1064 $substring = serialize( array( 'custom_style' => $value ) );
590 1065 return substr( $substring, 5, -1 );
591 1066 },
592 1067 array( '1', 1 )
593 1068 );
594 - $where = array(
1069 + $where = array(
595 1070 'status' => 'published',
596 1071 0 => array(
597 1072 'options NOT LIKE' => 'custom_style',
598 1073 'or' => 1,
@@ -602,9 +1077,9 @@
602 1077
603 1078 if ( $conversational_style_id ) {
604 1079 // When a conversational style is set, check for it in the query by wrapping the where and adding a conversational option check.
605 1080 $is_conversational_style = (int) $style_id === (int) $conversational_style_id;
606 - $where[0] = array(
1081 + $where[0] = array(
607 1082 // The chat option doesn't exist if it isn't on.
608 1083 ( $is_conversational_style ? 'options LIKE' : 'options NOT LIKE' ) => ';s:4:"chat";',
609 1084 $where[0],
610 1085 );
@@ -613,89 +1088,178 @@
613 1088 return FrmDb::get_count( 'frm_forms', $where );
614 1089 }
615 1090
616 1091 /**
617 - * @deprecated 3.01
618 - * @codeCoverageIgnore
1092 + * Check if the current page is the advanced settings page.
1093 + *
1094 + * @since 6.14
1095 + *
1096 + * @return bool True if is advanced settings, false otherwise.
619 1097 */
620 - public static function get_sigle_label_postitions() {
621 - return FrmDeprecated::get_sigle_label_postitions();
1098 + public static function is_advanced_settings() {
1099 + return FrmAppHelper::get_param( 'section' ) === 'advanced-settings' && FrmAppHelper::get_param( 'page' ) === 'formidable-styles';
622 1100 }
623 1101
624 1102 /**
625 - * @deprecated 3.02.03
626 - * @codeCoverageIgnore
1103 + * Get wrapper classname for style editor sections.
1104 + *
1105 + * @since 6.16
1106 + *
1107 + * @param string $section_type
1108 + *
1109 + * @return string The style editor wrapper classname.
627 1110 */
628 - public static function jquery_themes() {
629 - return FrmDeprecated::jquery_themes();
1111 + public static function style_editor_get_wrapper_classname( $section_type ) {
1112 + $is_quick_settings = 'quick-settings' === $section_type;
1113 + $classname = 'frm-style-editor-form';
1114 + $classname .= ( ! self::is_advanced_settings() xor $is_quick_settings ) ? ' frm_hidden' : '';
1115 +
1116 + return $classname . ( FrmAppHelper::pro_is_installed() ? ' frm-pro' : '' );
630 1117 }
631 1118
632 1119 /**
633 - * @deprecated 3.02.03
634 - * @codeCoverageIgnore
1120 + * Retrieve the background image URL of the submit button.
1121 + * It may be either a full URL string (used in versions prior to 6.14) or a numeric attachment ID (introduced in version 6.14).
1122 + *
1123 + * @since 6.14
1124 + *
1125 + * @param array $settings
1126 + *
1127 + * @return false|string Return image url or false.
635 1128 */
636 - public static function jquery_css_url( $theme_css ) {
637 - return FrmDeprecated::jquery_css_url( $theme_css );
1129 + public static function get_submit_image_bg_url( $settings ) {
1130 + $background_image = $settings['submit_bg_img'];
1131 +
1132 + if ( ! $background_image ) {
1133 + return false;
1134 + }
1135 +
1136 + // Handle the case where the submit_bg_img is a full URL string. If the
1137 + // Settings were saved with the older styler version prior to 6.14, the
1138 + // submit_bg_img will be a full URL string.
1139 + if ( ! is_numeric( $background_image ) ) {
1140 + return $background_image;
1141 + }
1142 +
1143 + return wp_get_attachment_url( (int) $background_image );
638 1144 }
639 1145
640 1146 /**
641 - * @deprecated 3.02.03
642 - * @codeCoverageIgnore
1147 + * Determines if the chosen JavaScript library should be used.
1148 + *
1149 + * @since 6.13
1150 + *
1151 + * @return bool
643 1152 */
644 - public static function enqueue_jquery_css() {
645 - FrmDeprecated::enqueue_jquery_css();
1153 + public static function use_chosen_js() {
1154 + if ( ! FrmAppHelper::pro_is_installed() ) {
1155 + return false;
1156 + }
1157 +
1158 + return is_callable( 'FrmProAppHelper::use_chosen_js' ) ? FrmProAppHelper::use_chosen_js() : true;
646 1159 }
647 1160
648 1161 /**
649 - * @deprecated 3.02.03
650 - * @codeCoverageIgnore
1162 + * Returns the bottom part from a margin/padding value.
1163 + *
1164 + * @since 6.17
1165 + *
1166 + * @param string $value The margin/padding value.
1167 + *
1168 + * @return string
651 1169 */
652 - public static function get_form_for_page() {
653 - return FrmDeprecated::get_form_for_page();
1170 + public static function get_bottom_value( $value ) {
1171 + if ( ! $value ) {
1172 + return $value;
1173 + }
1174 +
1175 + $parts = explode( ' ', $value );
1176 +
1177 + return count( $parts ) < 3 ? $parts[0] : $parts[2];
654 1178 }
655 1179
656 1180 /**
657 - * @since 4.0
658 - * @deprecated 6.0 The style menu is no longer used in the styler.
1181 + * Scope CSS to .frm_forms on admin pages to prevent style conflicts.
1182 + * On front-end pages, the CSS is returned unchanged.
659 1183 *
660 - * @param string $active
1184 + * @since 6.30
1185 + *
1186 + * @param string $css The CSS to scope.
1187 + *
661 1188 * @return string
662 1189 */
663 - public static function get_style_menu( $active = '' ) {
664 - _deprecated_function( __METHOD__, '6.0' );
665 - return '';
1190 + public static function maybe_scope_css_for_admin( $css ) {
1191 + if ( ! self::should_scope_custom_css() ) {
1192 + return $css;
1193 + }
1194 +
1195 + /**
1196 + * Filter the CSS selector used for @scope when scoping custom CSS on admin pages.
1197 + *
1198 + * @since 6.30
1199 + *
1200 + * @param string $selector The CSS selector to scope to. Default '.frm_forms'.
1201 + */
1202 + $selector = apply_filters( 'frm_scope_custom_css_selector', '.frm_forms' );
1203 +
1204 + return '@scope (' . $selector . ') {' . $css . '}';
666 1205 }
667 1206
668 1207 /**
669 - * @deprecated 6.0 The style menu is no longer used in the styler.
1208 + * Scope only the custom CSS portion of the full cached stylesheet for admin pages.
1209 + * Extracts the global custom CSS from the cached CSS, outputs the theme CSS unchanged,
1210 + * and returns only the custom CSS portion scoped.
670 1211 *
671 - * @param string $active
672 - * @return void
1212 + * @since 6.30
1213 + *
1214 + * @param string $css The full cached CSS containing both theme and custom CSS.
1215 + *
1216 + * @return string The theme CSS with only the custom CSS portion scoped.
673 1217 */
674 - public static function style_menu( $active = '' ) {
675 - _deprecated_function( __METHOD__, '6.0' );
1218 + public static function maybe_scope_custom_css_in_cached_output( $css ) {
1219 + if ( ! self::should_scope_custom_css() ) {
1220 + return $css;
1221 + }
1222 +
1223 + $custom_css = strip_tags( FrmStylesController::get_custom_css() );
1224 +
1225 + if ( ! $custom_css ) {
1226 + return $css;
1227 + }
1228 +
1229 + // The cached CSS is minified. Minify the custom CSS the same way to find it.
1230 + $minified_custom_css = self::minify_css( $custom_css );
1231 + $custom_css_pos = strrpos( $css, $minified_custom_css );
1232 +
1233 + if ( false !== $custom_css_pos ) {
1234 + $css = substr( $css, 0, $custom_css_pos );
1235 + }
1236 +
1237 + return $css . self::maybe_scope_css_for_admin( $custom_css );
676 1238 }
677 1239
678 1240 /**
679 - * Either get the heading or the style switcher.
1241 + * Minify CSS by stripping comments and whitespace.
1242 + * Matches the minification used when saving the cached CSS file.
680 1243 *
681 - * @since 4.0
682 - * @deprecated 6.0 The style switcher was replaced with a form switcher and is no longer used.
1244 + * @since 6.30
683 1245 *
684 - * @param array $atts
685 - * @return void
1246 + * @param string $css The CSS to minify.
1247 + *
1248 + * @return string
686 1249 */
687 - public static function styler_switcher( $atts ) {
688 - _deprecated_function( __METHOD__, '6.0' );
1250 + private static function minify_css( $css ) {
1251 + return preg_replace( '/\/\*(.|\s)*?\*\//', '', str_replace( array( "\r\n", "\r", "\n", "\t", ' ' ), '', $css ) );
689 1252 }
690 1253
691 1254 /**
692 - * @since 4.0
693 - * @deprecated 6.0 The styler now uses the Embed/Preview/Update header. It uses the same save button as other pages with Form tabs.
1255 + * Check if custom CSS should be scoped for admin context.
694 1256 *
695 - * @param array $atts
696 - * @return void
1257 + * @since 6.30
1258 + *
1259 + * @return bool
697 1260 */
698 - public static function styler_save_button( $atts ) {
699 - _deprecated_function( __METHOD__, '6.0' );
1261 + private static function should_scope_custom_css() {
1262 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only, used to scope CSS output for admin context.
1263 + return isset( $_GET['frm_scope_custom_css'] );
700 1264 }
701 1265 }