PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.31
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.31
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.31, 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 $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 if ( ! empty( $new_instance['post_content']['single_style_custom_css'] ) ) {
123 $css_scope = 'frm_style_' . $new_instance['post_name'];
124 $new_instance['post_content']['single_style_custom_css'] = $css_scope_helper->nest( $new_instance['post_content']['single_style_custom_css'], $css_scope );
125 }
126
127 $new_instance['post_type'] = FrmStylesController::$post_type;
128 $new_instance['post_status'] = 'publish';
129
130 if ( ! $id ) {
131 $new_instance['post_name'] = $new_instance['post_title'];
132 }
133
134 $default_settings = $this->get_defaults();
135
136 foreach ( $default_settings as $setting => $default ) {
137 if ( ! isset( $new_instance['post_content'][ $setting ] ) ) {
138 $new_instance['post_content'][ $setting ] = $default;
139 }
140
141 if ( $this->is_color( $setting ) ) {
142 $color_val = $new_instance['post_content'][ $setting ];
143
144 if ( $color_val !== '' && str_contains( $color_val, 'rgb' ) ) {
145 // Maybe sanitize if invalid rgba value is entered.
146 $this->maybe_sanitize_rgba_value( $color_val );
147 }
148 $new_instance['post_content'][ $setting ] = str_replace( '#', '', $color_val );
149 } elseif ( in_array( $setting, array( 'submit_style', 'important_style', 'auto_width' ), true ) && ! isset( $new_instance['post_content'][ $setting ] ) ) {
150 $new_instance['post_content'][ $setting ] = 0;
151 } elseif ( $setting === 'font' ) {
152 $new_instance['post_content'][ $setting ] = $this->force_balanced_quotation( $new_instance['post_content'][ $setting ] );
153 }
154 }
155
156 $new_instance['post_content'] = FrmStylesHelper::update_base_font_size( $new_instance['post_content'], $this->get_defaults() );
157 $action_ids[] = $this->save( $new_instance );
158 }//end foreach
159
160 $this->save_settings();
161
162 return $action_ids;
163 }
164
165 /**
166 * Sanitize custom color values and convert it to valid one filling missing values.
167 *
168 * @since 5.3.2
169 *
170 * @param string $color_val The color value, by reference.
171 *
172 * @return void
173 */
174 private function maybe_sanitize_rgba_value( &$color_val ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
175 if ( preg_match( '/(rgb|rgba)\(/', $color_val ) !== 1 ) {
176 return;
177 }
178
179 $color_val = trim( $color_val );
180 // Remove leading braces so (rgba(1,1,1,1) doesn't cause inconsistent braces.
181 $color_val = ltrim( $color_val, '(' );
182 $patterns = array( '/rgba\((\s*\d+\s*,){3}[[0-1]\.]+\)/', '/rgb\((\s*\d+\s*,){2}\s*[\d]+\)/' );
183
184 foreach ( $patterns as $pattern ) {
185 if ( preg_match( $pattern, $color_val ) === 1 ) {
186 return;
187 }
188 }
189
190 // Remove all leading ')' braces, then add one back. This way there's always a single brace.
191 $color_val = rtrim( $color_val, ')' );
192 $color_val .= ')';
193
194 $color_rgba = substr( $color_val, strpos( $color_val, '(' ) + 1, strlen( $color_val ) - strpos( $color_val, '(' ) - 2 );
195 // Remove any excessive braces from the rgba like rgba((.
196 $color_rgba = trim( $color_rgba, '()' );
197 $length_of_color_codes = strpos( $color_val, '(' );
198 $new_color_values = array();
199
200 // replace empty values by 0 or 1 (if alpha position).
201 foreach ( explode( ',', $color_rgba ) as $index => $value ) {
202 $new_value = null;
203 $value_is_empty_string = '' === trim( $value ) || '' === $value;
204
205 if ( 3 === $length_of_color_codes || $index !== $length_of_color_codes - 1 ) {
206 // Insert a value for r, g, or b.
207 if ( $value < 0 ) {
208 $new_value = 0;
209 } elseif ( $value > 255 ) {
210 $new_value = 255;
211 } elseif ( $value_is_empty_string ) {
212 $new_value = 0;
213 } else {
214 $new_value = absint( $value );
215 }
216 } else { // phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
217 // Insert a value for alpha.
218 if ( $value_is_empty_string ) {
219 $new_value = 4 === $length_of_color_codes ? 1 : 0;
220 } elseif ( $value > 1 || $value < 0 ) {
221 $new_value = 1;
222 } else {
223 $new_value = floatval( $value );
224 }
225 }//end if
226
227 $new_color_values[] = $new_value;
228 }//end foreach
229
230 // add more 0s and 1 (if alpha position) if needed.
231 $missing_values = $length_of_color_codes - count( $new_color_values );
232
233 if ( $missing_values > 1 ) {
234 $insert_values = array_fill( 0, $missing_values - 1, 0 );
235 $last_value = 4 === $length_of_color_codes ? 1 : 0;
236 array_push( $insert_values, $last_value );
237 } elseif ( $missing_values === 1 ) {
238 $insert_values = 4 === $length_of_color_codes ? array( 1 ) : array( 0 );
239 }
240
241 if ( ! empty( $insert_values ) ) {
242 $new_color_values = array_merge( $new_color_values, $insert_values );
243 }
244
245 $new_color = implode( ',', $new_color_values );
246 $prefix = substr( $color_val, 0, strpos( $color_val, '(' ) + 1 );
247 // Limit the number of opening braces after rgb/rgba. There should only be one.
248 $prefix = rtrim( $prefix, '(' ) . '(';
249 $new_color = $prefix . $new_color . ')';
250 $color_val = $new_color;
251 }
252
253 /**
254 * @since 5.0.13
255 *
256 * @param array $settings
257 *
258 * @return array
259 */
260 public function sanitize_post_content( $settings ) {
261 $defaults = $this->get_defaults();
262 $valid_keys = array_keys( $defaults );
263 $sanitized_settings = array();
264
265 foreach ( $valid_keys as $key ) {
266 $sanitized_settings[ $key ] = isset( $settings[ $key ] ) ? sanitize_textarea_field( $settings[ $key ] ) : $defaults[ $key ];
267
268 if ( 'custom_css' !== $key && 'single_style_custom_css' !== $key ) {
269 $sanitized_settings[ $key ] = $this->strip_invalid_characters( $sanitized_settings[ $key ] );
270 }
271 }
272
273 return $sanitized_settings;
274 }
275
276 /**
277 * Remove any characters that should not be used in CSS.
278 *
279 * @since 6.2.3
280 *
281 * @param string $setting
282 *
283 * @return string
284 */
285 private function strip_invalid_characters( $setting ) {
286 $characters_to_remove = array( '{', '}', ';', '[', ']' );
287
288 // RGB is handled instead in self::maybe_sanitize_rgba_value.
289 if ( ! str_starts_with( $setting, 'rgb' ) ) {
290 $setting = $this->maybe_fix_braces( $setting, $characters_to_remove );
291 }
292
293 return str_replace( $characters_to_remove, '', $setting );
294 }
295
296 /**
297 * @since 6.2.3
298 *
299 * @param string $setting
300 * @param array $characters_to_remove
301 *
302 * @return string
303 */
304 private function maybe_fix_braces( $setting, &$characters_to_remove ) {
305 $number_of_opening_braces = substr_count( $setting, '(' );
306 $number_of_closing_braces = substr_count( $setting, ')' );
307
308 if ( $number_of_opening_braces === $number_of_closing_braces ) {
309 return $this->trim_braces( $setting );
310 }
311
312 if ( $this->should_remove_every_brace( $setting ) ) {
313 // Add to $characters_to_remove to remove when str_replace is called.
314 array_push( $characters_to_remove, '(', ')' );
315 return $setting;
316 }
317
318 return $this->trim_braces( $setting );
319 }
320
321 /**
322 * @since 6.2.3
323 *
324 * @param string $input
325 *
326 * @return string
327 */
328 private function trim_braces( $input ) {
329 $output = $input;
330
331 // Remove any ( from the start of the string as no CSS values expect at the first character.
332 if ( $output && in_array( $output[0], array( '(', ')' ), true ) ) {
333 $output = ltrim( $output, '()' );
334 }
335
336 // Remove extra braces from the end.
337 if ( in_array( substr( $output, -1 ), array( '(', ')' ), true ) ) {
338 $output = rtrim( $output, '()' );
339
340 if ( str_contains( $output, '(' ) ) {
341 $output .= ')';
342 }
343 }
344
345 return $output;
346 }
347
348 /**
349 * @since 6.2.3
350 *
351 * @param string $setting
352 *
353 * @return bool
354 */
355 private function should_remove_every_brace( $setting ) {
356 if ( str_starts_with( trim( $setting, '()' ), 'calc' ) ) {
357 // Support calc() sizes. We do not want to remove all braces when calc is used.
358 return false;
359 }
360
361 // Matches hex values but also checks for unexpected ( and ).
362 $looks_like_a_hex_value = preg_match( '/^(?:\()?(?!#?[a-fA-F0-9]*[^\(#\)\da-fA-F])[a-fA-F0-9\(\)]*(?:\))?$/', $setting );
363
364 if ( $looks_like_a_hex_value ) {
365 return true;
366 }
367
368 // Matches size values but also checks for unexpected ( and ).
369 // This is case insensitive so it will catch PX, PT, etc, as well.
370 $looks_like_a_size = preg_match( '/\(?[+-]?\d*\.?\d+(?:px|%|em|rem|ex|pt|pc|mm|cm|in)\)?/i', $setting );
371 return (bool) $looks_like_a_size;
372 }
373
374 /**
375 * @since 3.01.01
376 *
377 * @param string $setting
378 *
379 * @return bool
380 */
381 private function is_color( $setting ) {
382 if ( str_contains( $setting, 'color' ) ) {
383 return true;
384 }
385
386 return in_array( $setting, array( 'error_bg', 'error_border', 'error_text' ), true );
387 }
388
389 /**
390 * @since 3.01.01
391 *
392 * @return array
393 */
394 public function get_color_settings() {
395 $settings = array_keys( $this->get_defaults() );
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, false );
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' . ( $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