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

858 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 {
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 $defaults = $this->get_defaults();
396 $settings = array_keys( $defaults );
397
398 return array_filter( $settings, array( $this, 'is_color' ) );
399 }
400
401 /**
402 * Create static CSS file and update the CSS transient alternative.
403 *
404 * @return void
405 */
406 public function save_settings() {
407 $filename = FrmAppHelper::plugin_path() . '/css/custom_theme.css.php';
408 update_option( 'frm_last_style_update', gmdate( 'njGi' ) );
409
410 if ( ! is_file( $filename ) ) {
411 return;
412 }
413
414 $this->clear_cache();
415
416 $css = $this->get_css_content( $filename );
417 $create_file = new FrmCreateFile(
418 array(
419 'file_name' => FrmStylesController::get_file_name(),
420 'new_file_path' => FrmAppHelper::plugin_path() . '/css',
421 )
422 );
423 $create_file->create_file( $css );
424
425 update_option( 'frmpro_css', $css, false );
426 set_transient( 'frmpro_css', $css, MONTH_IN_SECONDS );
427 }
428
429 /**
430 * @param string $filename
431 *
432 * @return string
433 */
434 private function get_css_content( $filename ) {
435 $css = '/* ' . __( 'WARNING: Any changes made to this file will be lost when your Formidable settings are updated', 'formidable' ) . ' */' . "\n";
436 $saving = true;
437 $frm_style = $this;
438
439 ob_start();
440 include $filename;
441 $css .= preg_replace( '/\/\*(.|\s)*?\*\//', '', str_replace( array( "\r\n", "\r", "\n", "\t", ' ' ), '', ob_get_clean() ) );
442
443 return FrmStylesController::replace_relative_url( $css );
444 }
445
446 /**
447 * @return void
448 */
449 private function clear_cache() {
450 $default_post_atts = array(
451 'post_type' => FrmStylesController::$post_type,
452 'post_status' => 'publish',
453 'numberposts' => 99,
454 'orderby' => 'title',
455 'order' => 'ASC',
456 );
457
458 FrmDb::delete_cache_and_transient( json_encode( $default_post_atts ), 'frm_styles' );
459 FrmDb::cache_delete_group( 'frm_styles' );
460 FrmDb::delete_cache_and_transient( 'frmpro_css' );
461 }
462
463 /**
464 * Delete a style by its post ID.
465 *
466 * @param int $id
467 *
468 * @return false|WP_Post|null
469 */
470 public function destroy( $id ) {
471 if ( $id === $this->get_default_style()->ID ) {
472 return false;
473 }
474 return wp_delete_post( $id );
475 }
476
477 /**
478 * @return stdClass|WP_Post
479 */
480 public function get_one() {
481 if ( 'default' === $this->id ) {
482 $style = $this->get_default_style();
483
484 $this->id = $style ? $style->ID : 0;
485
486 return $style;
487 }
488
489 $style = get_post( $this->id );
490
491 if ( ! $style ) {
492 return $style;
493 }
494
495 $style->post_content = FrmAppHelper::maybe_json_decode( $style->post_content );
496
497 $default_values = $this->get_defaults();
498
499 // Fill default values
500 $style->post_content = $this->override_defaults( $style->post_content );
501 $style->post_content = wp_parse_args( $style->post_content, $default_values );
502
503 return $style;
504 }
505
506 /**
507 * @param string $orderby
508 * @param string $order
509 * @param int $limit
510 *
511 * @return array
512 */
513 public function get_all( $orderby = 'title', $order = 'ASC', $limit = 99 ) {
514 $post_atts = array(
515 'post_type' => FrmStylesController::$post_type,
516 'post_status' => 'publish',
517 'numberposts' => $limit,
518 'orderby' => $orderby,
519 'order' => $order,
520 );
521
522 $temp_styles = FrmDb::check_cache( json_encode( $post_atts ), 'frm_styles', $post_atts, 'get_posts' );
523
524 if ( ! $temp_styles ) {
525 global $wpdb;
526 // Make sure there wasn't a conflict with the query
527 $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
528 $temp_styles = FrmDb::check_cache( 'frm_backup_style_check', 'frm_styles', $query, 'get_results' );
529
530 if ( ! $temp_styles ) {
531 // Create a new style if there are none
532 $new = $this->get_new();
533 $new->post_title = __( 'Formidable Style', 'formidable' );
534 $new->post_name = $new->post_title;
535 $new->menu_order = 1;
536 $new = $this->save( (array) $new );
537 $this->update( 'default' );
538
539 $post_atts['include'] = $new;
540 $temp_styles = get_posts( $post_atts );
541 }
542 }
543
544 $default_values = $this->get_defaults();
545 $default_style = false;
546 $styles = array();
547
548 foreach ( $temp_styles as $style ) {
549 $this->id = $style->ID;
550
551 if ( $style->menu_order ) {
552 if ( $default_style ) {
553 // Only return one default
554 $style->menu_order = 0;
555 } else {
556 // Check for a default style
557 $default_style = $style->ID;
558 }
559 }
560
561 $style->post_content = FrmAppHelper::maybe_json_decode( $style->post_content );
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 $styles[ $style->ID ] = $style;
568 }//end foreach
569
570 if ( ! $default_style ) {
571 $default_style = reset( $styles );
572 $styles[ $default_style->ID ]->menu_order = 1;
573 }
574
575 return $styles;
576 }
577
578 /**
579 * @param array|null $styles
580 *
581 * @return object|null
582 */
583 public function get_default_style( $styles = null ) {
584 if ( ! isset( $styles ) ) {
585 $styles = $this->get_all( 'menu_order', 'DESC', 1 );
586 }
587
588 foreach ( $styles as $style ) {
589 if ( $style->menu_order ) {
590 return $style;
591 }
592 }
593
594 return null;
595 }
596
597 /**
598 * @param mixed $settings
599 *
600 * @return mixed
601 */
602 public function override_defaults( $settings ) {
603 if ( ! is_array( $settings ) ) {
604 return $settings;
605 }
606
607 $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
608
609 if ( ! isset( $settings['form_desc_size'] ) && isset( $settings['description_font_size'] ) ) {
610 $settings['form_desc_size'] = $settings['description_font_size'];
611 $settings['form_desc_color'] = $settings['description_color'];
612 $settings['title_color'] = $settings['label_color'];
613 }
614
615 if ( ! isset( $settings['section_color'] ) && isset( $settings['label_color'] ) ) {
616 $settings['section_color'] = $settings['label_color'];
617 $settings['section_border_color'] = $settings['border_color'];
618 }
619
620 if ( ! isset( $settings['submit_hover_bg_color'] ) && isset( $settings['submit_bg_color'] ) ) {
621 $settings['submit_hover_bg_color'] = $settings['submit_bg_color'];
622 $settings['submit_hover_color'] = $settings['submit_text_color'];
623 $settings['submit_hover_border_color'] = $settings['submit_border_color'];
624
625 $settings['submit_active_bg_color'] = $settings['submit_bg_color'];
626 $settings['submit_active_color'] = $settings['submit_text_color'];
627 $settings['submit_active_border_color'] = $settings['submit_border_color'];
628 }
629
630 return apply_filters( 'frm_override_default_styles', $settings );
631 }
632
633 /**
634 * @return array
635 */
636 public function get_defaults() {
637 $defaults = array(
638 'theme_css' => 'ui-lightness',
639 'theme_name' => 'UI Lightness',
640
641 'center_form' => '',
642 'form_width' => '100%',
643 'form_align' => 'left',
644 'direction' => is_rtl() ? 'rtl' : 'ltr',
645 'fieldset' => '0px',
646 'fieldset_color' => '000000',
647 'fieldset_padding' => '0px 0px 15px 0px',
648 'fieldset_bg_color' => '',
649
650 'title_size' => '40px',
651 'title_color' => '444444',
652 'title_margin_top' => '10px',
653 'title_margin_bottom' => '60px',
654 'form_desc_size' => '14px',
655 'form_desc_color' => '98A2B3',
656 'form_desc_margin_top' => '10px',
657 'form_desc_margin_bottom' => '25px',
658 'form_desc_padding' => '0px',
659
660 'font' => '',
661 'font_size' => '15px',
662 'label_color' => '344054',
663 'weight' => 'normal',
664 'position' => 'none',
665 'align' => 'left',
666 'width' => '150px',
667 'required_color' => 'F04438',
668 'required_weight' => 'bold',
669 'label_padding' => '0px 0px 5px 0px',
670
671 'description_font_size' => '12px',
672 'description_color' => '667085',
673 'description_weight' => 'normal',
674 'description_style' => 'normal',
675 'description_align' => 'left',
676 'description_margin' => '0px',
677
678 'field_font_size' => '14px',
679 'field_height' => '36px',
680 'line_height' => 'normal',
681 'field_width' => '100%',
682 'auto_width' => false,
683 'field_pad' => '8px 12px',
684 'field_margin' => '20px',
685 'field_weight' => 'normal',
686 'text_color' => '1D2939',
687 // 'border_color_hv' => 'cccccc',
688 'border_color' => 'D0D5DD',
689 'field_border_width' => '1px',
690 'field_border_style' => 'solid',
691
692 'bg_color' => 'ffffff',
693 // 'bg_color_hv' => 'ffffff',
694 'remove_box_shadow' => '',
695 'bg_color_active' => 'ffffff',
696 'border_color_active' => '4199FD',
697 'remove_box_shadow_active' => '',
698 'text_color_error' => '444444',
699 'bg_color_error' => 'ffffff',
700 'border_color_error' => 'F04438',
701 'border_width_error' => '1px',
702 'border_style_error' => 'solid',
703 'bg_color_disabled' => 'F9FAFB',
704 'border_color_disabled' => 'D0D5DD',
705 'text_color_disabled' => '667085',
706
707 'radio_align' => 'block',
708 'check_align' => 'block',
709 'check_font_size' => '14px',
710 'check_label_color' => '1D2939',
711 'check_weight' => 'normal',
712
713 'section_font_size' => '18px',
714 'section_color' => '344054',
715 'section_weight' => 'bold',
716 'section_pad' => '32px 0px 3px 0px',
717 'section_mar_top' => '30px',
718 'section_mar_bottom' => '30px',
719 'section_bg_color' => '',
720 'section_border_color' => 'EAECF0',
721 'section_border_width' => '1px',
722 'section_border_style' => 'solid',
723 'section_border_loc' => '-top',
724 'collapse_icon' => '6',
725 'collapse_pos' => 'after',
726 'repeat_icon' => '1',
727 'repeat_icon_color' => 'ffffff',
728
729 'submit_style' => false,
730 'submit_font_size' => '14px',
731 'submit_width' => 'auto',
732 'submit_height' => 'auto',
733 'submit_bg_color' => '4199FD',
734 'submit_border_color' => '4199FD',
735 'submit_border_width' => '1px',
736 'submit_text_color' => 'ffffff',
737 'submit_weight' => 'normal',
738 'submit_border_radius' => '8px',
739 'submit_bg_img' => '',
740 'submit_margin' => '10px',
741 'submit_padding' => '8px 16px',
742 'submit_shadow_color' => 'eeeeee',
743 'submit_hover_bg_color' => '3680D3',
744 'submit_hover_color' => 'ffffff',
745 'submit_hover_border_color' => '3680D3',
746 'submit_active_bg_color' => '3680D3',
747 'submit_active_color' => 'ffffff',
748 'submit_active_border_color' => '3680D3',
749
750 'border_radius' => '8px',
751 'error_bg' => 'FEE4E2',
752 'error_border' => 'F5B8AA',
753 'error_text' => 'F04438',
754 'error_font_size' => '14px',
755
756 'success_bg_color' => 'DFF0D8',
757 'success_border_color' => 'D6E9C6',
758 'success_text_color' => '468847',
759 'success_font_size' => '14px',
760
761 'important_style' => false,
762
763 'progress_bg_color' => 'EAECF0',
764 'progress_color' => '1D2939',
765 'progress_active_bg_color' => '4199FD',
766 'progress_active_color' => 'ffffff',
767 'progress_border_color' => 'EAECF0',
768 'progress_border_size' => '1px',
769 'progress_size' => '30px',
770 'custom_css' => '',
771 'use_base_font_size' => false,
772 'base_font_size' => '15px',
773 'field_shape_type' => 'rounded-corner',
774
775 'enable_style_custom_css' => false,
776 'single_style_custom_css' => '',
777 );
778
779 return apply_filters( 'frm_default_style_settings', $defaults );
780 }
781
782 /**
783 * Get a name attribute value for a style setting input.
784 *
785 * @param string $field_name
786 * @param string $post_field
787 *
788 * @return string
789 */
790 public function get_field_name( $field_name, $post_field = 'post_content' ) {
791 return 'frm_style_setting' . ( $post_field ? '[' . $post_field . ']' : '' ) . '[' . $field_name . ']';
792 }
793
794 /**
795 * @return array
796 */
797 public static function get_bold_options() {
798 return array(
799 100 => __( 'Thin', 'formidable' ),
800 200 => __( 'Extra Light', 'formidable' ),
801 300 => __( 'Light', 'formidable' ),
802 'normal' => __( 'Regular', 'formidable' ),
803 500 => __( 'Medium', 'formidable' ),
804 600 => __( 'Semi Bold', 'formidable' ),
805 'bold' => __( 'Bold', 'formidable' ),
806 800 => __( 'Extra Bold', 'formidable' ),
807 900 => __( 'Black', 'formidable' ),
808 );
809 }
810
811 /**
812 * Don't let imbalanced font families ruin the whole stylesheet.
813 *
814 * @param string $value
815 *
816 * @return string
817 */
818 public function force_balanced_quotation( $value ) {
819 $balanced_characters = array( '"', "'" );
820
821 foreach ( $balanced_characters as $char ) {
822 $char_count = substr_count( $value, $char );
823 $is_balanced = $char_count % 2 === 0;
824
825 if ( $is_balanced ) {
826 continue;
827 }
828
829 if ( $value && $char === $value[ strlen( $value ) - 1 ] ) {
830 $value = $char . $value;
831 } else {
832 $value .= $char;
833 }
834 }
835
836 return $value;
837 }
838
839 /**
840 * Get the default template style
841 *
842 * @since 6.14
843 *
844 * @param int|string $style_id The post type "frm_styles" ID.
845 *
846 * @return string The json encoded template data
847 */
848 public function get_default_template_style( $style_id ) {
849 $default_template = get_post_meta( (int) $style_id, $this->default_template_style_meta_name, true );
850
851 if ( ! $default_template ) {
852 return FrmAppHelper::prepare_and_encode( $this->get_defaults() );
853 }
854
855 return $default_template;
856 }
857 }
858