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

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