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

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