PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.35
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.35
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
formidable / classes / models / FrmStyle.php

FrmStyle.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.35, at classes/models/FrmStyle.php

936 lines 28.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmStyle {
7
8 /**
9 * The meta name of default template style.
10 *
11 * @since 6.14
12 *
13 * @var string
14 */
15 private $default_template_style_meta_name = 'frm_style_default';
16
17 /**
18 * Unique ID number of the current instance.
19 *
20 * @var int
21 */
22 public $number = false;
23
24 /**
25 * The id of the post.
26 *
27 * @var int|string
28 */
29 public $id = 0;
30
31 /**
32 * @param int|string $id The id of the stylesheet or 'default'.
33 */
34 public function __construct( $id = 0 ) {
35 $this->id = $id;
36 }
37
38 /**
39 * @return stdClass
40 */
41 public function get_new() {
42 $this->id = 0;
43
44 $max_slug_value = 2147483647;
45 // We want to have at least 2 characters in the slug.
46 $min_slug_value = 37;
47 $key = base_convert( random_int( $min_slug_value, $max_slug_value ), 10, 36 );
48
49 $style = array(
50 'post_type' => FrmStylesController::$post_type,
51 'ID' => '',
52 'post_title' => __( 'New Style', 'formidable' ),
53 'post_name' => $key,
54 'post_content' => $this->get_defaults(),
55 'menu_order' => '',
56 'post_status' => 'publish',
57 );
58
59 return (object) $style;
60 }
61
62 /**
63 * @param array $settings
64 *
65 * @return int|WP_Error
66 */
67 public function save( $settings ) {
68 return FrmDb::save_settings( $settings, 'frm_styles' );
69 }
70
71 /**
72 * @param int|string $id The id of the stylesheet or 'default'.
73 *
74 * @return void
75 */
76 public function duplicate( $id ) {
77 // Duplicating is a pro feature. This is handled in FrmProStyle::duplicate instead.
78 }
79
80 /**
81 * Handle save actions in the visual styler edit page.
82 *
83 * @param mixed $id
84 *
85 * @return array<int|WP_Error>
86 */
87 public function update( $id = 'default' ) {
88 $all_instances = $this->get_all();
89 $css_scope_helper = new FrmCssScopeHelper();
90
91 if ( ! $id ) {
92 $all_instances[] = (array) $this->get_new();
93 }
94
95 $action_ids = array();
96
97 foreach ( $all_instances as $new_instance ) {
98 $new_instance = (array) $new_instance;
99 $this->id = $new_instance['ID'];
100
101 // phpcs:ignore WordPress.Security.NonceVerification.Missing, Universal.Operators.StrictComparisons
102 if ( $id != $this->id || ! $_POST || ! isset( $_POST['frm_style_setting'] ) ) {
103 // Don't continue if not saving this style.
104 continue;
105 }
106
107 // Custom CSS is no longer used from the default style, but it is still checked if the Global Setting is missing.
108 // Preserve the previous value in case Custom CSS has not been saved as a Global Setting yet.
109 $custom_css = $new_instance['post_content']['custom_css'] ?? '';
110
111 // phpcs:ignore WordPress.Security.NonceVerification.Missing
112 if ( ! empty( $_POST['frm_style_setting']['post_title'] ) ) {
113 // The nonce check happens in FrmStylesController::save_style before this is called.
114 // phpcs:ignore WordPress.Security.NonceVerification.Missing
115 $new_instance['post_title'] = sanitize_text_field( wp_unslash( $_POST['frm_style_setting']['post_title'] ) );
116 }
117
118 $new_instance['post_content'] = isset( $_POST['frm_style_setting']['post_content'] ) ? $this->sanitize_post_content( wp_unslash( $_POST['frm_style_setting']['post_content'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing, SlevomatCodingStandard.Files.LineLength.LineTooLong
119 $new_instance['post_content']['custom_css'] = $custom_css;
120 unset( $custom_css );
121
122 $new_instance['post_type'] = FrmStylesController::$post_type;
123 $new_instance['post_status'] = 'publish';
124
125 if ( ! $id ) {
126 // For a new style (including a duplicate), the post_name is derived from the title.
127 // Resolve slug uniqueness up front (WordPress appends -2, -3, etc. to duplicate slugs)
128 // so the CSS scope below matches the slug WordPress will actually store.
129 $slug = sanitize_title( $new_instance['post_title'] );
130 $new_instance['post_name'] = wp_unique_post_slug( $slug, 0, $new_instance['post_status'], $new_instance['post_type'], 0 );
131 }
132
133 if ( ! empty( $new_instance['post_content']['single_style_custom_css'] ) ) {
134 $css_scope = 'frm_style_' . $new_instance['post_name'];
135 $new_instance['post_content']['single_style_custom_css'] = $css_scope_helper->nest( $new_instance['post_content']['single_style_custom_css'], $css_scope );
136 }
137
138 $default_settings = $this->get_defaults();
139
140 foreach ( $default_settings as $setting => $default ) {
141 if ( ! isset( $new_instance['post_content'][ $setting ] ) ) {
142 $new_instance['post_content'][ $setting ] = $default;
143 }
144
145 if ( $this->is_color( $setting ) ) {
146 $color_val = $new_instance['post_content'][ $setting ];
147
148 if ( $color_val !== '' && str_contains( $color_val, 'rgb' ) ) {
149 // Maybe sanitize if invalid rgba value is entered.
150 $this->maybe_sanitize_rgba_value( $color_val );
151 }
152 $new_instance['post_content'][ $setting ] = str_replace( '#', '', $color_val );
153 } elseif ( in_array( $setting, array( 'submit_style', 'important_style', 'auto_width' ), true ) && ! isset( $new_instance['post_content'][ $setting ] ) ) {
154 $new_instance['post_content'][ $setting ] = 0;
155 } elseif ( $setting === 'font' ) {
156 $new_instance['post_content'][ $setting ] = $this->force_balanced_quotation( $new_instance['post_content'][ $setting ] );
157 }
158 }
159
160 $new_instance['post_content'] = FrmStylesHelper::update_base_font_size( $new_instance['post_content'], $this->get_defaults() );
161 $action_ids[] = $this->save( $new_instance );
162 }//end foreach
163
164 $this->save_settings();
165
166 return $action_ids;
167 }
168
169 /**
170 * Sanitize custom color values and convert it to valid one filling missing values.
171 *
172 * @since 5.3.2
173 *
174 * @param string $color_val The color value, by reference.
175 *
176 * @return void
177 */
178 private function maybe_sanitize_rgba_value( &$color_val ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
179 if ( preg_match( '/(rgb|rgba)\(/', $color_val ) !== 1 ) {
180 return;
181 }
182
183 $color_val = trim( $color_val );
184 // Remove leading braces so (rgba(1,1,1,1) doesn't cause inconsistent braces.
185 $color_val = ltrim( $color_val, '(' );
186 $patterns = array( '/rgba\((\s*\d+\s*,){3}[[0-1]\.]+\)/', '/rgb\((\s*\d+\s*,){2}\s*[\d]+\)/' );
187
188 foreach ( $patterns as $pattern ) {
189 if ( preg_match( $pattern, $color_val ) === 1 ) {
190 return;
191 }
192 }
193
194 // Remove all leading ')' braces, then add one back. This way there's always a single brace.
195 $color_val = rtrim( $color_val, ')' );
196 $color_val .= ')';
197
198 $color_rgba = substr( $color_val, strpos( $color_val, '(' ) + 1, strlen( $color_val ) - strpos( $color_val, '(' ) - 2 );
199 // Remove any excessive braces from the rgba like rgba((.
200 $color_rgba = trim( $color_rgba, '()' );
201 $length_of_color_codes = strpos( $color_val, '(' );
202 $new_color_values = array();
203
204 // replace empty values by 0 or 1 (if alpha position).
205 foreach ( explode( ',', $color_rgba ) as $index => $value ) {
206 $new_value = null;
207 $value_is_empty_string = '' === trim( $value ) || '' === $value;
208
209 if ( 3 === $length_of_color_codes || $index !== $length_of_color_codes - 1 ) {
210 // Insert a value for r, g, or b.
211 if ( $value < 0 ) {
212 $new_value = 0;
213 } elseif ( $value > 255 ) {
214 $new_value = 255;
215 } elseif ( $value_is_empty_string ) {
216 $new_value = 0;
217 } else {
218 $new_value = absint( $value );
219 }
220 } else { // phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
221 // Insert a value for alpha.
222 if ( $value_is_empty_string ) {
223 $new_value = 4 === $length_of_color_codes ? 1 : 0;
224 } elseif ( $value > 1 || $value < 0 ) {
225 $new_value = 1;
226 } else {
227 $new_value = floatval( $value );
228 }
229 }//end if
230
231 $new_color_values[] = $new_value;
232 }//end foreach
233
234 // add more 0s and 1 (if alpha position) if needed.
235 $missing_values = $length_of_color_codes - count( $new_color_values );
236
237 if ( $missing_values > 1 ) {
238 $insert_values = array_fill( 0, $missing_values - 1, 0 );
239 $last_value = 4 === $length_of_color_codes ? 1 : 0;
240 array_push( $insert_values, $last_value );
241 } elseif ( $missing_values === 1 ) {
242 $insert_values = 4 === $length_of_color_codes ? array( 1 ) : array( 0 );
243 }
244
245 if ( ! empty( $insert_values ) ) {
246 $new_color_values = array_merge( $new_color_values, $insert_values );
247 }
248
249 $new_color = implode( ',', $new_color_values );
250 $prefix = substr( $color_val, 0, strpos( $color_val, '(' ) + 1 );
251 // Limit the number of opening braces after rgb/rgba. There should only be one.
252 $prefix = rtrim( $prefix, '(' ) . '(';
253 $new_color = $prefix . $new_color . ')';
254 $color_val = $new_color;
255 }
256
257 /**
258 * @since 5.0.13
259 *
260 * @param array $settings
261 *
262 * @return array
263 */
264 public function sanitize_post_content( $settings ) {
265 $defaults = $this->get_defaults();
266 $valid_keys = array_keys( $defaults );
267 $sanitized_settings = array();
268
269 foreach ( $valid_keys as $key ) {
270 $sanitized_settings[ $key ] = isset( $settings[ $key ] ) ? sanitize_textarea_field( $settings[ $key ] ) : $defaults[ $key ];
271
272 if ( 'custom_css' !== $key && 'single_style_custom_css' !== $key ) {
273 $sanitized_settings[ $key ] = $this->strip_invalid_characters( $sanitized_settings[ $key ] );
274 }
275 }
276
277 return $sanitized_settings;
278 }
279
280 /**
281 * Remove any characters that should not be used in CSS.
282 *
283 * @since 6.2.3
284 *
285 * @param string $setting
286 *
287 * @return string
288 */
289 private function strip_invalid_characters( $setting ) {
290 $characters_to_remove = array( '{', '}', ';', '[', ']' );
291
292 // RGB is handled instead in self::maybe_sanitize_rgba_value.
293 if ( ! str_starts_with( $setting, 'rgb' ) ) {
294 $setting = $this->maybe_fix_braces( $setting, $characters_to_remove );
295 }
296
297 return str_replace( $characters_to_remove, '', $setting );
298 }
299
300 /**
301 * @since 6.2.3
302 *
303 * @param string $setting
304 * @param array $characters_to_remove
305 *
306 * @return string
307 */
308 private function maybe_fix_braces( $setting, &$characters_to_remove ) {
309 $number_of_opening_braces = substr_count( $setting, '(' );
310 $number_of_closing_braces = substr_count( $setting, ')' );
311
312 if ( $number_of_opening_braces === $number_of_closing_braces ) {
313 return $this->trim_braces( $setting );
314 }
315
316 if ( $this->should_remove_every_brace( $setting ) ) {
317 // Add to $characters_to_remove to remove when str_replace is called.
318 array_push( $characters_to_remove, '(', ')' );
319 return $setting;
320 }
321
322 return $this->trim_braces( $setting );
323 }
324
325 /**
326 * @since 6.2.3
327 *
328 * @param string $input
329 *
330 * @return string
331 */
332 private function trim_braces( $input ) {
333 $output = $input;
334
335 // Remove any ( from the start of the string as no CSS values expect at the first character.
336 if ( $output && in_array( $output[0], array( '(', ')' ), true ) ) {
337 $output = ltrim( $output, '()' );
338 }
339
340 // Remove extra braces from the end.
341 if ( in_array( substr( $output, -1 ), array( '(', ')' ), true ) ) {
342 $output = rtrim( $output, '()' );
343
344 if ( str_contains( $output, '(' ) ) {
345 $output .= ')';
346 }
347 }
348
349 return $output;
350 }
351
352 /**
353 * @since 6.2.3
354 *
355 * @param string $setting
356 *
357 * @return bool
358 */
359 private function should_remove_every_brace( $setting ) {
360 if ( str_starts_with( trim( $setting, '()' ), 'calc' ) ) {
361 // Support calc() sizes. We do not want to remove all braces when calc is used.
362 return false;
363 }
364
365 // Matches hex values but also checks for unexpected ( and ).
366 $looks_like_a_hex_value = preg_match( '/^(?:\()?(?!#?[a-fA-F0-9]*[^\(#\)\da-fA-F])[a-fA-F0-9\(\)]*(?:\))?$/', $setting );
367
368 if ( $looks_like_a_hex_value ) {
369 return true;
370 }
371
372 // Matches size values but also checks for unexpected ( and ).
373 // This is case insensitive so it will catch PX, PT, etc, as well.
374 $looks_like_a_size = preg_match( '/\(?[+-]?\d*\.?\d+(?:px|%|em|rem|ex|pt|pc|mm|cm|in)\)?/i', $setting );
375 return (bool) $looks_like_a_size;
376 }
377
378 /**
379 * @since 3.01.01
380 *
381 * @param string $setting
382 *
383 * @return bool
384 */
385 private function is_color( $setting ) {
386 if ( str_contains( $setting, 'color' ) ) {
387 return true;
388 }
389
390 return in_array( $setting, array( 'error_bg', 'error_border', 'error_text' ), true );
391 }
392
393 /**
394 * @since 3.01.01
395 *
396 * @return array
397 */
398 public function get_color_settings() {
399 $settings = array_keys( $this->get_defaults() );
400 return array_filter( $settings, array( $this, 'is_color' ) );
401 }
402
403 /**
404 * Create static CSS file and update the CSS transient alternative.
405 *
406 * @return void
407 */
408 public function save_settings() {
409 $filename = FrmAppHelper::plugin_path() . '/css/custom_theme.css.php';
410 update_option( 'frm_last_style_update', gmdate( 'njGi' ) );
411
412 if ( ! is_file( $filename ) ) {
413 return;
414 }
415
416 $this->clear_cache();
417
418 $css = $this->get_css_content( $filename );
419 $create_file = new FrmCreateFile( self::get_create_style_file_args() );
420 $create_file->create_file( $css );
421
422 update_option( 'frmpro_css', $css, false );
423 set_transient( 'frmpro_css', $css, MONTH_IN_SECONDS );
424 }
425
426 /**
427 * @since 6.32
428 *
429 * @return array
430 */
431 private static function get_create_style_file_args() {
432 $add_css_to_uploads_dir = self::add_css_to_uploads_dir();
433 $create_file_args = array(
434 'file_name' => FrmStylesController::get_file_name(),
435 'new_file_path' => self::get_generated_css_file_path( $add_css_to_uploads_dir ),
436 );
437
438 if ( $add_css_to_uploads_dir ) {
439 $create_file_args['folder_name'] = 'formidable/css';
440 }
441
442 return $create_file_args;
443 }
444
445 /**
446 * @since 6.32
447 *
448 * @param bool $add_css_to_uploads_dir
449 *
450 * @return string
451 */
452 public static function get_generated_css_file_path( $add_css_to_uploads_dir ) {
453 if ( $add_css_to_uploads_dir ) {
454 return self::target_css_uploads_dir();
455 }
456 return self::target_css_plugin_dir();
457 }
458
459 /**
460 * Returns true if generated css file should be saved in the uploads directory.
461 *
462 * @since 6.32
463 *
464 * @return bool
465 */
466 public static function add_css_to_uploads_dir() {
467 /**
468 * @since 6.32
469 *
470 * @param bool $add_css_to_uploads_dir
471 */
472 return apply_filters( 'frm_add_css_to_uploads_dir', ! wp_is_file_mod_allowed( 'frm_save_css_to_plugin_folder' ) );
473 }
474
475 /**
476 * @since 6.32
477 *
478 * @return string
479 */
480 private static function target_css_uploads_dir() {
481 return wp_upload_dir()['basedir'] . '/formidable/css';
482 }
483
484 /**
485 * @since 6.32
486 *
487 * @return string
488 */
489 private static function target_css_plugin_dir() {
490 return FrmAppHelper::plugin_path() . '/css';
491 }
492
493 /**
494 * @param string $filename
495 *
496 * @return string
497 */
498 private function get_css_content( $filename ) {
499 $css = '/* ' . __( 'WARNING: Any changes made to this file will be lost when your Formidable settings are updated', 'formidable' ) . ' */' . "\n";
500 $saving = true;
501 $frm_style = $this;
502
503 ob_start();
504 include $filename;
505 $css .= preg_replace( '/\/\*(.|\s)*?\*\//', '', str_replace( array( "\r\n", "\r", "\n", "\t", ' ' ), '', ob_get_clean() ) );
506
507 return FrmStylesController::replace_relative_url( $css );
508 }
509
510 /**
511 * @return void
512 */
513 private function clear_cache() {
514 $default_post_atts = array(
515 'post_type' => FrmStylesController::$post_type,
516 'post_status' => 'publish',
517 'numberposts' => 99,
518 'orderby' => 'title',
519 'order' => 'ASC',
520 );
521
522 FrmDb::delete_cache_and_transient( json_encode( $default_post_atts ), 'frm_styles' );
523 FrmDb::cache_delete_group( 'frm_styles' );
524 FrmDb::delete_cache_and_transient( 'frmpro_css' );
525 }
526
527 /**
528 * Delete a style by its post ID.
529 *
530 * @param int $id
531 *
532 * @return false|WP_Post|null
533 */
534 public function destroy( $id ) {
535 if ( $id === $this->get_default_style()->ID ) {
536 return false;
537 }
538 return wp_delete_post( $id );
539 }
540
541 /**
542 * @return stdClass|WP_Post
543 */
544 public function get_one() {
545 if ( 'default' === $this->id ) {
546 $style = $this->get_default_style();
547
548 $this->id = $style ? $style->ID : 0;
549
550 return $style;
551 }
552
553 $style = get_post( $this->id );
554
555 if ( ! $style ) {
556 return $style;
557 }
558
559 $style->post_content = FrmAppHelper::maybe_json_decode( $style->post_content );
560
561 $default_values = $this->get_defaults();
562
563 // Fill default values
564 $style->post_content = $this->override_defaults( $style->post_content );
565 $style->post_content = wp_parse_args( $style->post_content, $default_values );
566
567 return $style;
568 }
569
570 /**
571 * @param string $orderby
572 * @param string $order
573 * @param int $limit
574 *
575 * @return array
576 */
577 public function get_all( $orderby = 'title', $order = 'ASC', $limit = 99 ) {
578 $post_atts = array(
579 'post_type' => FrmStylesController::$post_type,
580 'post_status' => 'publish',
581 'numberposts' => $limit,
582 'orderby' => $orderby,
583 'order' => $order,
584 );
585
586 $temp_styles = FrmDb::check_cache( json_encode( $post_atts ), 'frm_styles', $post_atts, 'get_posts' );
587
588 if ( ! $temp_styles ) {
589 global $wpdb;
590 // Make sure there wasn't a conflict with the query
591 $query = $wpdb->prepare( 'SELECT * FROM ' . $wpdb->posts . ' WHERE post_type=%s AND post_status=%s ORDER BY post_title ASC LIMIT 99', FrmStylesController::$post_type, 'publish' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
592 $temp_styles = FrmDb::check_cache( 'frm_backup_style_check', 'frm_styles', $query, 'get_results' );
593
594 if ( ! $temp_styles ) {
595 // Create a new style if there are none
596 $new = $this->get_new();
597 $new->post_title = __( 'Formidable Style', 'formidable' );
598 $new->post_name = $new->post_title;
599 $new->menu_order = 1;
600 $new = $this->save( (array) $new );
601 $this->update( 'default' );
602
603 $post_atts['include'] = $new;
604 $temp_styles = get_posts( $post_atts );
605 }
606 }
607
608 $default_values = $this->get_defaults();
609 $default_style = false;
610 $styles = array();
611
612 foreach ( $temp_styles as $style ) {
613 $this->id = $style->ID;
614
615 if ( $style->menu_order ) {
616 if ( $default_style ) {
617 // Only return one default
618 $style->menu_order = 0;
619 } else {
620 // Check for a default style
621 $default_style = $style->ID;
622 }
623 }
624
625 $style->post_content = FrmAppHelper::maybe_json_decode( $style->post_content );
626
627 // Fill default values
628 $style->post_content = $this->override_defaults( $style->post_content );
629 $style->post_content = wp_parse_args( $style->post_content, $default_values );
630
631 $styles[ $style->ID ] = $style;
632 }//end foreach
633
634 if ( ! $default_style ) {
635 $default_style = reset( $styles );
636 $styles[ $default_style->ID ]->menu_order = 1;
637 }
638
639 return $styles;
640 }
641
642 /**
643 * @param array|null $styles
644 *
645 * @return object|null
646 */
647 public function get_default_style( $styles = null ) {
648 if ( ! isset( $styles ) ) {
649 $styles = $this->get_all( 'menu_order', 'DESC', 1 );
650 }
651
652 foreach ( $styles as $style ) {
653 if ( $style->menu_order ) {
654 return $style;
655 }
656 }
657
658 return null;
659 }
660
661 /**
662 * @param mixed $settings
663 *
664 * @return mixed
665 */
666 public function override_defaults( $settings ) {
667 if ( ! is_array( $settings ) ) {
668 return $settings;
669 }
670
671 $settings['line_height'] = ! isset( $settings['field_height'] ) || $settings['field_height'] == '' || $settings['field_height'] === 'auto' ? 'normal' : $settings['field_height']; // phpcs:ignore Universal.Operators.StrictComparisons, SlevomatCodingStandard.Files.LineLength.LineTooLong
672
673 if ( ! isset( $settings['form_desc_size'] ) && isset( $settings['description_font_size'] ) ) {
674 $settings['form_desc_size'] = $settings['description_font_size'];
675 $settings['form_desc_color'] = $settings['description_color'];
676 $settings['title_color'] = $settings['label_color'];
677 }
678
679 if ( ! isset( $settings['section_color'] ) && isset( $settings['label_color'] ) ) {
680 $settings['section_color'] = $settings['label_color'];
681 $settings['section_border_color'] = $settings['border_color'];
682 }
683
684 if ( ! isset( $settings['submit_hover_bg_color'] ) && isset( $settings['submit_bg_color'] ) ) {
685 $settings['submit_hover_bg_color'] = $settings['submit_bg_color'];
686 }
687
688 if ( ! isset( $settings['submit_hover_color'] ) && isset( $settings['submit_text_color'] ) ) {
689 $settings['submit_hover_color'] = $settings['submit_text_color'];
690 }
691
692 if ( ! isset( $settings['submit_hover_border_color'] ) && isset( $settings['submit_border_color'] ) ) {
693 $settings['submit_hover_border_color'] = $settings['submit_border_color'];
694 }
695
696 if ( ! isset( $settings['submit_active_bg_color'] ) && isset( $settings['submit_bg_color'] ) ) {
697 $settings['submit_active_bg_color'] = $settings['submit_bg_color'];
698 }
699
700 if ( ! isset( $settings['submit_active_color'] ) && isset( $settings['submit_text_color'] ) ) {
701 $settings['submit_active_color'] = $settings['submit_text_color'];
702 }
703
704 if ( ! isset( $settings['submit_active_border_color'] ) && isset( $settings['submit_border_color'] ) ) {
705 $settings['submit_active_border_color'] = $settings['submit_border_color'];
706 }
707
708 return apply_filters( 'frm_override_default_styles', $settings );
709 }
710
711 /**
712 * @return array
713 */
714 public function get_defaults() {
715 $defaults = array(
716 'theme_css' => 'ui-lightness',
717 'theme_name' => 'UI Lightness',
718
719 'center_form' => '',
720 'form_width' => '100%',
721 'form_align' => 'left',
722 'direction' => is_rtl() ? 'rtl' : 'ltr',
723 'fieldset' => '0px',
724 'fieldset_color' => '000000',
725 'fieldset_padding' => '0px 0px 15px 0px',
726 'fieldset_bg_color' => '',
727
728 'title_size' => '40px',
729 'title_color' => '444444',
730 'title_margin_top' => '10px',
731 'title_margin_bottom' => '60px',
732 'form_desc_size' => '14px',
733 'form_desc_color' => '98A2B3',
734 'form_desc_margin_top' => '10px',
735 'form_desc_margin_bottom' => '25px',
736 'form_desc_padding' => '0px',
737
738 'font' => '',
739 'font_size' => '15px',
740 'label_color' => '344054',
741 'weight' => 'normal',
742 'position' => 'none',
743 'align' => 'left',
744 'width' => '150px',
745 'required_color' => 'F04438',
746 'required_weight' => 'bold',
747 'label_padding' => '0px 0px 5px 0px',
748
749 'description_font_size' => '12px',
750 'description_color' => '667085',
751 'description_weight' => 'normal',
752 'description_style' => 'normal',
753 'description_align' => 'left',
754 'description_margin' => '0px',
755
756 'field_font_size' => '14px',
757 'field_height' => '36px',
758 'line_height' => 'normal',
759 'field_width' => '100%',
760 'auto_width' => false,
761 'field_pad' => '8px 12px',
762 'field_margin' => '20px',
763 'field_weight' => 'normal',
764 'text_color' => '1D2939',
765 // 'border_color_hv' => 'cccccc',
766 'border_color' => 'D0D5DD',
767 'field_border_width' => '1px',
768 'field_border_style' => 'solid',
769
770 'bg_color' => 'ffffff',
771 // 'bg_color_hv' => 'ffffff',
772 'remove_box_shadow' => '',
773 'bg_color_active' => 'ffffff',
774 'border_color_active' => '4199FD',
775 'remove_box_shadow_active' => '',
776 'text_color_error' => '444444',
777 'bg_color_error' => 'ffffff',
778 'border_color_error' => 'F04438',
779 'border_width_error' => '1px',
780 'border_style_error' => 'solid',
781 'bg_color_disabled' => 'F9FAFB',
782 'border_color_disabled' => 'D0D5DD',
783 'text_color_disabled' => '667085',
784
785 'radio_align' => 'block',
786 'check_align' => 'block',
787 'check_font_size' => '14px',
788 'check_label_color' => '1D2939',
789 'check_weight' => 'normal',
790
791 'section_font_size' => '18px',
792 'section_color' => '344054',
793 'section_weight' => 'bold',
794 'section_pad' => '32px 0px 3px 0px',
795 'section_mar_top' => '30px',
796 'section_mar_bottom' => '30px',
797 'section_bg_color' => '',
798 'section_border_color' => 'EAECF0',
799 'section_border_width' => '1px',
800 'section_border_style' => 'solid',
801 'section_border_loc' => '-top',
802 'collapse_icon' => '6',
803 'collapse_pos' => 'after',
804 'repeat_icon' => '1',
805 'repeat_icon_color' => 'ffffff',
806
807 'submit_style' => false,
808 'submit_font_size' => '14px',
809 'submit_width' => 'auto',
810 'submit_height' => 'auto',
811 'submit_bg_color' => '4199FD',
812 'submit_border_color' => '4199FD',
813 'submit_border_width' => '1px',
814 'submit_text_color' => 'ffffff',
815 'submit_weight' => 'normal',
816 'submit_border_radius' => '8px',
817 'submit_bg_img' => '',
818 'submit_margin' => '10px',
819 'submit_padding' => '8px 16px',
820 'submit_shadow_color' => 'eeeeee',
821 'submit_hover_bg_color' => '3680D3',
822 'submit_hover_color' => 'ffffff',
823 'submit_hover_border_color' => '3680D3',
824 'submit_active_bg_color' => '3680D3',
825 'submit_active_color' => 'ffffff',
826 'submit_active_border_color' => '3680D3',
827
828 'border_radius' => '8px',
829 'error_bg' => 'FEE4E2',
830 'error_border' => 'F5B8AA',
831 'error_text' => 'F04438',
832 'error_font_size' => '14px',
833
834 'success_bg_color' => 'DFF0D8',
835 'success_border_color' => 'D6E9C6',
836 'success_text_color' => '468847',
837 'success_font_size' => '14px',
838
839 'important_style' => false,
840
841 'progress_bg_color' => 'EAECF0',
842 'progress_color' => '1D2939',
843 'progress_active_bg_color' => '4199FD',
844 'progress_active_color' => 'ffffff',
845 'progress_border_color' => 'EAECF0',
846 'progress_border_size' => '1px',
847 'progress_size' => '30px',
848 'custom_css' => '',
849 'use_base_font_size' => false,
850 'base_font_size' => '15px',
851 'field_shape_type' => 'rounded-corner',
852
853 'enable_style_custom_css' => false,
854 'single_style_custom_css' => '',
855 );
856
857 return apply_filters( 'frm_default_style_settings', $defaults );
858 }
859
860 /**
861 * Get a name attribute value for a style setting input.
862 *
863 * @param string $field_name
864 * @param string $post_field
865 *
866 * @return string
867 */
868 public function get_field_name( $field_name, $post_field = 'post_content' ) {
869 return 'frm_style_setting' . ( $post_field ? '[' . $post_field . ']' : '' ) . '[' . $field_name . ']';
870 }
871
872 /**
873 * @return array
874 */
875 public static function get_bold_options() {
876 return array(
877 100 => __( 'Thin', 'formidable' ),
878 200 => __( 'Extra Light', 'formidable' ),
879 300 => __( 'Light', 'formidable' ),
880 'normal' => __( 'Regular', 'formidable' ),
881 500 => __( 'Medium', 'formidable' ),
882 600 => __( 'Semi Bold', 'formidable' ),
883 'bold' => __( 'Bold', 'formidable' ),
884 800 => __( 'Extra Bold', 'formidable' ),
885 900 => __( 'Black', 'formidable' ),
886 );
887 }
888
889 /**
890 * Don't let imbalanced font families ruin the whole stylesheet.
891 *
892 * @param string $value
893 *
894 * @return string
895 */
896 public function force_balanced_quotation( $value ) {
897 $balanced_characters = array( '"', "'" );
898
899 foreach ( $balanced_characters as $char ) {
900 $char_count = substr_count( $value, $char );
901 $is_balanced = $char_count % 2 === 0;
902
903 if ( $is_balanced ) {
904 continue;
905 }
906
907 if ( $value && $char === $value[ strlen( $value ) - 1 ] ) {
908 $value = $char . $value;
909 } else {
910 $value .= $char;
911 }
912 }
913
914 return $value;
915 }
916
917 /**
918 * Get the default template style
919 *
920 * @since 6.14
921 *
922 * @param int|string $style_id The post type "frm_styles" ID.
923 *
924 * @return string The json encoded template data
925 */
926 public function get_default_template_style( $style_id ) {
927 $default_template = get_post_meta( (int) $style_id, $this->default_template_style_meta_name, true );
928
929 if ( ! $default_template ) {
930 return FrmAppHelper::prepare_and_encode( $this->get_defaults() );
931 }
932
933 return $default_template;
934 }
935 }
936