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

618 lines 19.3 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 public $number = false; // Unique ID number of the current instance.
8 public $id = 0; // the id of the post
9
10 /**
11 * @param int|string $id The id of the stylsheet or 'default'
12 */
13 public function __construct( $id = 0 ) {
14 $this->id = $id;
15 }
16
17 public function get_new() {
18 $this->id = 0;
19
20 $max_slug_value = 2147483647;
21 $min_slug_value = 37; // we want to have at least 2 characters in the slug
22 $key = base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
23
24 $style = array(
25 'post_type' => FrmStylesController::$post_type,
26 'ID' => '',
27 'post_title' => __( 'New Style', 'formidable' ),
28 'post_name' => $key,
29 'post_content' => $this->get_defaults(),
30 'menu_order' => '',
31 'post_status' => 'publish',
32 );
33
34 return (object) $style;
35 }
36
37 public function save( $settings ) {
38 return FrmDb::save_settings( $settings, 'frm_styles' );
39 }
40
41 public function duplicate( $id ) {
42 // duplicating is a pro feature
43 }
44
45 public function update( $id = 'default' ) {
46 $all_instances = $this->get_all();
47
48 if ( empty( $id ) ) {
49 $new_style = (array) $this->get_new();
50 $all_instances[] = $new_style;
51 }
52
53 $action_ids = array();
54
55 foreach ( $all_instances as $number => $new_instance ) {
56 $new_instance = (array) $new_instance;
57 $this->id = $new_instance['ID'];
58 // phpcs:ignore WordPress.Security.NonceVerification.Missing
59 if ( $id != $this->id || ! $_POST || ! isset( $_POST['frm_style_setting'] ) ) {
60 $all_instances[ $number ] = $new_instance;
61
62 // phpcs:ignore WordPress.Security.NonceVerification.Missing
63 if ( $new_instance['menu_order'] && $_POST && empty( $_POST['prev_menu_order'] ) && isset( $_POST['frm_style_setting']['menu_order'] ) ) {
64 // this style was set to default, so remove default setting on previous default style
65 $new_instance['menu_order'] = 0;
66 $action_ids[] = $this->save( $new_instance );
67 }
68
69 // don't continue if not saving this style
70 continue;
71 }
72
73 $new_instance['post_title'] = isset( $_POST['frm_style_setting']['post_title'] ) ? sanitize_text_field( wp_unslash( $_POST['frm_style_setting']['post_title'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
74 $new_instance['post_content'] = isset( $_POST['frm_style_setting']['post_content'] ) ? $this->sanitize_post_content( $this->unslash_post_content( $_POST['frm_style_setting']['post_content'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
75 $new_instance['post_type'] = FrmStylesController::$post_type;
76 $new_instance['post_status'] = 'publish';
77 $new_instance['menu_order'] = isset( $_POST['frm_style_setting']['menu_order'] ) ? absint( $_POST['frm_style_setting']['menu_order'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
78
79 if ( empty( $id ) ) {
80 $new_instance['post_name'] = $new_instance['post_title'];
81 }
82
83 $default_settings = $this->get_defaults();
84
85 foreach ( $default_settings as $setting => $default ) {
86 if ( ! isset( $new_instance['post_content'][ $setting ] ) ) {
87 $new_instance['post_content'][ $setting ] = $default;
88 }
89
90 if ( $this->is_color( $setting ) ) {
91 $color_val = $new_instance['post_content'][ $setting ];
92 if ( $color_val !== '' && 0 === strpos( $color_val, 'rgb' ) ) {
93 // maybe sanitize if invalid rgba value is entered
94 $this->maybe_sanitize_rgba_value( $color_val );
95 }
96 $new_instance['post_content'][ $setting ] = str_replace( '#', '', $color_val );
97 } elseif ( in_array( $setting, array( 'submit_style', 'important_style', 'auto_width' ) )
98 && ! isset( $new_instance['post_content'][ $setting ] )
99 ) {
100 $new_instance['post_content'][ $setting ] = 0;
101 } elseif ( $setting == 'font' ) {
102 $new_instance['post_content'][ $setting ] = $this->force_balanced_quotation( $new_instance['post_content'][ $setting ] );
103 }
104 }
105
106 $all_instances[ $number ] = $new_instance;
107
108 $action_ids[] = $this->save( $new_instance );
109
110 }
111
112 $this->save_settings();
113
114 return $action_ids;
115 }
116
117 /**
118 * Sanitize custom color values and convert it to valid one filling missing values.
119 *
120 * @since 5.3.2
121 *
122 * @param string $color_val, The color value, by reference.
123 * @return void
124 */
125 private function maybe_sanitize_rgba_value( &$color_val ) {
126 if ( preg_match( '/(rgb|rgba)\(/', $color_val ) !== 1 ) {
127 return;
128 }
129
130 $color_val = trim( $color_val );
131 $patterns = array( '/rgba\((\s*\d+\s*,){3}[[0-1]\.]+\)/', '/rgb\((\s*\d+\s*,){2}\s*[\d]+\)/' );
132 foreach ( $patterns as $pattern ) {
133 if ( preg_match( $pattern, $color_val ) === 1 ) {
134 return;
135 }
136 }
137
138 if ( substr( $color_val, -1 ) !== ')' ) {
139 $color_val .= ')';
140 }
141
142 $color_rgba = substr( $color_val, strpos( $color_val, '(' ) + 1, strlen( $color_val ) - strpos( $color_val, '(' ) - 2 );
143 $length_of_color_codes = strpos( $color_val, '(' );
144 $new_color_values = array();
145
146 // replace empty values by 0 or 1 (if alpha position).
147 foreach ( explode( ',', $color_rgba ) as $index => $value ) {
148 $new_value = null;
149 $value_is_empty_string = '' === trim( $value ) || '' === $value;
150
151 if ( 3 === $length_of_color_codes || ( $index !== $length_of_color_codes - 1 ) ) {
152 // insert a value for r, g, or b
153 if ( $value < 0 ) {
154 $new_value = 0;
155 } elseif ( $value > 255 ) {
156 $new_value = 255;
157 } elseif ( $value_is_empty_string ) {
158 $new_value = 0;
159 }
160 } else {
161 // insert a value for alpha
162 if ( $value_is_empty_string ) {
163 $new_value = 4 === $length_of_color_codes ? 1 : 0;
164 } elseif ( $value > 1 || $value < 0 ) {
165 $new_value = 1;
166 }
167 }
168
169 $new_color_values[] = null === $new_value ? $value : $new_value;
170 }
171
172 // add more 0s and 1 (if alpha position) if needed.
173 $missing_values = $length_of_color_codes - count( $new_color_values );
174 if ( $missing_values > 1 ) {
175 $insert_values = array_fill( 0, $missing_values - 1, 0 );
176 $last_value = 4 === $length_of_color_codes ? 1 : 0;
177 array_push( $insert_values, $last_value );
178 } elseif ( $missing_values === 1 ) {
179 $insert_values = 4 === $length_of_color_codes ? array( 1 ) : array( 0 );
180 }
181 if ( ! empty( $insert_values ) ) {
182 $new_color_values = array_merge( $new_color_values, $insert_values );
183 }
184
185 $new_color = implode( ',', $new_color_values );
186 $prefix = substr( $color_val, 0, strpos( $color_val, '(' ) + 1 );
187 $new_color = $prefix . $new_color . ')';
188
189 $color_val = $new_color;
190 }
191
192 /**
193 * Unslash everything in post_content but custom_css
194 *
195 * @since 5.0.13
196 *
197 * @param array $settings
198 * @return array
199 */
200 private function unslash_post_content( $settings ) {
201 $custom_css = isset( $settings['custom_css'] ) ? $settings['custom_css'] : '';
202 $settings = wp_unslash( $settings );
203 $settings['custom_css'] = $custom_css;
204 return $settings;
205 }
206
207 /**
208 * @since 5.0.13
209 *
210 * @param array $settings
211 * @return array
212 */
213 public function sanitize_post_content( $settings ) {
214 $defaults = $this->get_defaults();
215 $valid_keys = array_keys( $defaults );
216 $sanitized_settings = array();
217 foreach ( $valid_keys as $key ) {
218 if ( isset( $settings[ $key ] ) ) {
219 $sanitized_settings[ $key ] = sanitize_textarea_field( $settings[ $key ] );
220 } else {
221 $sanitized_settings[ $key ] = $defaults[ $key ];
222 }
223 }
224 return $sanitized_settings;
225 }
226
227 /**
228 * @since 3.01.01
229 */
230 private function is_color( $setting ) {
231 $extra_colors = array( 'error_bg', 'error_border', 'error_text' );
232
233 return strpos( $setting, 'color' ) !== false || in_array( $setting, $extra_colors );
234 }
235
236 /**
237 * @since 3.01.01
238 */
239 public function get_color_settings() {
240 $defaults = $this->get_defaults();
241 $settings = array_keys( $defaults );
242
243 return array_filter( $settings, array( $this, 'is_color' ) );
244 }
245
246 /**
247 * Create static css file
248 */
249 public function save_settings() {
250 $filename = FrmAppHelper::plugin_path() . '/css/custom_theme.css.php';
251 update_option( 'frm_last_style_update', gmdate( 'njGi' ) );
252
253 if ( ! is_file( $filename ) ) {
254 return;
255 }
256
257 $this->clear_cache();
258
259 $css = $this->get_css_content( $filename );
260
261 $create_file = new FrmCreateFile(
262 array(
263 'file_name' => FrmStylesController::get_file_name(),
264 'new_file_path' => FrmAppHelper::plugin_path() . '/css',
265 )
266 );
267 $create_file->create_file( $css );
268
269 update_option( 'frmpro_css', $css, 'no' );
270 set_transient( 'frmpro_css', $css, MONTH_IN_SECONDS );
271 }
272
273 private function get_css_content( $filename ) {
274 $css = '/* ' . __( 'WARNING: Any changes made to this file will be lost when your Formidable settings are updated', 'formidable' ) . ' */' . "\n";
275
276 $saving = true;
277 $frm_style = $this;
278
279 ob_start();
280 include( $filename );
281 $css .= preg_replace( '/\/\*(.|\s)*?\*\//', '', str_replace( array( "\r\n", "\r", "\n", "\t", ' ' ), '', ob_get_contents() ) );
282 ob_end_clean();
283
284 return FrmStylesController::replace_relative_url( $css );
285 }
286
287 private function clear_cache() {
288 $default_post_atts = array(
289 'post_type' => FrmStylesController::$post_type,
290 'post_status' => 'publish',
291 'numberposts' => 99,
292 'orderby' => 'title',
293 'order' => 'ASC',
294 );
295
296 FrmDb::delete_cache_and_transient( json_encode( $default_post_atts ), 'frm_styles' );
297 FrmDb::cache_delete_group( 'frm_styles' );
298 FrmDb::delete_cache_and_transient( 'frmpro_css' );
299 }
300
301 public function destroy( $id ) {
302 return wp_delete_post( $id );
303 }
304
305 public function get_one() {
306 if ( 'default' == $this->id ) {
307 $style = $this->get_default_style();
308 if ( $style ) {
309 $this->id = $style->ID;
310 } else {
311 $this->id = 0;
312 }
313
314 return $style;
315 }
316
317 $style = get_post( $this->id );
318
319 if ( ! $style ) {
320 return $style;
321 }
322
323 $style->post_content = FrmAppHelper::maybe_json_decode( $style->post_content );
324
325 $default_values = $this->get_defaults();
326
327 // fill default values
328 $style->post_content = $this->override_defaults( $style->post_content );
329 $style->post_content = wp_parse_args( $style->post_content, $default_values );
330
331 return $style;
332 }
333
334 public function get_all( $orderby = 'title', $order = 'ASC', $limit = 99 ) {
335 $post_atts = array(
336 'post_type' => FrmStylesController::$post_type,
337 'post_status' => 'publish',
338 'numberposts' => $limit,
339 'orderby' => $orderby,
340 'order' => $order,
341 );
342
343 $temp_styles = FrmDb::check_cache( json_encode( $post_atts ), 'frm_styles', $post_atts, 'get_posts' );
344
345 if ( empty( $temp_styles ) ) {
346 global $wpdb;
347 // make sure there wasn't a conflict with the query
348 $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' );
349 $temp_styles = FrmDb::check_cache( 'frm_backup_style_check', 'frm_styles', $query, 'get_results' );
350
351 if ( empty( $temp_styles ) ) {
352 // create a new style if there are none
353 $new = $this->get_new();
354 $new->post_title = __( 'Formidable Style', 'formidable' );
355 $new->post_name = $new->post_title;
356 $new->menu_order = 1;
357 $new = $this->save( (array) $new );
358 $this->update( 'default' );
359
360 $post_atts['include'] = $new;
361
362 $temp_styles = get_posts( $post_atts );
363 }
364 }
365
366 $default_values = $this->get_defaults();
367 $default_style = false;
368
369 $styles = array();
370 foreach ( $temp_styles as $style ) {
371 $this->id = $style->ID;
372 if ( $style->menu_order ) {
373 if ( $default_style ) {
374 // only return one default
375 $style->menu_order = 0;
376 } else {
377 // check for a default style
378 $default_style = $style->ID;
379 }
380 }
381
382 $style->post_content = FrmAppHelper::maybe_json_decode( $style->post_content );
383
384 // fill default values
385 $style->post_content = $this->override_defaults( $style->post_content );
386 $style->post_content = wp_parse_args( $style->post_content, $default_values );
387
388 $styles[ $style->ID ] = $style;
389 }
390
391 if ( ! $default_style ) {
392 $default_style = reset( $styles );
393
394 $styles[ $default_style->ID ]->menu_order = 1;
395 }
396
397 return $styles;
398 }
399
400 public function get_default_style( $styles = null ) {
401 if ( ! isset( $styles ) ) {
402 $styles = $this->get_all( 'menu_order', 'DESC', 1 );
403 }
404
405 foreach ( $styles as $style ) {
406 if ( $style->menu_order ) {
407 return $style;
408 }
409 }
410 }
411
412 public function override_defaults( $settings ) {
413 if ( ! is_array( $settings ) ) {
414 return $settings;
415 }
416
417 $settings['line_height'] = ( ! isset( $settings['field_height'] ) || $settings['field_height'] == '' || $settings['field_height'] == 'auto' ) ? 'normal' : $settings['field_height'];
418
419 if ( ! isset( $settings['form_desc_size'] ) && isset( $settings['description_font_size'] ) ) {
420 $settings['form_desc_size'] = $settings['description_font_size'];
421 $settings['form_desc_color'] = $settings['description_color'];
422 $settings['title_color'] = $settings['label_color'];
423 }
424
425 if ( ! isset( $settings['section_color'] ) && isset( $settings['label_color'] ) ) {
426 $settings['section_color'] = $settings['label_color'];
427 $settings['section_border_color'] = $settings['border_color'];
428 }
429
430 if ( ! isset( $settings['submit_hover_bg_color'] ) && isset( $settings['submit_bg_color'] ) ) {
431 $settings['submit_hover_bg_color'] = $settings['submit_bg_color'];
432 $settings['submit_hover_color'] = $settings['submit_text_color'];
433 $settings['submit_hover_border_color'] = $settings['submit_border_color'];
434
435 $settings['submit_active_bg_color'] = $settings['submit_bg_color'];
436 $settings['submit_active_color'] = $settings['submit_text_color'];
437 $settings['submit_active_border_color'] = $settings['submit_border_color'];
438 }
439
440 return apply_filters( 'frm_override_default_styles', $settings );
441 }
442
443 public function get_defaults() {
444 $defaults = array(
445 'theme_css' => 'ui-lightness',
446 'theme_name' => 'UI Lightness',
447
448 'center_form' => '',
449 'form_width' => '100%',
450 'form_align' => 'left',
451 'direction' => is_rtl() ? 'rtl' : 'ltr',
452 'fieldset' => '0px',
453 'fieldset_color' => '000000',
454 'fieldset_padding' => '0 0 15px 0',
455 'fieldset_bg_color' => '',
456
457 'title_size' => '40px',
458 'title_color' => '444444',
459 'title_margin_top' => '10px',
460 'title_margin_bottom' => '60px',
461 'form_desc_size' => '14px',
462 'form_desc_color' => '666666',
463 'form_desc_margin_top' => '10px',
464 'form_desc_margin_bottom' => '25px',
465 'form_desc_padding' => '0',
466
467 'font' => '',
468 'font_size' => '15px',
469 'label_color' => '3f4b5b',
470 'weight' => 'normal',
471 'position' => 'none',
472 'align' => 'left',
473 'width' => '150px',
474 'required_color' => 'B94A48',
475 'required_weight' => 'bold',
476 'label_padding' => '0 0 3px 0',
477
478 'description_font_size' => '12px',
479 'description_color' => '666666',
480 'description_weight' => 'normal',
481 'description_style' => 'normal',
482 'description_align' => 'left',
483 'description_margin' => '0',
484
485 'field_font_size' => '14px',
486 'field_height' => '32px',
487 'line_height' => 'normal',
488 'field_width' => '100%',
489 'auto_width' => false,
490 'field_pad' => '6px 10px',
491 'field_margin' => '20px',
492 'field_weight' => 'normal',
493 'text_color' => '555555',
494 //'border_color_hv' => 'cccccc',
495 'border_color' => 'BFC3C8',
496 'field_border_width' => '1px',
497 'field_border_style' => 'solid',
498
499 'bg_color' => 'ffffff',
500 //'bg_color_hv' => 'ffffff',
501 'remove_box_shadow' => '',
502 'bg_color_active' => 'ffffff',
503 'border_color_active' => '66afe9',
504 'remove_box_shadow_active' => '',
505 'text_color_error' => '444444',
506 'bg_color_error' => 'ffffff',
507 'border_color_error' => 'B94A48',
508 'border_width_error' => '1px',
509 'border_style_error' => 'solid',
510 'bg_color_disabled' => 'ffffff',
511 'border_color_disabled' => 'E5E5E5',
512 'text_color_disabled' => 'A1A1A1',
513
514 'radio_align' => 'block',
515 'check_align' => 'block',
516 'check_font_size' => '13px',
517 'check_label_color' => '444444',
518 'check_weight' => 'normal',
519
520 'section_font_size' => '18px',
521 'section_color' => '444444',
522 'section_weight' => 'bold',
523 'section_pad' => '15px 0 3px 0',
524 'section_mar_top' => '15px',
525 'section_mar_bottom' => '30px',
526 'section_bg_color' => '',
527 'section_border_color' => 'e8e8e8',
528 'section_border_width' => '2px',
529 'section_border_style' => 'solid',
530 'section_border_loc' => '-top',
531 'collapse_icon' => '6',
532 'collapse_pos' => 'after',
533 'repeat_icon' => '1',
534 'repeat_icon_color' => 'ffffff',
535
536 'submit_style' => false,
537 'submit_font_size' => '15px',
538 'submit_width' => 'auto',
539 'submit_height' => 'auto',
540 'submit_bg_color' => '579AF6',
541 'submit_border_color' => '579AF6',
542 'submit_border_width' => '1px',
543 'submit_text_color' => 'ffffff',
544 'submit_weight' => 'normal',
545 'submit_border_radius' => '4px',
546 'submit_bg_img' => '',
547 'submit_margin' => '10px',
548 'submit_padding' => '10px 20px',
549 'submit_shadow_color' => 'eeeeee',
550 'submit_hover_bg_color' => 'efefef',
551 'submit_hover_color' => '444444',
552 'submit_hover_border_color' => 'cccccc',
553 'submit_active_bg_color' => 'efefef',
554 'submit_active_color' => '444444',
555 'submit_active_border_color' => 'cccccc',
556
557 'border_radius' => '4px',
558 'error_bg' => 'F2DEDE',
559 'error_border' => 'EBCCD1',
560 'error_text' => 'B94A48',
561 'error_font_size' => '14px',
562
563 'success_bg_color' => 'DFF0D8',
564 'success_border_color' => 'D6E9C6',
565 'success_text_color' => '468847',
566 'success_font_size' => '14px',
567
568 'important_style' => false,
569
570 'progress_bg_color' => 'eaeaea',
571 'progress_active_color' => 'ffffff',
572 'progress_active_bg_color' => '579AF6',
573 'progress_color' => '3f4b5b',
574 'progress_border_color' => 'E5E5E5',
575 'progress_border_size' => '2px',
576 'progress_size' => '30px',
577
578 'custom_css' => '',
579 );
580
581 return apply_filters( 'frm_default_style_settings', $defaults );
582 }
583
584 public function get_field_name( $field_name, $post_field = 'post_content' ) {
585 return 'frm_style_setting' . ( empty( $post_field ) ? '' : '[' . $post_field . ']' ) . '[' . $field_name . ']';
586 }
587
588 public static function get_bold_options() {
589 return array(
590 100 => 100,
591 200 => 200,
592 300 => 300,
593 'normal' => __( 'normal', 'formidable' ),
594 500 => 500,
595 600 => 600,
596 'bold' => __( 'bold', 'formidable' ),
597 800 => 800,
598 900 => 900,
599 );
600 }
601
602 /**
603 * Don't let imbalanced font families ruin the whole stylesheet
604 */
605 public function force_balanced_quotation( $value ) {
606 $balanced_characters = array( '"', "'" );
607 foreach ( $balanced_characters as $char ) {
608 $char_count = substr_count( $value, $char );
609 $is_balanced = $char_count % 2 == 0;
610 if ( ! $is_balanced ) {
611 $value .= $char;
612 }
613 }
614
615 return $value;
616 }
617 }
618