| @@ -25,11 +25,13 @@ | ||
| 25 | 25 | * |
| 26 | 26 | * @return void |
| 27 | 27 | */ |
| 28 | 28 | public static function save_button() { |
| 29 | + // phpcs:disable Generic.WhiteSpace.ScopeIndent | |
| 29 | 30 | ?> |
| 30 | 31 | <input type="submit" name="submit" class="button button-primary frm-button-primary" value="<?php esc_attr_e( 'Update', 'formidable' ); ?>" /> |
| 31 | 32 | <?php |
| 33 | + // phpcs:enable Generic.WhiteSpace.ScopeIndent | |
| 32 | 34 | } |
| 33 | 35 | |
| 34 | 36 | /** |
| 35 | 37 | * @since 2.05 |
| @@ -176,11 +178,9 @@ | ||
| 176 | 178 | if ( $key ) { |
| 177 | 179 | $class .= $key; |
| 178 | 180 | } |
| 179 | 181 | |
| 180 | - $class .= '_icon'; | |
| 181 | - | |
| 182 | - return $class; | |
| 182 | + return $class . '_icon'; | |
| 183 | 183 | } |
| 184 | 184 | |
| 185 | 185 | /** |
| 186 | 186 | * @param WP_Post $style |
| @@ -194,8 +194,9 @@ | ||
| 194 | 194 | $icons = self::$function_name(); |
| 195 | 195 | unset( $function_name ); |
| 196 | 196 | |
| 197 | 197 | $name = 'arrow' === $type ? 'collapse_icon' : 'repeat_icon'; |
| 198 | + // phpcs:disable Generic.WhiteSpace.ScopeIndent | |
| 198 | 199 | ?> |
| 199 | 200 | <div class="btn-group" id="frm_<?php echo esc_attr( $name ); ?>_select"> |
| 200 | 201 | <button class="multiselect dropdown-toggle btn btn-default" data-toggle="dropdown" type="button"> |
| 201 | 202 | <?php FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $style->post_content[ $name ], '+', $type ) ); ?> |
| @@ -203,12 +204,12 @@ | ||
| 203 | 204 | <b class="caret"></b> |
| 204 | 205 | </button> |
| 205 | 206 | <ul class="multiselect-container frm-dropdown-menu"> |
| 206 | 207 | <?php foreach ( $icons as $key => $icon ) { ?> |
| 207 | - <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 ?>> | |
| 208 | 209 | <a href="javascript:void(0);"> |
| 209 | 210 | <label> |
| 210 | - <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 ?> | |
| 211 | 212 | <span> |
| 212 | 213 | <?php |
| 213 | 214 | FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $key, '+', $type ) ); |
| 214 | 215 | FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $key, '-', $type ) ); |
| @@ -220,8 +221,9 @@ | ||
| 220 | 221 | <?php } ?> |
| 221 | 222 | </ul> |
| 222 | 223 | </div> |
| 223 | 224 | <?php |
| 225 | + // phpcs:enable Generic.WhiteSpace.ScopeIndent | |
| 224 | 226 | } |
| 225 | 227 | |
| 226 | 228 | /** |
| 227 | 229 | * Convert a color setting to a RGB CSV (without the rgb()/rgba() wrapper). |
| @@ -232,13 +234,9 @@ | ||
| 232 | 234 | * |
| 233 | 235 | * @return string RGB value without the rgb() wrapper. |
| 234 | 236 | */ |
| 235 | 237 | public static function hex2rgb( $color ) { |
| 236 | - if ( 0 === strpos( $color, 'rgb' ) ) { | |
| 237 | - $rgb = self::get_rgb_array_from_rgb( $color ); | |
| 238 | - } else { | |
| 239 | - $rgb = self::get_rgb_array_from_hex( $color ); | |
| 240 | - } | |
| 238 | + $rgb = str_starts_with( $color, 'rgb' ) ? self::get_rgb_array_from_rgb( $color ) : self::get_rgb_array_from_hex( $color ); | |
| 241 | 239 | return implode( ',', $rgb ); |
| 242 | 240 | } |
| 243 | 241 | |
| 244 | 242 | /** |
| @@ -257,8 +255,9 @@ | ||
| 257 | 255 | if ( 4 === count( $rgb ) ) { |
| 258 | 256 | // Drop the alpha. The function is expected to only return r,g,b with no alpha. |
| 259 | 257 | array_pop( $rgb ); |
| 260 | 258 | } |
| 259 | + | |
| 261 | 260 | return $rgb; |
| 262 | 261 | } |
| 263 | 262 | |
| 264 | 263 | /** |
| @@ -285,9 +284,8 @@ | ||
| 285 | 284 | * @return string |
| 286 | 285 | */ |
| 287 | 286 | public static function hex2rgba( $hex, $a ) { |
| 288 | 287 | $rgb = self::hex2rgb( $hex ); |
| 289 | - | |
| 290 | 288 | return 'rgba(' . $rgb . ',' . $a . ')'; |
| 291 | 289 | } |
| 292 | 290 | |
| 293 | 291 | /** |
| @@ -297,9 +295,9 @@ | ||
| 297 | 295 | * |
| 298 | 296 | * @return string Hex color value. |
| 299 | 297 | */ |
| 300 | 298 | private static function rgb_to_hex( $rgba ) { |
| 301 | - if ( strpos( $rgba, '#' ) === 0 ) { | |
| 299 | + if ( str_starts_with( $rgba, '#' ) ) { | |
| 302 | 300 | // Color is already hex. |
| 303 | 301 | return $rgba; |
| 304 | 302 | } |
| 305 | 303 | preg_match( '/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i', $rgba, $by_color ); |
| @@ -363,11 +361,9 @@ | ||
| 363 | 361 | $g = round( ( $g + $m ) * 255 ); |
| 364 | 362 | $b = round( ( $b + $m ) * 255 ); |
| 365 | 363 | |
| 366 | 364 | // Convert RGB to hex |
| 367 | - $hex = sprintf( '%02x%02x%02x', $r, $g, $b ); | |
| 368 | - | |
| 369 | - return $hex; | |
| 365 | + return sprintf( '%02x%02x%02x', $r, $g, $b ); | |
| 370 | 366 | } |
| 371 | 367 | |
| 372 | 368 | /** |
| 373 | 369 | * @since 2.3 |
| @@ -379,9 +375,9 @@ | ||
| 379 | 375 | */ |
| 380 | 376 | public static function adjust_brightness( $hex, $steps ) { |
| 381 | 377 | $steps = max( - 255, min( 255, $steps ) ); |
| 382 | 378 | |
| 383 | - if ( 0 === strpos( $hex, 'rgba(' ) ) { | |
| 379 | + if ( str_starts_with( $hex, 'rgba(' ) ) { | |
| 384 | 380 | $rgba = str_replace( ')', '', str_replace( 'rgba(', '', $hex ) ); |
| 385 | 381 | list ( $r, $g, $b, $a ) = array_map( 'trim', explode( ',', $rgba ) ); |
| 386 | 382 | $r = max( 0, min( 255, $r + $steps ) ); |
| 387 | 383 | $g = max( 0, min( 255, $g + $steps ) ); |
| @@ -417,13 +413,13 @@ | ||
| 417 | 413 | * |
| 418 | 414 | * @return int |
| 419 | 415 | */ |
| 420 | 416 | public static function get_color_brightness( $color ) { |
| 421 | - if ( 0 === strpos( $color, 'rgb' ) ) { | |
| 417 | + if ( str_starts_with( $color, 'rgb' ) ) { | |
| 422 | 418 | $color = self::rgb_to_hex( $color ); |
| 423 | 419 | } |
| 424 | 420 | |
| 425 | - if ( 0 === strpos( $color, 'hsl' ) ) { | |
| 421 | + if ( str_starts_with( $color, 'hsl' ) ) { | |
| 426 | 422 | $hsl_to_hex = self::hsl_to_hex( $color ); |
| 427 | 423 | |
| 428 | 424 | if ( is_null( $hsl_to_hex ) ) { |
| 429 | 425 | // Fallback if we cannot convert the HSL value. |
| @@ -434,14 +430,13 @@ | ||
| 434 | 430 | } |
| 435 | 431 | |
| 436 | 432 | self::fill_hex( $color ); |
| 437 | 433 | |
| 438 | - $c_r = hexdec( substr( $color, 0, 2 ) ); | |
| 439 | - $c_g = hexdec( substr( $color, 2, 2 ) ); | |
| 440 | - $c_b = hexdec( substr( $color, 4, 2 ) ); | |
| 441 | - $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 ) ); | |
| 442 | 437 | |
| 443 | - return $brightness; | |
| 438 | + return ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000; | |
| 444 | 439 | } |
| 445 | 440 | |
| 446 | 441 | /** |
| 447 | 442 | * Change a 3 character hex color to a 6 character one. |
| @@ -479,14 +474,13 @@ | ||
| 479 | 474 | * |
| 480 | 475 | * @return void |
| 481 | 476 | */ |
| 482 | 477 | public static function output_vars( $settings, $defaults = array(), $vars = array() ) { |
| 483 | - if ( empty( $vars ) ) { | |
| 478 | + if ( ! $vars ) { | |
| 484 | 479 | $vars = self::get_css_vars( array_keys( $settings ) ); |
| 485 | 480 | } |
| 486 | 481 | |
| 487 | - $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', 'use_base_font_size', 'field_shape_type' ); | |
| 488 | - $vars = array_diff( $vars, $remove ); | |
| 482 | + $vars = array_diff( $vars, self::get_style_keys_to_remove_from_output_vars() ); | |
| 489 | 483 | |
| 490 | 484 | foreach ( $vars as $var ) { |
| 491 | 485 | if ( ! isset( $settings[ $var ] ) || ! self::css_key_is_valid( $var ) ) { |
| 492 | 486 | continue; |
| @@ -498,14 +492,46 @@ | ||
| 498 | 492 | |
| 499 | 493 | $prepared_value = ''; |
| 500 | 494 | |
| 501 | 495 | if ( self::should_add_css_var( $settings, $defaults, $var, $prepared_value ) ) { |
| 502 | - echo '--' . esc_html( self::clean_var_name( str_replace( '_', '-', $var ) ) ) . ':' . $prepared_value . ';'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 496 | + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 497 | + echo '--' . esc_html( self::clean_var_name( str_replace( '_', '-', $var ) ) ) . ':' . $prepared_value . ';'; | |
| 503 | 498 | } |
| 504 | 499 | } |
| 505 | 500 | } |
| 506 | 501 | |
| 507 | 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 | + /** | |
| 508 | 534 | * Check if a CSS variable setting is not blank, doesn't match the default, and doesn't include invalid substrings. |
| 509 | 535 | * |
| 510 | 536 | * @since 6.24 |
| 511 | 537 | * |
| @@ -541,9 +567,9 @@ | ||
| 541 | 567 | */ |
| 542 | 568 | private static function css_key_is_valid( $key ) { |
| 543 | 569 | // Any key that is abnormally large is not valid. |
| 544 | 570 | // Any key that contains a '{' is not valid. |
| 545 | - return strlen( $key ) < 100 && false === strpos( $key, '{' ); | |
| 571 | + return strlen( $key ) < 100 && ! str_contains( $key, '{' ); | |
| 546 | 572 | } |
| 547 | 573 | |
| 548 | 574 | /** |
| 549 | 575 | * Confirm a CSS value is valid. |
| @@ -571,9 +597,9 @@ | ||
| 571 | 597 | 'Array;', |
| 572 | 598 | ); |
| 573 | 599 | |
| 574 | 600 | foreach ( $invalid_substrings as $substring ) { |
| 575 | - if ( strpos( $var, $substring ) !== false ) { | |
| 601 | + if ( str_contains( $var, $substring ) ) { | |
| 576 | 602 | return false; |
| 577 | 603 | } |
| 578 | 604 | } |
| 579 | 605 | |
| @@ -654,18 +680,19 @@ | ||
| 654 | 680 | |
| 655 | 681 | if ( isset( $_POST['frm_style_setting'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing |
| 656 | 682 | |
| 657 | 683 | // Sanitizing is done later. |
| 658 | - $posted = wp_unslash( $_POST['frm_style_setting'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing | |
| 684 | + //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing | |
| 685 | + $posted = wp_unslash( $_POST['frm_style_setting'] ); | |
| 659 | 686 | |
| 660 | - if ( ! is_array( $posted ) ) { | |
| 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 { | |
| 661 | 691 | $posted = json_decode( $posted, true ); |
| 662 | 692 | FrmAppHelper::format_form_data( $posted ); |
| 663 | 693 | $settings = $frm_style->sanitize_post_content( $posted['frm_style_setting']['post_content'] ); |
| 664 | 694 | $style_name = sanitize_title( $posted['style_name'] ); |
| 665 | - } else { | |
| 666 | - $settings = $frm_style->sanitize_post_content( $posted['post_content'] ); | |
| 667 | - $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_title' ); | |
| 668 | 695 | } |
| 669 | 696 | } else { |
| 670 | 697 | $settings = $frm_style->sanitize_post_content( wp_unslash( $_GET ) ); |
| 671 | 698 | $style_name = FrmAppHelper::get_param( 'style_name', '', 'get', 'sanitize_title' ); |
| @@ -838,14 +865,11 @@ | ||
| 838 | 865 | */ |
| 839 | 866 | private static function get_color_output( $default, &$color ) { |
| 840 | 867 | $color = trim( $color ); |
| 841 | 868 | |
| 842 | - if ( empty( $color ) ) { | |
| 869 | + if ( ! $color ) { | |
| 843 | 870 | $color = $default; |
| 844 | - } elseif ( false !== strpos( $color, 'rgb(' ) ) { | |
| 845 | - $color = str_replace( 'rgb(', 'rgba(', $color ); | |
| 846 | - $color = str_replace( ')', ',1)', $color ); | |
| 847 | - } elseif ( strpos( $color, '#' ) === false && self::is_hex( $color ) ) { | |
| 871 | + } elseif ( ! str_contains( $color, '#' ) && self::is_hex( $color ) ) { | |
| 848 | 872 | $color = '#' . $color; |
| 849 | 873 | } |
| 850 | 874 | } |
| 851 | 875 | |
| @@ -860,8 +884,9 @@ | ||
| 860 | 884 | * @return bool |
| 861 | 885 | */ |
| 862 | 886 | private static function is_hex( $color ) { |
| 863 | 887 | $non_hex_substrings = array( |
| 888 | + 'rgb(', | |
| 864 | 889 | 'rgba(', |
| 865 | 890 | 'hsl(', |
| 866 | 891 | 'hsla(', |
| 867 | 892 | 'hwb(', |
| @@ -867,9 +892,9 @@ | ||
| 867 | 892 | 'hwb(', |
| 868 | 893 | ); |
| 869 | 894 | |
| 870 | 895 | foreach ( $non_hex_substrings as $substring ) { |
| 871 | - if ( false !== strpos( $color, $substring ) ) { | |
| 896 | + if ( str_contains( $color, $substring ) ) { | |
| 872 | 897 | return false; |
| 873 | 898 | } |
| 874 | 899 | } |
| 875 | 900 | |
| @@ -901,14 +926,31 @@ | ||
| 901 | 926 | return $change_margin; |
| 902 | 927 | } |
| 903 | 928 | |
| 904 | 929 | /** |
| 930 | + * Get the raw alignment value stored in the active style for a radio or checkbox field. | |
| 931 | + * | |
| 932 | + * @since 6.32 | |
| 933 | + * | |
| 934 | + * @param array|int $field The 'field' array. | |
| 935 | + * | |
| 936 | + * @return string | |
| 937 | + */ | |
| 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 ); | |
| 941 | + | |
| 942 | + return FrmStylesController::get_active_style( $field )->post_content[ $key ] ?? ''; | |
| 943 | + } | |
| 944 | + | |
| 945 | + /** | |
| 905 | 946 | * @since 2.3 |
| 906 | 947 | * |
| 907 | 948 | * @return bool |
| 908 | 949 | */ |
| 909 | 950 | public static function previewing_style() { |
| 910 | - $ajax_change = isset( $_POST['action'] ) && $_POST['action'] === 'frm_change_styling' && isset( $_POST['frm_style_setting'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 951 | + // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 952 | + $ajax_change = isset( $_POST['action'] ) && $_POST['action'] === 'frm_change_styling' && isset( $_POST['frm_style_setting'] ); | |
| 911 | 953 | |
| 912 | 954 | return $ajax_change || isset( $_GET['flat'] ); |
| 913 | 955 | } |
| 914 | 956 | |
| @@ -1001,11 +1043,10 @@ | ||
| 1001 | 1043 | return $number_of_forms; |
| 1002 | 1044 | } |
| 1003 | 1045 | |
| 1004 | 1046 | $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' ); |
| 1005 | - $number_of_forms += self::get_default_style_count( $style_id, $conversational_style_id ); | |
| 1006 | 1047 | |
| 1007 | - return $number_of_forms; | |
| 1048 | + return $number_of_forms + self::get_default_style_count( $style_id, $conversational_style_id ); | |
| 1008 | 1049 | } |
| 1009 | 1050 | |
| 1010 | 1051 | /** |
| 1011 | 1052 | * Get the number of forms that use the default style. |
| @@ -1067,14 +1108,13 @@ | ||
| 1067 | 1108 | * |
| 1068 | 1109 | * @return string The style editor wrapper classname. |
| 1069 | 1110 | */ |
| 1070 | 1111 | public static function style_editor_get_wrapper_classname( $section_type ) { |
| 1071 | - $is_quick_settings = ( 'quick-settings' === $section_type ); | |
| 1112 | + $is_quick_settings = 'quick-settings' === $section_type; | |
| 1072 | 1113 | $classname = 'frm-style-editor-form'; |
| 1073 | 1114 | $classname .= ( ! self::is_advanced_settings() xor $is_quick_settings ) ? ' frm_hidden' : ''; |
| 1074 | - $classname .= FrmAppHelper::pro_is_installed() ? ' frm-pro' : ''; | |
| 1075 | 1115 | |
| 1076 | - return $classname; | |
| 1116 | + return $classname . ( FrmAppHelper::pro_is_installed() ? ' frm-pro' : '' ); | |
| 1077 | 1117 | } |
| 1078 | 1118 | |
| 1079 | 1119 | /** |
| 1080 | 1120 | * Retrieve the background image URL of the submit button. |
| @@ -1088,13 +1128,15 @@ | ||
| 1088 | 1128 | */ |
| 1089 | 1129 | public static function get_submit_image_bg_url( $settings ) { |
| 1090 | 1130 | $background_image = $settings['submit_bg_img']; |
| 1091 | 1131 | |
| 1092 | - if ( empty( $background_image ) ) { | |
| 1132 | + if ( ! $background_image ) { | |
| 1093 | 1133 | return false; |
| 1094 | 1134 | } |
| 1095 | 1135 | |
| 1096 | - // Handle the case where the submit_bg_img is a full URL string. If the settings were saved with the older styler version prior to 6.14, the submit_bg_img will be a full URL string. | |
| 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. | |
| 1097 | 1139 | if ( ! is_numeric( $background_image ) ) { |
| 1098 | 1140 | return $background_image; |
| 1099 | 1141 | } |
| 1100 | 1142 | |
| @@ -1112,11 +1154,9 @@ | ||
| 1112 | 1154 | if ( ! FrmAppHelper::pro_is_installed() ) { |
| 1113 | 1155 | return false; |
| 1114 | 1156 | } |
| 1115 | 1157 | |
| 1116 | - return is_callable( 'FrmProAppHelper::use_chosen_js' ) | |
| 1117 | - ? FrmProAppHelper::use_chosen_js() | |
| 1118 | - : true; | |
| 1158 | + return is_callable( 'FrmProAppHelper::use_chosen_js' ) ? FrmProAppHelper::use_chosen_js() : true; | |
| 1119 | 1159 | } |
| 1120 | 1160 | |
| 1121 | 1161 | /** |
| 1122 | 1162 | * Returns the bottom part from a margin/padding value. |
| @@ -1133,10 +1173,93 @@ | ||
| 1133 | 1173 | } |
| 1134 | 1174 | |
| 1135 | 1175 | $parts = explode( ' ', $value ); |
| 1136 | 1176 | |
| 1137 | - if ( count( $parts ) < 3 ) { | |
| 1138 | - return $parts[0]; | |
| 1177 | + return count( $parts ) < 3 ? $parts[0] : $parts[2]; | |
| 1178 | + } | |
| 1179 | + | |
| 1180 | + /** | |
| 1181 | + * Scope CSS to .frm_forms on admin pages to prevent style conflicts. | |
| 1182 | + * On front-end pages, the CSS is returned unchanged. | |
| 1183 | + * | |
| 1184 | + * @since 6.30 | |
| 1185 | + * | |
| 1186 | + * @param string $css The CSS to scope. | |
| 1187 | + * | |
| 1188 | + * @return string | |
| 1189 | + */ | |
| 1190 | + public static function maybe_scope_css_for_admin( $css ) { | |
| 1191 | + if ( ! self::should_scope_custom_css() ) { | |
| 1192 | + return $css; | |
| 1139 | 1193 | } |
| 1140 | - return $parts[2]; | |
| 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 . '}'; | |
| 1205 | + } | |
| 1206 | + | |
| 1207 | + /** | |
| 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. | |
| 1211 | + * | |
| 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. | |
| 1217 | + */ | |
| 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 ); | |
| 1238 | + } | |
| 1239 | + | |
| 1240 | + /** | |
| 1241 | + * Minify CSS by stripping comments and whitespace. | |
| 1242 | + * Matches the minification used when saving the cached CSS file. | |
| 1243 | + * | |
| 1244 | + * @since 6.30 | |
| 1245 | + * | |
| 1246 | + * @param string $css The CSS to minify. | |
| 1247 | + * | |
| 1248 | + * @return string | |
| 1249 | + */ | |
| 1250 | + private static function minify_css( $css ) { | |
| 1251 | + return preg_replace( '/\/\*(.|\s)*?\*\//', '', str_replace( array( "\r\n", "\r", "\n", "\t", ' ' ), '', $css ) ); | |
| 1252 | + } | |
| 1253 | + | |
| 1254 | + /** | |
| 1255 | + * Check if custom CSS should be scoped for admin context. | |
| 1256 | + * | |
| 1257 | + * @since 6.30 | |
| 1258 | + * | |
| 1259 | + * @return bool | |
| 1260 | + */ | |
| 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'] ); | |
| 1141 | 1264 | } |
| 1142 | 1265 | } |