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

707 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 string $hex string The original color in hex format #ffffff.
223 * @param int $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 // Convert to decimal.
249 $color = hexdec( $color );
250 // Adjust color.
251 $color = max( 0, min( 255, $color + $steps ) );
252
253 // Make two char hex code.
254 $return .= str_pad( dechex( $color ), 2, '0', STR_PAD_LEFT );
255 }
256
257 return $return;
258 }
259
260 /**
261 * @since 6.0
262 *
263 * @param string $color
264 * @return int
265 */
266 public static function get_color_brightness( $color ) {
267 if ( 0 === strpos( $color, 'rgb' ) ) {
268 $color = self::rgb_to_hex( $color );
269 }
270
271 self::fill_hex( $color );
272
273 $c_r = hexdec( substr( $color, 0, 2 ) );
274 $c_g = hexdec( substr( $color, 2, 2 ) );
275 $c_b = hexdec( substr( $color, 4, 2 ) );
276 $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
277
278 return $brightness;
279 }
280
281 /**
282 * Change a 3 character hex color to a 6 character one.
283 *
284 * @since 6.0
285 *
286 * @return void
287 */
288 private static function fill_hex( &$color ) {
289 if ( 3 === strlen( $color ) ) {
290 $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
291 }
292 }
293
294 /**
295 * @since 4.05.02
296 */
297 public static function get_css_vars( $vars = array() ) {
298 $vars = apply_filters( 'frm_css_vars', $vars );
299 return array_unique( $vars );
300 }
301
302 /**
303 * @since 4.05.02
304 */
305 public static function output_vars( $settings, $defaults = array(), $vars = array() ) {
306 if ( empty( $vars ) ) {
307 $vars = self::get_css_vars( array_keys( $settings ) );
308 }
309 $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' );
310 $vars = array_diff( $vars, $remove );
311
312 foreach ( $vars as $var ) {
313 if ( ! isset( $settings[ $var ] ) ) {
314 continue;
315 }
316 if ( ! isset( $defaults[ $var ] ) ) {
317 $defaults[ $var ] = '';
318 }
319 $show = empty( $defaults ) || ( $settings[ $var ] !== '' && $settings[ $var ] !== $defaults[ $var ] );
320 if ( $show ) {
321 echo '--' . esc_html( str_replace( '_', '-', $var ) ) . ':' . ( $var === 'font' ? FrmAppHelper::kses( $settings[ $var ] ) : esc_html( $settings[ $var ] ) ) . ';'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
322 }
323 }
324 }
325
326 /**
327 * @since 2.3
328 *
329 * @param WP_Post $style
330 * @return array
331 */
332 public static function get_settings_for_output( $style ) {
333 if ( self::previewing_style() ) {
334 $frm_style = new FrmStyle();
335 if ( isset( $_POST['frm_style_setting'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
336
337 // Sanitizing is done later.
338 $posted = wp_unslash( $_POST['frm_style_setting'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
339 if ( ! is_array( $posted ) ) {
340 $posted = json_decode( $posted, true );
341 FrmAppHelper::format_form_data( $posted );
342 $settings = $frm_style->sanitize_post_content( $posted['frm_style_setting']['post_content'] );
343 $style_name = sanitize_title( $posted['style_name'] );
344 } else {
345 $settings = $frm_style->sanitize_post_content( $posted['post_content'] );
346 $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_title' );
347 }
348 } else {
349 $settings = $frm_style->sanitize_post_content( wp_unslash( $_GET ) );
350 $style_name = FrmAppHelper::get_param( 'style_name', '', 'get', 'sanitize_title' );
351 }
352
353 FrmAppHelper::sanitize_value( 'sanitize_text_field', $settings );
354
355 $settings['style_class'] = '';
356 if ( ! empty( $style_name ) ) {
357 $settings['style_class'] = $style_name . '.';
358 }
359 } else {
360 $settings = $style->post_content;
361 $settings['style_class'] = 'frm_style_' . $style->post_name . '.';
362 }//end if
363
364 $settings['style_class'] .= 'with_frm_style';
365 $settings['font'] = stripslashes( $settings['font'] );
366 $settings['change_margin'] = self::description_margin_for_screensize( $settings['width'] );
367
368 $checkbox_opts = array( 'important_style', 'auto_width', 'submit_style', 'collapse_icon', 'center_form' );
369 foreach ( $checkbox_opts as $opt ) {
370 if ( ! isset( $settings[ $opt ] ) ) {
371 $settings[ $opt ] = 0;
372 }
373 }
374
375 self::prepare_color_output( $settings );
376
377 $settings['field_height'] = $settings['field_height'] === '' ? 'auto' : $settings['field_height'];
378 $settings['field_width'] = $settings['field_width'] === '' ? 'auto' : $settings['field_width'];
379 $settings['auto_width'] = $settings['auto_width'] ? 'auto' : $settings['field_width'];
380 $settings['box_shadow'] = ! empty( $settings['remove_box_shadow'] ) ? 'none' : '0 1px 1px rgba(0, 0, 0, 0.075) inset';
381
382 if ( ! isset( $settings['repeat_icon'] ) ) {
383 $settings['repeat_icon'] = 1;
384 }
385
386 return $settings;
387 }
388
389 /**
390 * @since 2.3
391 */
392 public static function prepare_color_output( &$settings, $allow_transparent = true ) {
393 $colors = self::allow_color_override();
394 foreach ( $colors as $css => $opts ) {
395 if ( $css === 'transparent' && ! $allow_transparent ) {
396 $css = '';
397 }
398 foreach ( $opts as $opt ) {
399 self::get_color_output( $css, $settings[ $opt ] );
400 }
401 }
402 }
403
404 /**
405 * @since 2.3
406 *
407 * @return array
408 */
409 private static function allow_color_override() {
410 $frm_style = new FrmStyle();
411 $colors = $frm_style->get_color_settings();
412
413 $transparent = array(
414 'fieldset_color',
415 'fieldset_bg_color',
416 'bg_color',
417 'bg_color_active',
418 'bg_color_disabled',
419 'section_bg_color',
420 'error_bg',
421 'success_bg_color',
422 'progress_bg_color',
423 'progress_active_bg_color',
424 'submit_border_color',
425 'submit_hover_border_color',
426 'submit_active_border_color',
427 'submit_hover_bg_color',
428 'submit_active_bg_color',
429 );
430
431 return array(
432 'transparent' => $transparent,
433 '' => array_diff( $colors, $transparent ),
434 );
435 }
436
437 /**
438 * @since 2.3
439 */
440 private static function get_color_output( $default, &$color ) {
441 $color = trim( $color );
442 if ( empty( $color ) ) {
443 $color = $default;
444 } elseif ( false !== strpos( $color, 'rgb(' ) ) {
445 $color = str_replace( 'rgb(', 'rgba(', $color );
446 $color = str_replace( ')', ',1)', $color );
447 } elseif ( strpos( $color, '#' ) === false && false === strpos( $color, 'rgba(' ) ) {
448 $color = '#' . $color;
449 }
450 }
451
452 /**
453 * If left/right label is over a certain size,
454 * adjust the field description margin at a different screen size
455 *
456 * @since 2.3
457 */
458 private static function description_margin_for_screensize( $width ) {
459 $temp_label_width = str_replace( 'px', '', $width );
460 $change_margin = false;
461 if ( $temp_label_width >= 230 ) {
462 $change_margin = '800px';
463 } elseif ( $width >= 215 ) {
464 $change_margin = '700px';
465 } elseif ( $width >= 180 ) {
466 $change_margin = '650px';
467 }
468
469 return $change_margin;
470 }
471
472 /**
473 * @since 2.3
474 *
475 * @return bool
476 */
477 public static function previewing_style() {
478 $ajax_change = isset( $_POST['action'] ) && $_POST['action'] === 'frm_change_styling' && isset( $_POST['frm_style_setting'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
479
480 return $ajax_change || isset( $_GET['flat'] );
481 }
482
483 /**
484 * @since 5.5.1
485 * @return void
486 */
487 public static function maybe_include_font_icon_css() {
488 $signature_add_on_is_active = class_exists( 'FrmSigAppHelper', false );
489
490 if ( ! FrmAppHelper::pro_is_installed() && ! $signature_add_on_is_active ) {
491 // If Pro and Signatures are both not active, there is no need to include the font icon CSS in lite.
492 return;
493 }
494
495 $pro_version_will_handle_loading = false;
496
497 if ( class_exists( 'FrmProDb', false ) ) {
498 $pro_version_that_includes_font_icons_css = '5.5.1';
499
500 // Include font icons in Lite for backward compatibility with older version of Pro.
501 $pro_version_will_handle_loading = version_compare( FrmProDb::$plug_version, $pro_version_that_includes_font_icons_css, '>=' );
502 }
503
504 $load_it_here = false;
505 if ( ! $pro_version_will_handle_loading ) {
506 // If Pro is not handling it, we still need to include it for the Signature add on.
507 $load_it_here = $signature_add_on_is_active;
508 }
509
510 if ( $load_it_here ) {
511 readfile( FrmAppHelper::plugin_path() . '/css/font_icons.css' );
512 }
513 }
514
515 /**
516 * 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.
517 *
518 * @since 6.0
519 *
520 * @param string|int $form_id
521 * @return string
522 */
523 public static function get_list_url( $form_id ) {
524 return admin_url( 'admin.php?page=formidable-styles&form=' . absint( $form_id ) );
525 }
526
527 /**
528 * Get a link to edit a target style post object in the visual styler.
529 *
530 * @param WP_Post|stdClass $style
531 * @param string|int $form_id Used for the back button and preview form target.
532 * @return string
533 */
534 public static function get_edit_url( $style, $form_id = 0 ) {
535 $query_args = array(
536 'page' => 'formidable-styles',
537 'frm_action' => 'edit',
538 'id' => $style->ID,
539 );
540
541 if ( $form_id ) {
542 // We include &form_id for the back button to know where to point to.
543 $query_args['form'] = $form_id;
544 }
545
546 return add_query_arg( $query_args, admin_url( 'admin.php' ) );
547 }
548
549 /**
550 * Get a count of the number of forms assigned to a target style ID.
551 * All unassigned forms are included in the count for the default style.
552 *
553 * @since 6.0
554 *
555 * @param string|int $style_id
556 * @param bool $is_default
557 * @return int
558 */
559 public static function get_form_count_for_style( $style_id, $is_default ) {
560 $serialized = serialize( array( 'custom_style' => (string) $style_id ) );
561 // Chop off the "a:1:{" from the front and the "}" from the back.
562 $substring = substr( $serialized, 5, -1 );
563 $number_of_forms = FrmDb::get_count(
564 'frm_forms',
565 array(
566 'status' => 'published',
567 'options LIKE' => $substring,
568 )
569 );
570
571 if ( ! $is_default ) {
572 // Exit early as the rest of the code is about including the default count.
573 return $number_of_forms;
574 }
575
576 $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' );
577 $number_of_forms += self::get_default_style_count( $style_id, $conversational_style_id );
578
579 return $number_of_forms;
580 }
581
582 /**
583 * Get the number of forms that use the default style.
584 *
585 * @since 6.0
586 *
587 * @param string|int $style_id
588 * @param mixed $conversational_style_id
589 * @return int
590 */
591 private static function get_default_style_count( $style_id, $conversational_style_id ) {
592 $substrings = array_map(
593 function( $value ) {
594 $substring = serialize( array( 'custom_style' => $value ) );
595 return substr( $substring, 5, -1 );
596 },
597 array( '1', 1 )
598 );
599 $where = array(
600 'status' => 'published',
601 0 => array(
602 'options NOT LIKE' => 'custom_style',
603 'or' => 1,
604 'options LIKE' => $substrings,
605 ),
606 );
607
608 if ( $conversational_style_id ) {
609 // When a conversational style is set, check for it in the query by wrapping the where and adding a conversational option check.
610 $is_conversational_style = (int) $style_id === (int) $conversational_style_id;
611 $where[0] = array(
612 // The chat option doesn't exist if it isn't on.
613 ( $is_conversational_style ? 'options LIKE' : 'options NOT LIKE' ) => ';s:4:"chat";',
614 $where[0],
615 );
616 }
617
618 return FrmDb::get_count( 'frm_forms', $where );
619 }
620
621 /**
622 * @deprecated 3.01
623 * @codeCoverageIgnore
624 */
625 public static function get_sigle_label_postitions() {
626 return FrmDeprecated::get_sigle_label_postitions();
627 }
628
629 /**
630 * @deprecated 3.02.03
631 * @codeCoverageIgnore
632 */
633 public static function jquery_themes() {
634 return FrmDeprecated::jquery_themes();
635 }
636
637 /**
638 * @deprecated 3.02.03
639 * @codeCoverageIgnore
640 */
641 public static function jquery_css_url( $theme_css ) {
642 return FrmDeprecated::jquery_css_url( $theme_css );
643 }
644
645 /**
646 * @deprecated 3.02.03
647 * @codeCoverageIgnore
648 */
649 public static function enqueue_jquery_css() {
650 FrmDeprecated::enqueue_jquery_css();
651 }
652
653 /**
654 * @deprecated 3.02.03
655 * @codeCoverageIgnore
656 */
657 public static function get_form_for_page() {
658 return FrmDeprecated::get_form_for_page();
659 }
660
661 /**
662 * @since 4.0
663 * @deprecated 6.0 The style menu is no longer used in the styler.
664 *
665 * @param string $active
666 * @return string
667 */
668 public static function get_style_menu( $active = '' ) {
669 _deprecated_function( __METHOD__, '6.0' );
670 return '';
671 }
672
673 /**
674 * @deprecated 6.0 The style menu is no longer used in the styler.
675 *
676 * @param string $active
677 * @return void
678 */
679 public static function style_menu( $active = '' ) {
680 _deprecated_function( __METHOD__, '6.0' );
681 }
682
683 /**
684 * Either get the heading or the style switcher.
685 *
686 * @since 4.0
687 * @deprecated 6.0 The style switcher was replaced with a form switcher and is no longer used.
688 *
689 * @param array $atts
690 * @return void
691 */
692 public static function styler_switcher( $atts ) {
693 _deprecated_function( __METHOD__, '6.0' );
694 }
695
696 /**
697 * @since 4.0
698 * @deprecated 6.0 The styler now uses the Embed/Preview/Update header. It uses the same save button as other pages with Form tabs.
699 *
700 * @param array $atts
701 * @return void
702 */
703 public static function styler_save_button( $atts ) {
704 _deprecated_function( __METHOD__, '6.0' );
705 }
706 }
707