PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.2.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.2.1
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 / helpers / FrmStylesHelper.php

FrmStylesHelper.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.2.1, at classes/helpers/FrmStylesHelper.php

701 lines 19.2 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 FrmStylesHelper {
7
8 public static function get_upload_base() {
9 $uploads = wp_upload_dir();
10 if ( is_ssl() && ! preg_match( '/^https:\/\/.*\..*$/', $uploads['baseurl'] ) ) {
11 $uploads['baseurl'] = str_replace( 'http://', 'https://', $uploads['baseurl'] );
12 }
13
14 return $uploads;
15 }
16
17 /**
18 * Called from the admin header.
19 *
20 * @since 4.0
21 */
22 public static function save_button() {
23 ?>
24 <input type="submit" name="submit" class="button button-primary frm-button-primary" value="<?php esc_attr_e( 'Update', 'formidable' ); ?>" />
25 <?php
26 }
27
28 /**
29 * @since 2.05
30 */
31 public static function get_css_label_positions() {
32 return array(
33 'none' => __( 'top', 'formidable' ),
34 'left' => __( 'left', 'formidable' ),
35 'right' => __( 'right', 'formidable' ),
36 'no_label' => __( 'none', 'formidable' ),
37 'inside' => __( 'inside', 'formidable' ),
38 );
39 }
40
41 public static function get_single_label_positions() {
42 return array(
43 'top' => __( 'Top', 'formidable' ),
44 'left' => __( 'Left', 'formidable' ),
45 'right' => __( 'Right', 'formidable' ),
46 'inline' => __( 'Inline (left without a set width)', 'formidable' ),
47 'none' => __( 'None', 'formidable' ),
48 'hidden' => __( 'Hidden (but leave the space)', 'formidable' ),
49 'inside' => __( 'Placeholder inside the field', 'formidable' ),
50 );
51 }
52
53 public static function minus_icons() {
54 return array(
55 0 => array(
56 '-' => '62e',
57 '+' => '62f',
58 ),
59 1 => array(
60 '-' => '600',
61 '+' => '602',
62 ),
63 2 => array(
64 '-' => '604',
65 '+' => '603',
66 ),
67 3 => array(
68 '-' => '633',
69 '+' => '632',
70 ),
71 4 => array(
72 '-' => '613',
73 '+' => '60f',
74 ),
75 );
76 }
77
78 public static function arrow_icons() {
79 $minus_icons = self::minus_icons();
80
81 return array(
82 6 => array(
83 '-' => '62d',
84 '+' => '62a',
85 ),
86 0 => array(
87 '-' => '60d',
88 '+' => '609',
89 ),
90 1 => array(
91 '-' => '60e',
92 '+' => '60c',
93 ),
94 2 => array(
95 '-' => '630',
96 '+' => '631',
97 ),
98 3 => array(
99 '-' => '62b',
100 '+' => '628',
101 ),
102 4 => array(
103 '-' => '62c',
104 '+' => '629',
105 ),
106 5 => array(
107 '-' => '635',
108 '+' => '634',
109 ),
110 'p0' => $minus_icons[0],
111 'p1' => $minus_icons[1],
112 'p2' => $minus_icons[2],
113 'p3' => $minus_icons[3],
114 'p4' => $minus_icons[4],
115 );
116 }
117
118 /**
119 * @since 2.0
120 * @return string The class for this icon.
121 */
122 public static function icon_key_to_class( $key, $icon = '+', $type = 'arrow' ) {
123 if ( 'arrow' === $type && is_numeric( $key ) ) {
124 //frm_arrowup6_icon
125 $arrow = array(
126 '-' => 'down',
127 '+' => 'up',
128 );
129 $class = 'frm_arrow' . $arrow[ $icon ];
130 } else {
131 //frm_minus1_icon
132 $key = str_replace( 'p', '', $key );
133 $plus = array(
134 '-' => 'minus',
135 '+' => 'plus',
136 );
137 $class = 'frm_' . $plus[ $icon ];
138 }
139
140 if ( $key ) {
141 $class .= $key;
142 }
143 $class .= '_icon';
144
145 return $class;
146 }
147
148 /**
149 * @param WP_Post $style
150 * @param FrmStyle $frm_style
151 * @param string $type
152 * @return void
153 */
154 public static function bs_icon_select( $style, $frm_style, $type = 'arrow' ) {
155 $function_name = $type . '_icons';
156 $icons = self::$function_name();
157 unset( $function_name );
158
159 $name = 'arrow' === $type ? 'collapse_icon' : 'repeat_icon';
160 ?>
161 <div class="btn-group" id="frm_<?php echo esc_attr( $name ); ?>_select">
162 <button class="multiselect dropdown-toggle btn btn-default" data-toggle="dropdown" type="button">
163 <?php FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $style->post_content[ $name ], '+', $type ) ); ?>
164 <?php FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $style->post_content[ $name ], '-', $type ) ); ?>
165 <b class="caret"></b>
166 </button>
167 <ul class="multiselect-container frm-dropdown-menu">
168 <?php foreach ( $icons as $key => $icon ) { ?>
169 <li <?php echo ( $style->post_content['collapse_icon'] == $key ) ? 'class="active"' : ''; ?>>
170 <a href="javascript:void(0);">
171 <label>
172 <input type="radio" value="<?php echo esc_attr( $key ); ?>" name="<?php echo esc_attr( $frm_style->get_field_name( $name ) ); ?>" <?php checked( $style->post_content[ $name ], $key ); ?> />
173 <span>
174 <?php
175 FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $key, '+', $type ) );
176 FrmAppHelper::icon_by_class( 'frmfont ' . self::icon_key_to_class( $key, '-', $type ) );
177 ?>
178 </span>
179 </label>
180 </a>
181 </li>
182 <?php } ?>
183 </ul>
184 </div>
185 <?php
186 }
187
188 public static function hex2rgb( $hex ) {
189 $hex = str_replace( '#', '', $hex );
190
191 list( $r, $g, $b ) = sscanf( $hex, '%02x%02x%02x' );
192
193 $rgb = array( $r, $g, $b );
194
195 return implode( ',', $rgb );
196 }
197
198 /**
199 * @since 4.0
200 */
201 public static function hex2rgba( $hex, $a ) {
202 $rgb = self::hex2rgb( $hex );
203
204 return 'rgba(' . $rgb . ',' . $a . ')';
205 }
206
207 /**
208 * @since 6.0
209 *
210 * @param string $rgba
211 * @return string
212 */
213 private static function rgb_to_hex( $rgba ) {
214 if ( strpos( $rgba, '#' ) === 0 ) {
215 return $rgba;
216 }
217 preg_match( '/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i', $rgba, $by_color );
218 return sprintf( '%02x%02x%02x', $by_color[1], $by_color[2], $by_color[3] );
219 }
220
221 /**
222 * @param $hex string - The original color in hex format #ffffff
223 * @param $steps integer - should be between -255 and 255. Negative = darker, positive = lighter
224 *
225 * @since 2.3
226 */
227 public static function adjust_brightness( $hex, $steps ) {
228 $steps = max( - 255, min( 255, $steps ) );
229
230 if ( 0 === strpos( $hex, 'rgba(' ) ) {
231 $rgba = str_replace( ')', '', str_replace( 'rgba(', '', $hex ) );
232 list ( $r, $g, $b, $a ) = array_map( 'trim', explode( ',', $rgba ) );
233 $r = max( 0, min( 255, $r + $steps ) );
234 $g = max( 0, min( 255, $g + $steps ) );
235 $b = max( 0, min( 255, $b + $steps ) );
236 return 'rgba(' . $r . ',' . $g . ',' . $b . ',' . $a . ')';
237 }
238
239 // Normalize into a six character long hex string
240 $hex = str_replace( '#', '', $hex );
241 self::fill_hex( $hex );
242
243 // Split into three parts: R, G and B
244 $color_parts = str_split( $hex, 2 );
245 $return = '#';
246
247 foreach ( $color_parts as $color ) {
248 $color = hexdec( $color ); // Convert to decimal
249 $color = max( 0, min( 255, $color + $steps ) ); // Adjust color
250 $return .= str_pad( dechex( $color ), 2, '0', STR_PAD_LEFT ); // Make two char hex code
251 }
252
253 return $return;
254 }
255
256 /**
257 * @since 6.0
258 *
259 * @param string $color
260 * @return int
261 */
262 public static function get_color_brightness( $color ) {
263 if ( 0 === strpos( $color, 'rgb' ) ) {
264 $color = self::rgb_to_hex( $color );
265 }
266
267 self::fill_hex( $color );
268
269 $c_r = hexdec( substr( $color, 0, 2 ) );
270 $c_g = hexdec( substr( $color, 2, 2 ) );
271 $c_b = hexdec( substr( $color, 4, 2 ) );
272 $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
273
274 return $brightness;
275 }
276
277 /**
278 * Change a 3 character hex color to a 6 character one.
279 *
280 * @since 6.0
281 *
282 * @return array
283 */
284 private static function fill_hex( &$color ) {
285 if ( 3 === strlen( $color ) ) {
286 $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
287 }
288 }
289
290 /**
291 * @since 4.05.02
292 */
293 public static function get_css_vars( $vars = array() ) {
294 $vars = apply_filters( 'frm_css_vars', $vars );
295 return array_unique( $vars );
296 }
297
298 /**
299 * @since 4.05.02
300 */
301 public static function output_vars( $settings, $defaults = array(), $vars = array() ) {
302 if ( empty( $vars ) ) {
303 $vars = self::get_css_vars( array_keys( $settings ) );
304 }
305 $remove = array( 'remove_box_shadow', 'remove_box_shadow_active', 'theme_css', 'theme_name', 'theme_selector', 'important_style', 'submit_style', 'collapse_icon', 'center_form', 'custom_css', 'style_class', 'submit_bg_img', 'change_margin', 'repeat_icon' );
306 $vars = array_diff( $vars, $remove );
307
308 foreach ( $vars as $var ) {
309 if ( ! isset( $settings[ $var ] ) ) {
310 continue;
311 }
312 if ( ! isset( $defaults[ $var ] ) ) {
313 $defaults[ $var ] = '';
314 }
315 $show = empty( $defaults ) || ( $settings[ $var ] !== '' && $settings[ $var ] !== $defaults[ $var ] );
316 if ( $show ) {
317 echo '--' . esc_html( str_replace( '_', '-', $var ) ) . ':' . ( $var === 'font' ? FrmAppHelper::kses( $settings[ $var ] ) : esc_html( $settings[ $var ] ) ) . ';'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
318 }
319 }
320 }
321
322 /**
323 * @since 2.3
324 *
325 * @param WP_Post $style
326 * @return array
327 */
328 public static function get_settings_for_output( $style ) {
329 if ( self::previewing_style() ) {
330 $frm_style = new FrmStyle();
331 if ( isset( $_POST['frm_style_setting'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
332
333 // Sanitizing is done later.
334 $posted = wp_unslash( $_POST['frm_style_setting'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
335 if ( ! is_array( $posted ) ) {
336 $posted = json_decode( $posted, true );
337 FrmAppHelper::format_form_data( $posted );
338 $settings = $frm_style->sanitize_post_content( $posted['frm_style_setting']['post_content'] );
339 $style_name = sanitize_title( $posted['style_name'] );
340 } else {
341 $settings = $frm_style->sanitize_post_content( $posted['post_content'] );
342 $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_title' );
343 }
344 } else {
345 $settings = $frm_style->sanitize_post_content( wp_unslash( $_GET ) );
346 $style_name = FrmAppHelper::get_param( 'style_name', '', 'get', 'sanitize_title' );
347 }
348
349 FrmAppHelper::sanitize_value( 'sanitize_text_field', $settings );
350
351 $settings['style_class'] = '';
352 if ( ! empty( $style_name ) ) {
353 $settings['style_class'] = $style_name . '.';
354 }
355 } else {
356 $settings = $style->post_content;
357 $settings['style_class'] = 'frm_style_' . $style->post_name . '.';
358 }
359
360 $settings['style_class'] .= 'with_frm_style';
361 $settings['font'] = stripslashes( $settings['font'] );
362 $settings['change_margin'] = self::description_margin_for_screensize( $settings['width'] );
363
364 $checkbox_opts = array( 'important_style', 'auto_width', 'submit_style', 'collapse_icon', 'center_form' );
365 foreach ( $checkbox_opts as $opt ) {
366 if ( ! isset( $settings[ $opt ] ) ) {
367 $settings[ $opt ] = 0;
368 }
369 }
370
371 self::prepare_color_output( $settings );
372
373 $settings['field_height'] = $settings['field_height'] === '' ? 'auto' : $settings['field_height'];
374 $settings['field_width'] = $settings['field_width'] === '' ? 'auto' : $settings['field_width'];
375 $settings['auto_width'] = $settings['auto_width'] ? 'auto' : $settings['field_width'];
376 $settings['box_shadow'] = ! empty( $settings['remove_box_shadow'] ) ? 'none' : '0 1px 1px rgba(0, 0, 0, 0.075) inset';
377
378 if ( ! isset( $settings['repeat_icon'] ) ) {
379 $settings['repeat_icon'] = 1;
380 }
381
382 return $settings;
383 }
384
385 /**
386 * @since 2.3
387 */
388 public static function prepare_color_output( &$settings, $allow_transparent = true ) {
389 $colors = self::allow_color_override();
390 foreach ( $colors as $css => $opts ) {
391 if ( $css === 'transparent' && ! $allow_transparent ) {
392 $css = '';
393 }
394 foreach ( $opts as $opt ) {
395 self::get_color_output( $css, $settings[ $opt ] );
396 }
397 }
398 }
399
400 /**
401 * @since 2.3
402 */
403 private static function allow_color_override() {
404 $frm_style = new FrmStyle();
405 $colors = $frm_style->get_color_settings();
406
407 $transparent = array(
408 'fieldset_color',
409 'fieldset_bg_color',
410 'bg_color',
411 'bg_color_active',
412 'bg_color_disabled',
413 'section_bg_color',
414 'error_bg',
415 'success_bg_color',
416 'progress_bg_color',
417 'progress_active_bg_color',
418 'submit_border_color',
419 'submit_hover_border_color',
420 'submit_active_border_color',
421 'submit_hover_bg_color',
422 'submit_active_bg_color',
423 'success_bg_color',
424 );
425
426 return array(
427 'transparent' => $transparent,
428 '' => array_diff( $colors, $transparent ),
429 );
430 }
431
432 /**
433 * @since 2.3
434 */
435 private static function get_color_output( $default, &$color ) {
436 $color = trim( $color );
437 if ( empty( $color ) ) {
438 $color = $default;
439 } elseif ( false !== strpos( $color, 'rgb(' ) ) {
440 $color = str_replace( 'rgb(', 'rgba(', $color );
441 $color = str_replace( ')', ',1)', $color );
442 } elseif ( strpos( $color, '#' ) === false && false === strpos( $color, 'rgba(' ) ) {
443 $color = '#' . $color;
444 }
445 }
446
447 /**
448 * If left/right label is over a certain size,
449 * adjust the field description margin at a different screen size
450 *
451 * @since 2.3
452 */
453 private static function description_margin_for_screensize( $width ) {
454 $temp_label_width = str_replace( 'px', '', $width );
455 $change_margin = false;
456 if ( $temp_label_width >= 230 ) {
457 $change_margin = '800px';
458 } elseif ( $width >= 215 ) {
459 $change_margin = '700px';
460 } elseif ( $width >= 180 ) {
461 $change_margin = '650px';
462 }
463
464 return $change_margin;
465 }
466
467 /**
468 * @since 2.3
469 *
470 * @return bool
471 */
472 public static function previewing_style() {
473 $ajax_change = isset( $_POST['action'] ) && $_POST['action'] === 'frm_change_styling' && isset( $_POST['frm_style_setting'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
474
475 return $ajax_change || isset( $_GET['flat'] );
476 }
477
478 /**
479 * @since 5.5.1
480 * @return void
481 */
482 public static function maybe_include_font_icon_css() {
483 $signature_add_on_is_active = class_exists( 'FrmSigAppHelper', false );
484
485 if ( ! FrmAppHelper::pro_is_installed() && ! $signature_add_on_is_active ) {
486 // If Pro and Signatures are both not active, there is no need to include the font icon CSS in lite.
487 return;
488 }
489
490 $pro_version_will_handle_loading = false;
491
492 if ( class_exists( 'FrmProDb', false ) ) {
493 $pro_version_that_includes_font_icons_css = '5.5.1';
494
495 // Include font icons in Lite for backward compatibility with older version of Pro.
496 $pro_version_will_handle_loading = version_compare( FrmProDb::$plug_version, $pro_version_that_includes_font_icons_css, '>=' );
497 }
498
499 $load_it_here = false;
500 if ( ! $pro_version_will_handle_loading ) {
501 // If Pro is not handling it, we still need to include it for the Signature add on.
502 $load_it_here = $signature_add_on_is_active;
503 }
504
505 if ( $load_it_here ) {
506 readfile( FrmAppHelper::plugin_path() . '/css/font_icons.css' );
507 }
508 }
509
510 /**
511 * Get the URL for the Styler page list view (where you can assign styles to a form and view style templates) for a target form.
512 *
513 * @since 6.0
514 *
515 * @param string|int $form_id
516 * @return string
517 */
518 public static function get_list_url( $form_id ) {
519 return admin_url( 'admin.php?page=formidable-styles&form=' . absint( $form_id ) );
520 }
521
522 /**
523 * Get a link to edit a target style post object in the visual styler.
524 *
525 * @param WP_Post|stdClass $style
526 * @param string|int $form_id Used for the back button and preview form target.
527 * @return string
528 */
529 public static function get_edit_url( $style, $form_id = 0 ) {
530 $query_args = array(
531 'page' => 'formidable-styles',
532 'frm_action' => 'edit',
533 'id' => $style->ID,
534 );
535
536 if ( $form_id ) {
537 // We include &form_id for the back button to know where to point to.
538 $query_args['form'] = $form_id;
539 }
540
541 return add_query_arg( $query_args, admin_url( 'admin.php' ) );
542 }
543
544 /**
545 * Get a count of the number of forms assigned to a target style ID.
546 * All unassigned forms are included in the count for the default style.
547 *
548 * @since 6.0
549 *
550 * @param string|int $style_id
551 * @param bool $is_default
552 * @return int
553 */
554 public static function get_form_count_for_style( $style_id, $is_default ) {
555 $serialized = serialize( array( 'custom_style' => (string) $style_id ) );
556 $substring = substr( $serialized, 5, -1 ); // Chop off the "a:1:{" from the front and the "}" from the back.
557 $number_of_forms = FrmDb::get_count(
558 'frm_forms',
559 array(
560 'status' => 'published',
561 'options LIKE' => $substring,
562 )
563 );
564
565 if ( ! $is_default ) {
566 // Exit early as the rest of the code is about including the default count.
567 return $number_of_forms;
568 }
569
570 $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' );
571 $number_of_forms += self::get_default_style_count( $style_id, $conversational_style_id );
572
573 return $number_of_forms;
574 }
575
576 /**
577 * Get the number of forms that use the default style.
578 *
579 * @since 6.0
580 *
581 * @param string|int $style_id
582 * @param mixed $conversational_style_id
583 * @return int
584 */
585 private static function get_default_style_count( $style_id, $conversational_style_id ) {
586 $substrings = array_map(
587 function( $value ) {
588 $substring = serialize( array( 'custom_style' => $value ) );
589 return substr( $substring, 5, -1 );
590 },
591 array( '1', 1 )
592 );
593 $where = array(
594 'status' => 'published',
595 0 => array(
596 'options NOT LIKE' => 'custom_style',
597 'or' => 1,
598 'options LIKE' => $substrings,
599 ),
600 );
601
602 if ( $conversational_style_id ) {
603 // When a conversational style is set, check for it in the query by wrapping the where and adding a conversational option check.
604 $is_conversational_style = (int) $style_id === (int) $conversational_style_id;
605 $where[0] = array(
606 // The chat option doesn't exist if it isn't on.
607 ( $is_conversational_style ? 'options LIKE' : 'options NOT LIKE' ) => ';s:4:"chat";',
608 $where[0],
609 );
610 }
611
612 return FrmDb::get_count( 'frm_forms', $where );
613 }
614
615 /**
616 * @deprecated 3.01
617 * @codeCoverageIgnore
618 */
619 public static function get_sigle_label_postitions() {
620 return FrmDeprecated::get_sigle_label_postitions();
621 }
622
623 /**
624 * @deprecated 3.02.03
625 * @codeCoverageIgnore
626 */
627 public static function jquery_themes() {
628 return FrmDeprecated::jquery_themes();
629 }
630
631 /**
632 * @deprecated 3.02.03
633 * @codeCoverageIgnore
634 */
635 public static function jquery_css_url( $theme_css ) {
636 return FrmDeprecated::jquery_css_url( $theme_css );
637 }
638
639 /**
640 * @deprecated 3.02.03
641 * @codeCoverageIgnore
642 */
643 public static function enqueue_jquery_css() {
644 FrmDeprecated::enqueue_jquery_css();
645 }
646
647 /**
648 * @deprecated 3.02.03
649 * @codeCoverageIgnore
650 */
651 public static function get_form_for_page() {
652 return FrmDeprecated::get_form_for_page();
653 }
654
655 /**
656 * @since 4.0
657 * @deprecated 6.0 The style menu is no longer used in the styler.
658 *
659 * @param string $active
660 * @return string
661 */
662 public static function get_style_menu( $active = '' ) {
663 _deprecated_function( __METHOD__, '6.0' );
664 return '';
665 }
666
667 /**
668 * @deprecated 6.0 The style menu is no longer used in the styler.
669 *
670 * @param string $active
671 * @return void
672 */
673 public static function style_menu( $active = '' ) {
674 _deprecated_function( __METHOD__, '6.0' );
675 }
676
677 /**
678 * Either get the heading or the style switcher.
679 *
680 * @since 4.0
681 * @deprecated 6.0 The style switcher was replaced with a form switcher and is no longer used.
682 *
683 * @param array $atts
684 * @return void
685 */
686 public static function styler_switcher( $atts ) {
687 _deprecated_function( __METHOD__, '6.0' );
688 }
689
690 /**
691 * @since 4.0
692 * @deprecated 6.0 The styler now uses the Embed/Preview/Update header. It uses the same save button as other pages with Form tabs.
693 *
694 * @param array $atts
695 * @return void
696 */
697 public static function styler_save_button( $atts ) {
698 _deprecated_function( __METHOD__, '6.0' );
699 }
700 }
701