| @@ -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' ), |
| @@ -66,8 +76,11 @@ | ||
| 66 | 76 | */ |
| 67 | 77 | return apply_filters( 'frm_single_label_positions', $label_positions, $field ); |
| 68 | 78 | } |
| 69 | 79 | |
| 80 | + /** | |
| 81 | + * @return array | |
| 82 | + */ | |
| 70 | 83 | public static function minus_icons() { |
| 71 | 84 | return array( |
| 72 | 85 | 0 => array( |
| 73 | 86 | '-' => '62e', |
| @@ -91,8 +104,11 @@ | ||
| 91 | 104 | ), |
| 92 | 105 | ); |
| 93 | 106 | } |
| 94 | 107 | |
| 108 | + /** | |
| 109 | + * @return array | |
| 110 | + */ | |
| 95 | 111 | public static function arrow_icons() { |
| 96 | 112 | $minus_icons = self::minus_icons(); |
| 97 | 113 | |
| 98 | 114 | return array( |
| @@ -133,8 +149,13 @@ | ||
| 133 | 149 | } |
| 134 | 150 | |
| 135 | 151 | /** |
| 136 | 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 | + * | |
| 137 | 158 | * @return string The class for this icon. |
| 138 | 159 | */ |
| 139 | 160 | public static function icon_key_to_class( $key, $icon = '+', $type = 'arrow' ) { |
| 140 | 161 | if ( 'arrow' === $type && is_numeric( $key ) ) { |
| @@ -156,11 +177,10 @@ | ||
| 156 | 177 | |
| 157 | 178 | if ( $key ) { |
| 158 | 179 | $class .= $key; |
| 159 | 180 | } |
| 160 | - $class .= '_icon'; | |
| 161 | 181 | |
| 162 | - return $class; | |
| 182 | + return $class . '_icon'; | |
| 163 | 183 | } |
| 164 | 184 | |
| 165 | 185 | /** |
| 166 | 186 | * @param WP_Post $style |
| @@ -165,8 +185,9 @@ | ||
| 165 | 185 | /** |
| 166 | 186 | * @param WP_Post $style |
| 167 | 187 | * @param FrmStyle $frm_style |
| 168 | 188 | * @param string $type |
| 189 | + * | |
| 169 | 190 | * @return void |
| 170 | 191 | */ |
| 171 | 192 | public static function bs_icon_select( $style, $frm_style, $type = 'arrow' ) { |
| 172 | 193 | $function_name = $type . '_icons'; |
| @@ -173,8 +194,9 @@ | ||
| 173 | 194 | $icons = self::$function_name(); |
| 174 | 195 | unset( $function_name ); |
| 175 | 196 | |
| 176 | 197 | $name = 'arrow' === $type ? 'collapse_icon' : 'repeat_icon'; |
| 198 | + // phpcs:disable Generic.WhiteSpace.ScopeIndent | |
| 177 | 199 | ?> |
| 178 | 200 | <div class="btn-group" id="frm_<?php echo esc_attr( $name ); ?>_select"> |
| 179 | 201 | <button class="multiselect dropdown-toggle btn btn-default" data-toggle="dropdown" type="button"> |
| 180 | 202 | <?php FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $style->post_content[ $name ], '+', $type ) ); ?> |
| @@ -182,12 +204,12 @@ | ||
| 182 | 204 | <b class="caret"></b> |
| 183 | 205 | </button> |
| 184 | 206 | <ul class="multiselect-container frm-dropdown-menu"> |
| 185 | 207 | <?php foreach ( $icons as $key => $icon ) { ?> |
| 186 | - <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 ?>> | |
| 187 | 209 | <a href="javascript:void(0);"> |
| 188 | 210 | <label> |
| 189 | - <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 ?> | |
| 190 | 212 | <span> |
| 191 | 213 | <?php |
| 192 | 214 | FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $key, '+', $type ) ); |
| 193 | 215 | FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $key, '-', $type ) ); |
| @@ -199,8 +221,9 @@ | ||
| 199 | 221 | <?php } ?> |
| 200 | 222 | </ul> |
| 201 | 223 | </div> |
| 202 | 224 | <?php |
| 225 | + // phpcs:enable Generic.WhiteSpace.ScopeIndent | |
| 203 | 226 | } |
| 204 | 227 | |
| 205 | 228 | /** |
| 206 | 229 | * Convert a color setting to a RGB CSV (without the rgb()/rgba() wrapper). |
| @@ -207,16 +230,13 @@ | ||
| 207 | 230 | * |
| 208 | 231 | * @since 2.0 |
| 209 | 232 | * |
| 210 | 233 | * @param string $color Color setting value. This could be hex or rgb. |
| 234 | + * | |
| 211 | 235 | * @return string RGB value without the rgb() wrapper. |
| 212 | 236 | */ |
| 213 | 237 | public static function hex2rgb( $color ) { |
| 214 | - if ( 0 === strpos( $color, 'rgb' ) ) { | |
| 215 | - $rgb = self::get_rgb_array_from_rgb( $color ); | |
| 216 | - } else { | |
| 217 | - $rgb = self::get_rgb_array_from_hex( $color ); | |
| 218 | - } | |
| 238 | + $rgb = str_starts_with( $color, 'rgb' ) ? self::get_rgb_array_from_rgb( $color ) : self::get_rgb_array_from_hex( $color ); | |
| 219 | 239 | return implode( ',', $rgb ); |
| 220 | 240 | } |
| 221 | 241 | |
| 222 | 242 | /** |
| @@ -224,17 +244,20 @@ | ||
| 224 | 244 | * |
| 225 | 245 | * @since 6.8.3 |
| 226 | 246 | * |
| 227 | 247 | * @param string $rgb RGB value including the rgb() or rgba() wrapper. |
| 248 | + * | |
| 228 | 249 | * @return array<string> including three numeric values for R, G, and B. |
| 229 | 250 | */ |
| 230 | 251 | private static function get_rgb_array_from_rgb( $rgb ) { |
| 231 | 252 | $rgb = str_replace( array( 'rgb(', 'rgba(', ')' ), '', $rgb ); |
| 232 | 253 | $rgb = explode( ',', $rgb ); |
| 254 | + | |
| 233 | 255 | if ( 4 === count( $rgb ) ) { |
| 234 | 256 | // Drop the alpha. The function is expected to only return r,g,b with no alpha. |
| 235 | 257 | array_pop( $rgb ); |
| 236 | 258 | } |
| 259 | + | |
| 237 | 260 | return $rgb; |
| 238 | 261 | } |
| 239 | 262 | |
| 240 | 263 | /** |
| @@ -242,8 +265,9 @@ | ||
| 242 | 265 | * |
| 243 | 266 | * @since 6.8.3 |
| 244 | 267 | * |
| 245 | 268 | * @param string $hex A hex color string. |
| 269 | + * | |
| 246 | 270 | * @return array<string> Including three numeric values for R, G, and B. |
| 247 | 271 | */ |
| 248 | 272 | private static function get_rgb_array_from_hex( $hex ) { |
| 249 | 273 | $hex = str_replace( '#', '', $hex ); |
| @@ -252,12 +276,16 @@ | ||
| 252 | 276 | } |
| 253 | 277 | |
| 254 | 278 | /** |
| 255 | 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 | |
| 256 | 285 | */ |
| 257 | 286 | public static function hex2rgba( $hex, $a ) { |
| 258 | 287 | $rgb = self::hex2rgb( $hex ); |
| 259 | - | |
| 260 | 288 | return 'rgba(' . $rgb . ',' . $a . ')'; |
| 261 | 289 | } |
| 262 | 290 | |
| 263 | 291 | /** |
| @@ -263,12 +291,13 @@ | ||
| 263 | 291 | /** |
| 264 | 292 | * @since 6.0 |
| 265 | 293 | * |
| 266 | 294 | * @param string $rgba Color setting value. This could be hex or rgb. |
| 295 | + * | |
| 267 | 296 | * @return string Hex color value. |
| 268 | 297 | */ |
| 269 | 298 | private static function rgb_to_hex( $rgba ) { |
| 270 | - if ( strpos( $rgba, '#' ) === 0 ) { | |
| 299 | + if ( str_starts_with( $rgba, '#' ) ) { | |
| 271 | 300 | // Color is already hex. |
| 272 | 301 | return $rgba; |
| 273 | 302 | } |
| 274 | 303 | preg_match( '/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i', $rgba, $by_color ); |
| @@ -278,8 +307,9 @@ | ||
| 278 | 307 | /** |
| 279 | 308 | * @since 6.8 |
| 280 | 309 | * |
| 281 | 310 | * @param string $hsl |
| 311 | + * | |
| 282 | 312 | * @return string|null Null if it fails to parse the HSL string. |
| 283 | 313 | */ |
| 284 | 314 | private static function hsl_to_hex( $hsl ) { |
| 285 | 315 | // Convert hsla to hsl. |
| @@ -331,22 +361,23 @@ | ||
| 331 | 361 | $g = round( ( $g + $m ) * 255 ); |
| 332 | 362 | $b = round( ( $b + $m ) * 255 ); |
| 333 | 363 | |
| 334 | 364 | // Convert RGB to hex |
| 335 | - $hex = sprintf( '%02x%02x%02x', $r, $g, $b ); | |
| 336 | - | |
| 337 | - return $hex; | |
| 365 | + return sprintf( '%02x%02x%02x', $r, $g, $b ); | |
| 338 | 366 | } |
| 339 | 367 | |
| 340 | 368 | /** |
| 341 | 369 | * @since 2.3 |
| 370 | + * | |
| 342 | 371 | * @param string $hex string The original color in hex format #ffffff. |
| 343 | 372 | * @param int $steps integer Should be between -255 and 255. Negative = darker, positive = lighter. |
| 373 | + * | |
| 374 | + * @return string | |
| 344 | 375 | */ |
| 345 | 376 | public static function adjust_brightness( $hex, $steps ) { |
| 346 | 377 | $steps = max( - 255, min( 255, $steps ) ); |
| 347 | 378 | |
| 348 | - if ( 0 === strpos( $hex, 'rgba(' ) ) { | |
| 379 | + if ( str_starts_with( $hex, 'rgba(' ) ) { | |
| 349 | 380 | $rgba = str_replace( ')', '', str_replace( 'rgba(', '', $hex ) ); |
| 350 | 381 | list ( $r, $g, $b, $a ) = array_map( 'trim', explode( ',', $rgba ) ); |
| 351 | 382 | $r = max( 0, min( 255, $r + $steps ) ); |
| 352 | 383 | $g = max( 0, min( 255, $g + $steps ) ); |
| @@ -378,32 +409,34 @@ | ||
| 378 | 409 | /** |
| 379 | 410 | * @since 6.0 |
| 380 | 411 | * |
| 381 | 412 | * @param string $color |
| 413 | + * | |
| 382 | 414 | * @return int |
| 383 | 415 | */ |
| 384 | 416 | public static function get_color_brightness( $color ) { |
| 385 | - if ( 0 === strpos( $color, 'rgb' ) ) { | |
| 417 | + if ( str_starts_with( $color, 'rgb' ) ) { | |
| 386 | 418 | $color = self::rgb_to_hex( $color ); |
| 387 | 419 | } |
| 388 | 420 | |
| 389 | - if ( 0 === strpos( $color, 'hsl' ) ) { | |
| 421 | + if ( str_starts_with( $color, 'hsl' ) ) { | |
| 390 | 422 | $hsl_to_hex = self::hsl_to_hex( $color ); |
| 423 | + | |
| 391 | 424 | if ( is_null( $hsl_to_hex ) ) { |
| 392 | 425 | // Fallback if we cannot convert the HSL value. |
| 393 | 426 | return 0; |
| 394 | 427 | } |
| 428 | + | |
| 395 | 429 | $color = $hsl_to_hex; |
| 396 | 430 | } |
| 397 | 431 | |
| 398 | 432 | self::fill_hex( $color ); |
| 399 | 433 | |
| 400 | - $c_r = hexdec( substr( $color, 0, 2 ) ); | |
| 401 | - $c_g = hexdec( substr( $color, 2, 2 ) ); | |
| 402 | - $c_b = hexdec( substr( $color, 4, 2 ) ); | |
| 403 | - $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 ) ); | |
| 404 | 437 | |
| 405 | - return $brightness; | |
| 438 | + return ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000; | |
| 406 | 439 | } |
| 407 | 440 | |
| 408 | 441 | /** |
| 409 | 442 | * Change a 3 character hex color to a 6 character one. |
| @@ -409,8 +442,10 @@ | ||
| 409 | 442 | * Change a 3 character hex color to a 6 character one. |
| 410 | 443 | * |
| 411 | 444 | * @since 6.0 |
| 412 | 445 | * |
| 446 | + * @param string $color Color value, passed by reference. | |
| 447 | + * | |
| 413 | 448 | * @return void |
| 414 | 449 | */ |
| 415 | 450 | private static function fill_hex( &$color ) { |
| 416 | 451 | if ( 3 === strlen( $color ) ) { |
| @@ -419,8 +454,12 @@ | ||
| 419 | 454 | } |
| 420 | 455 | |
| 421 | 456 | /** |
| 422 | 457 | * @since 4.05.02 |
| 458 | + * | |
| 459 | + * @param array $vars CSS variable keys. | |
| 460 | + * | |
| 461 | + * @return array | |
| 423 | 462 | */ |
| 424 | 463 | public static function get_css_vars( $vars = array() ) { |
| 425 | 464 | $vars = apply_filters( 'frm_css_vars', $vars ); |
| 426 | 465 | return array_unique( $vars ); |
| @@ -427,32 +466,72 @@ | ||
| 427 | 466 | } |
| 428 | 467 | |
| 429 | 468 | /** |
| 430 | 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 | |
| 431 | 476 | */ |
| 432 | 477 | public static function output_vars( $settings, $defaults = array(), $vars = array() ) { |
| 433 | - if ( empty( $vars ) ) { | |
| 478 | + if ( ! $vars ) { | |
| 434 | 479 | $vars = self::get_css_vars( array_keys( $settings ) ); |
| 435 | 480 | } |
| 436 | - $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' ); | |
| 437 | - $vars = array_diff( $vars, $remove ); | |
| 438 | 481 | |
| 482 | + $vars = array_diff( $vars, self::get_style_keys_to_remove_from_output_vars() ); | |
| 483 | + | |
| 439 | 484 | foreach ( $vars as $var ) { |
| 440 | 485 | if ( ! isset( $settings[ $var ] ) || ! self::css_key_is_valid( $var ) ) { |
| 441 | 486 | continue; |
| 442 | 487 | } |
| 488 | + | |
| 443 | 489 | if ( ! isset( $defaults[ $var ] ) ) { |
| 444 | 490 | $defaults[ $var ] = ''; |
| 445 | 491 | } |
| 446 | 492 | |
| 447 | 493 | $prepared_value = ''; |
| 494 | + | |
| 448 | 495 | if ( self::should_add_css_var( $settings, $defaults, $var, $prepared_value ) ) { |
| 449 | - 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 . ';'; | |
| 450 | 498 | } |
| 451 | 499 | } |
| 452 | 500 | } |
| 453 | 501 | |
| 454 | 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 | + /** | |
| 455 | 534 | * Check if a CSS variable setting is not blank, doesn't match the default, and doesn't include invalid substrings. |
| 456 | 535 | * |
| 457 | 536 | * @since 6.24 |
| 458 | 537 | * |
| @@ -459,12 +538,14 @@ | ||
| 459 | 538 | * @param array $settings Array of setting values. |
| 460 | 539 | * @param array $defaults Array of default values. |
| 461 | 540 | * @param string $var The setting key name. |
| 462 | 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 | + * | |
| 463 | 543 | * @return bool True if the CSS value should be printed. |
| 464 | 544 | */ |
| 465 | 545 | private static function should_add_css_var( $settings, $defaults, $var, &$prepared_value ) { |
| 466 | 546 | $prepared_value = self::css_var_prepare_value( $settings, $var ); |
| 547 | + | |
| 467 | 548 | if ( $prepared_value === '' ) { |
| 468 | 549 | return false; |
| 469 | 550 | } |
| 470 | 551 | |
| @@ -480,14 +561,15 @@ | ||
| 480 | 561 | * |
| 481 | 562 | * @since 6.20 |
| 482 | 563 | * |
| 483 | 564 | * @param string $key |
| 565 | + * | |
| 484 | 566 | * @return bool |
| 485 | 567 | */ |
| 486 | 568 | private static function css_key_is_valid( $key ) { |
| 487 | 569 | // Any key that is abnormally large is not valid. |
| 488 | 570 | // Any key that contains a '{' is not valid. |
| 489 | - return strlen( $key ) < 100 && false === strpos( $key, '{' ); | |
| 571 | + return strlen( $key ) < 100 && ! str_contains( $key, '{' ); | |
| 490 | 572 | } |
| 491 | 573 | |
| 492 | 574 | /** |
| 493 | 575 | * Confirm a CSS value is valid. |
| @@ -495,8 +577,9 @@ | ||
| 495 | 577 | * |
| 496 | 578 | * @since 6.20 |
| 497 | 579 | * |
| 498 | 580 | * @param string $var |
| 581 | + * | |
| 499 | 582 | * @return bool |
| 500 | 583 | */ |
| 501 | 584 | private static function css_value_is_valid( $var ) { |
| 502 | 585 | if ( is_numeric( $var ) ) { |
| @@ -514,9 +597,9 @@ | ||
| 514 | 597 | 'Array;', |
| 515 | 598 | ); |
| 516 | 599 | |
| 517 | 600 | foreach ( $invalid_substrings as $substring ) { |
| 518 | - if ( strpos( $var, $substring ) !== false ) { | |
| 601 | + if ( str_contains( $var, $substring ) ) { | |
| 519 | 602 | return false; |
| 520 | 603 | } |
| 521 | 604 | } |
| 522 | 605 | |
| @@ -522,13 +605,13 @@ | ||
| 522 | 605 | |
| 523 | 606 | return true; |
| 524 | 607 | } |
| 525 | 608 | |
| 526 | - | |
| 527 | 609 | /** |
| 528 | 610 | * Remove anything that isn't used as a CSS variable name. |
| 529 | 611 | * |
| 530 | 612 | * @param string $var_name |
| 613 | + * | |
| 531 | 614 | * @return string |
| 532 | 615 | */ |
| 533 | 616 | private static function clean_var_name( $var_name ) { |
| 534 | 617 | return preg_replace( '/[^a-zA-Z0-9_-]/', '', $var_name ); |
| @@ -587,25 +670,29 @@ | ||
| 587 | 670 | /** |
| 588 | 671 | * @since 2.3 |
| 589 | 672 | * |
| 590 | 673 | * @param WP_Post $style |
| 674 | + * | |
| 591 | 675 | * @return array |
| 592 | 676 | */ |
| 593 | 677 | public static function get_settings_for_output( $style ) { |
| 594 | 678 | if ( self::previewing_style() ) { |
| 595 | 679 | $frm_style = new FrmStyle(); |
| 680 | + | |
| 596 | 681 | if ( isset( $_POST['frm_style_setting'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing |
| 597 | 682 | |
| 598 | 683 | // Sanitizing is done later. |
| 599 | - $posted = wp_unslash( $_POST['frm_style_setting'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing | |
| 600 | - 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 { | |
| 601 | 691 | $posted = json_decode( $posted, true ); |
| 602 | 692 | FrmAppHelper::format_form_data( $posted ); |
| 603 | 693 | $settings = $frm_style->sanitize_post_content( $posted['frm_style_setting']['post_content'] ); |
| 604 | 694 | $style_name = sanitize_title( $posted['style_name'] ); |
| 605 | - } else { | |
| 606 | - $settings = $frm_style->sanitize_post_content( $posted['post_content'] ); | |
| 607 | - $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_title' ); | |
| 608 | 695 | } |
| 609 | 696 | } else { |
| 610 | 697 | $settings = $frm_style->sanitize_post_content( wp_unslash( $_GET ) ); |
| 611 | 698 | $style_name = FrmAppHelper::get_param( 'style_name', '', 'get', 'sanitize_title' ); |
| @@ -615,8 +702,9 @@ | ||
| 615 | 702 | |
| 616 | 703 | FrmAppHelper::sanitize_value( 'sanitize_text_field', $settings ); |
| 617 | 704 | |
| 618 | 705 | $settings['style_class'] = ''; |
| 706 | + | |
| 619 | 707 | if ( ! empty( $style_name ) ) { |
| 620 | 708 | $settings['style_class'] = $style_name . '.'; |
| 621 | 709 | } |
| 622 | 710 | } else { |
| @@ -628,8 +716,9 @@ | ||
| 628 | 716 | $settings['font'] = stripslashes( $settings['font'] ); |
| 629 | 717 | $settings['change_margin'] = self::description_margin_for_screensize( $settings['width'] ); |
| 630 | 718 | |
| 631 | 719 | $checkbox_opts = array( 'important_style', 'auto_width', 'submit_style', 'collapse_icon', 'center_form' ); |
| 720 | + | |
| 632 | 721 | foreach ( $checkbox_opts as $opt ) { |
| 633 | 722 | if ( ! isset( $settings[ $opt ] ) ) { |
| 634 | 723 | $settings[ $opt ] = 0; |
| 635 | 724 | } |
| @@ -654,8 +743,9 @@ | ||
| 654 | 743 | * |
| 655 | 744 | * @since 6.14 |
| 656 | 745 | * |
| 657 | 746 | * @param array $settings An array of css style. |
| 747 | + * @param array $defaults Default style settings. | |
| 658 | 748 | * |
| 659 | 749 | * @return array |
| 660 | 750 | */ |
| 661 | 751 | public static function update_base_font_size( $settings, $defaults ) { |
| @@ -661,8 +751,9 @@ | ||
| 661 | 751 | public static function update_base_font_size( $settings, $defaults ) { |
| 662 | 752 | if ( empty( $settings['base_font_size'] ) || empty( $settings['use_base_font_size'] ) || 'false' === $settings['use_base_font_size'] ) { |
| 663 | 753 | return $settings; |
| 664 | 754 | } |
| 755 | + | |
| 665 | 756 | $base_font_size = (int) $settings['base_font_size']; |
| 666 | 757 | $font_size = $defaults['font_size']; |
| 667 | 758 | $font_sizes_to_update = array( |
| 668 | 759 | 'font_size', |
| @@ -694,8 +785,12 @@ | ||
| 694 | 785 | * Get style font size scale value. |
| 695 | 786 | * |
| 696 | 787 | * @since 6.14 |
| 697 | 788 | * |
| 789 | + * @param string $key Setting key. | |
| 790 | + * @param int|string $value Base font size value. | |
| 791 | + * @param array $defaults Default style settings. | |
| 792 | + * | |
| 698 | 793 | * @return float |
| 699 | 794 | */ |
| 700 | 795 | private static function get_base_font_size_scale( $key, $value, $defaults ) { |
| 701 | 796 | if ( empty( $defaults[ $key ] ) || ! is_numeric( (int) $defaults[ $key ] ) || ! is_numeric( (int) $value ) || 0 === (int) $value ) { |
| @@ -706,15 +801,22 @@ | ||
| 706 | 801 | } |
| 707 | 802 | |
| 708 | 803 | /** |
| 709 | 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 | |
| 710 | 810 | */ |
| 711 | 811 | public static function prepare_color_output( &$settings, $allow_transparent = true ) { |
| 712 | 812 | $colors = self::allow_color_override(); |
| 813 | + | |
| 713 | 814 | foreach ( $colors as $css => $opts ) { |
| 714 | 815 | if ( $css === 'transparent' && ! $allow_transparent ) { |
| 715 | 816 | $css = ''; |
| 716 | 817 | } |
| 818 | + | |
| 717 | 819 | foreach ( $opts as $opt ) { |
| 718 | 820 | self::get_color_output( $css, $settings[ $opt ] ); |
| 719 | 821 | } |
| 720 | 822 | } |
| @@ -754,17 +856,20 @@ | ||
| 754 | 856 | } |
| 755 | 857 | |
| 756 | 858 | /** |
| 757 | 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 | |
| 758 | 865 | */ |
| 759 | 866 | private static function get_color_output( $default, &$color ) { |
| 760 | 867 | $color = trim( $color ); |
| 761 | - if ( empty( $color ) ) { | |
| 868 | + | |
| 869 | + if ( ! $color ) { | |
| 762 | 870 | $color = $default; |
| 763 | - } elseif ( false !== strpos( $color, 'rgb(' ) ) { | |
| 764 | - $color = str_replace( 'rgb(', 'rgba(', $color ); | |
| 765 | - $color = str_replace( ')', ',1)', $color ); | |
| 766 | - } elseif ( strpos( $color, '#' ) === false && self::is_hex( $color ) ) { | |
| 871 | + } elseif ( ! str_contains( $color, '#' ) && self::is_hex( $color ) ) { | |
| 767 | 872 | $color = '#' . $color; |
| 768 | 873 | } |
| 769 | 874 | } |
| 770 | 875 | |
| @@ -774,12 +879,14 @@ | ||
| 774 | 879 | * |
| 775 | 880 | * @since 6.8 |
| 776 | 881 | * |
| 777 | 882 | * @param string $color |
| 883 | + * | |
| 778 | 884 | * @return bool |
| 779 | 885 | */ |
| 780 | 886 | private static function is_hex( $color ) { |
| 781 | 887 | $non_hex_substrings = array( |
| 888 | + 'rgb(', | |
| 782 | 889 | 'rgba(', |
| 783 | 890 | 'hsl(', |
| 784 | 891 | 'hsla(', |
| 785 | 892 | 'hwb(', |
| @@ -785,9 +892,9 @@ | ||
| 785 | 892 | 'hwb(', |
| 786 | 893 | ); |
| 787 | 894 | |
| 788 | 895 | foreach ( $non_hex_substrings as $substring ) { |
| 789 | - if ( false !== strpos( $color, $substring ) ) { | |
| 896 | + if ( str_contains( $color, $substring ) ) { | |
| 790 | 897 | return false; |
| 791 | 898 | } |
| 792 | 899 | } |
| 793 | 900 | |
| @@ -798,12 +905,17 @@ | ||
| 798 | 905 | * If left/right label is over a certain size, |
| 799 | 906 | * adjust the field description margin at a different screen size |
| 800 | 907 | * |
| 801 | 908 | * @since 2.3 |
| 909 | + * | |
| 910 | + * @param string $width Label width value. | |
| 911 | + * | |
| 912 | + * @return false|string | |
| 802 | 913 | */ |
| 803 | 914 | private static function description_margin_for_screensize( $width ) { |
| 804 | 915 | $temp_label_width = str_replace( 'px', '', $width ); |
| 805 | 916 | $change_margin = false; |
| 917 | + | |
| 806 | 918 | if ( $temp_label_width >= 230 ) { |
| 807 | 919 | $change_margin = '800px'; |
| 808 | 920 | } elseif ( $width >= 215 ) { |
| 809 | 921 | $change_margin = '700px'; |
| @@ -814,14 +926,31 @@ | ||
| 814 | 926 | return $change_margin; |
| 815 | 927 | } |
| 816 | 928 | |
| 817 | 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 | + /** | |
| 818 | 946 | * @since 2.3 |
| 819 | 947 | * |
| 820 | 948 | * @return bool |
| 821 | 949 | */ |
| 822 | 950 | public static function previewing_style() { |
| 823 | - $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'] ); | |
| 824 | 953 | |
| 825 | 954 | return $ajax_change || isset( $_GET['flat'] ); |
| 826 | 955 | } |
| 827 | 956 | |
| @@ -830,8 +959,9 @@ | ||
| 830 | 959 | * |
| 831 | 960 | * @since 6.0 |
| 832 | 961 | * |
| 833 | 962 | * @param int|string $form_id |
| 963 | + * | |
| 834 | 964 | * @return string |
| 835 | 965 | */ |
| 836 | 966 | public static function get_list_url( $form_id ) { |
| 837 | 967 | return admin_url( 'admin.php?page=formidable-styles&form=' . absint( $form_id ) ); |
| @@ -843,8 +973,9 @@ | ||
| 843 | 973 | * @since 6.14 |
| 844 | 974 | * |
| 845 | 975 | * @param stdClass|WP_Post $style |
| 846 | 976 | * @param int $form_id |
| 977 | + * | |
| 847 | 978 | * @return array |
| 848 | 979 | */ |
| 849 | 980 | public static function get_style_options_back_button_args( $style, $form_id ) { |
| 850 | 981 | if ( self::is_advanced_settings() ) { |
| @@ -891,8 +1022,9 @@ | ||
| 891 | 1022 | * @since 6.0 |
| 892 | 1023 | * |
| 893 | 1024 | * @param int|string $style_id |
| 894 | 1025 | * @param bool $is_default |
| 1026 | + * | |
| 895 | 1027 | * @return int |
| 896 | 1028 | */ |
| 897 | 1029 | public static function get_form_count_for_style( $style_id, $is_default ) { |
| 898 | 1030 | $serialized = serialize( array( 'custom_style' => (string) $style_id ) ); |
| @@ -911,11 +1043,10 @@ | ||
| 911 | 1043 | return $number_of_forms; |
| 912 | 1044 | } |
| 913 | 1045 | |
| 914 | 1046 | $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' ); |
| 915 | - $number_of_forms += self::get_default_style_count( $style_id, $conversational_style_id ); | |
| 916 | 1047 | |
| 917 | - return $number_of_forms; | |
| 1048 | + return $number_of_forms + self::get_default_style_count( $style_id, $conversational_style_id ); | |
| 918 | 1049 | } |
| 919 | 1050 | |
| 920 | 1051 | /** |
| 921 | 1052 | * Get the number of forms that use the default style. |
| @@ -923,8 +1054,9 @@ | ||
| 923 | 1054 | * @since 6.0 |
| 924 | 1055 | * |
| 925 | 1056 | * @param int|string $style_id |
| 926 | 1057 | * @param mixed $conversational_style_id |
| 1058 | + * | |
| 927 | 1059 | * @return int |
| 928 | 1060 | */ |
| 929 | 1061 | private static function get_default_style_count( $style_id, $conversational_style_id ) { |
| 930 | 1062 | $substrings = array_map( |
| @@ -976,14 +1108,13 @@ | ||
| 976 | 1108 | * |
| 977 | 1109 | * @return string The style editor wrapper classname. |
| 978 | 1110 | */ |
| 979 | 1111 | public static function style_editor_get_wrapper_classname( $section_type ) { |
| 980 | - $is_quick_settings = ( 'quick-settings' === $section_type ); | |
| 1112 | + $is_quick_settings = 'quick-settings' === $section_type; | |
| 981 | 1113 | $classname = 'frm-style-editor-form'; |
| 982 | 1114 | $classname .= ( ! self::is_advanced_settings() xor $is_quick_settings ) ? ' frm_hidden' : ''; |
| 983 | - $classname .= FrmAppHelper::pro_is_installed() ? ' frm-pro' : ''; | |
| 984 | 1115 | |
| 985 | - return $classname; | |
| 1116 | + return $classname . ( FrmAppHelper::pro_is_installed() ? ' frm-pro' : '' ); | |
| 986 | 1117 | } |
| 987 | 1118 | |
| 988 | 1119 | /** |
| 989 | 1120 | * Retrieve the background image URL of the submit button. |
| @@ -991,16 +1122,21 @@ | ||
| 991 | 1122 | * |
| 992 | 1123 | * @since 6.14 |
| 993 | 1124 | * |
| 994 | 1125 | * @param array $settings |
| 1126 | + * | |
| 995 | 1127 | * @return false|string Return image url or false. |
| 996 | 1128 | */ |
| 997 | 1129 | public static function get_submit_image_bg_url( $settings ) { |
| 998 | 1130 | $background_image = $settings['submit_bg_img']; |
| 999 | - if ( empty( $background_image ) ) { | |
| 1131 | + | |
| 1132 | + if ( ! $background_image ) { | |
| 1000 | 1133 | return false; |
| 1001 | 1134 | } |
| 1002 | - // 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. | |
| 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. | |
| 1003 | 1139 | if ( ! is_numeric( $background_image ) ) { |
| 1004 | 1140 | return $background_image; |
| 1005 | 1141 | } |
| 1006 | 1142 | |
| @@ -1018,11 +1154,9 @@ | ||
| 1018 | 1154 | if ( ! FrmAppHelper::pro_is_installed() ) { |
| 1019 | 1155 | return false; |
| 1020 | 1156 | } |
| 1021 | 1157 | |
| 1022 | - return is_callable( 'FrmProAppHelper::use_chosen_js' ) | |
| 1023 | - ? FrmProAppHelper::use_chosen_js() | |
| 1024 | - : true; | |
| 1158 | + return is_callable( 'FrmProAppHelper::use_chosen_js' ) ? FrmProAppHelper::use_chosen_js() : true; | |
| 1025 | 1159 | } |
| 1026 | 1160 | |
| 1027 | 1161 | /** |
| 1028 | 1162 | * Returns the bottom part from a margin/padding value. |
| @@ -1029,8 +1163,9 @@ | ||
| 1029 | 1163 | * |
| 1030 | 1164 | * @since 6.17 |
| 1031 | 1165 | * |
| 1032 | 1166 | * @param string $value The margin/padding value. |
| 1167 | + * | |
| 1033 | 1168 | * @return string |
| 1034 | 1169 | */ |
| 1035 | 1170 | public static function get_bottom_value( $value ) { |
| 1036 | 1171 | if ( ! $value ) { |
| @@ -1035,11 +1170,96 @@ | ||
| 1035 | 1170 | public static function get_bottom_value( $value ) { |
| 1036 | 1171 | if ( ! $value ) { |
| 1037 | 1172 | return $value; |
| 1038 | 1173 | } |
| 1174 | + | |
| 1039 | 1175 | $parts = explode( ' ', $value ); |
| 1040 | - if ( count( $parts ) < 3 ) { | |
| 1041 | - return $parts[0]; | |
| 1176 | + | |
| 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; | |
| 1042 | 1193 | } |
| 1043 | - 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'] ); | |
| 1044 | 1264 | } |
| 1045 | 1265 | } |