PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.18
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.18
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
← All changes | classes/helpers/FrmAppHelper.php +857 -353 6.36.18 View file →
@@ -3,27 +3,43 @@
3 3 die( 'You are not allowed to call this page directly.' );
4 4 }
5 5
6 6 class FrmAppHelper {
7 - public static $db_version = 98; // Version of the database we are moving to.
8 - public static $pro_db_version = 37; //deprecated
9 - public static $font_version = 7;
10 7
11 8 /**
12 - * @var bool $added_gmt_offset_filter
9 + * Version of the database we are moving to.
10 + *
11 + * @var int
13 12 */
13 + public static $db_version = 103;
14 +
15 + /**
16 + * Used by the API add-on.
17 + *
18 + * @var float
19 + */
20 + public static $font_version = 7;
21 +
22 + /**
23 + * @var bool
24 + */
14 25 private static $added_gmt_offset_filter = false;
15 26
16 27 /**
17 28 * @since 2.0
29 + *
30 + * @var string
18 31 */
19 - public static $plug_version = '6.3';
32 + public static $plug_version = '6.18';
20 33
21 34 /**
35 + * @var bool
36 + */
37 + private static $included_svg = false;
38 +
39 + /**
22 40 * @since 1.07.02
23 41 *
24 - * @param none
25 - *
26 42 * @return string The version of this plugin
27 43 */
28 44 public static function plugin_version() {
29 45 return self::$plug_version;
@@ -28,21 +44,33 @@
28 44 public static function plugin_version() {
29 45 return self::$plug_version;
30 46 }
31 47
48 + /**
49 + * @return string
50 + */
32 51 public static function plugin_folder() {
33 52 return basename( self::plugin_path() );
34 53 }
35 54
55 + /**
56 + * @return string
57 + */
36 58 public static function plugin_path() {
37 - return dirname( dirname( dirname( __FILE__ ) ) );
59 + return dirname( dirname( __DIR__ ) );
38 60 }
39 61
62 + /**
63 + * @return string
64 + */
40 65 public static function plugin_url() {
41 - // Prevously FRM_URL constant.
66 + // Previously FRM_URL constant.
42 67 return plugins_url( '', self::plugin_path() . '/formidable.php' );
43 68 }
44 69
70 + /**
71 + * @return string
72 + */
45 73 public static function relative_plugin_url() {
46 74 return str_replace( array( 'https:', 'http:' ), '', self::plugin_url() );
47 75 }
48 76
@@ -63,8 +91,12 @@
63 91 public static function site_name() {
64 92 return get_option( 'blogname' );
65 93 }
66 94
95 + /**
96 + * @param string $url
97 + * @return string
98 + */
67 99 public static function make_affiliate_url( $url ) {
68 100 $affiliate_id = self::get_affiliate();
69 101 if ( ! empty( $affiliate_id ) ) {
70 102 $url = str_replace( array( 'http://', 'https://' ), '', $url );
@@ -73,8 +105,11 @@
73 105
74 106 return $url;
75 107 }
76 108
109 + /**
110 + * @return int
111 + */
77 112 public static function get_affiliate() {
78 113 return absint( apply_filters( 'frm_affiliate_id', 0 ) );
79 114 }
80 115
@@ -131,9 +166,9 @@
131 166 *
132 167 * @since 2.0
133 168 *
134 169 * @param array $args - May include the form id when values need translation.
135 - * @return FrmSettings $frm_setings
170 + * @return FrmSettings $frm_settings
136 171 */
137 172 public static function get_settings( $args = array() ) {
138 173 global $frm_settings;
139 174 if ( empty( $frm_settings ) ) {
@@ -145,16 +180,39 @@
145 180
146 181 return $frm_settings;
147 182 }
148 183
184 + /**
185 + * @return string
186 + */
149 187 public static function get_menu_name() {
150 188 $frm_settings = self::get_settings();
151 189
152 - return $frm_settings->menu;
190 + return FrmAddonsController::is_license_expired() ? 'Formidable' : $frm_settings->menu;
153 191 }
154 192
155 193 /**
194 + * Determine if the current branding is set to 'formidable'.
195 + * Checks the menu icon, and verifies if it matches the formidable branding.
196 + *
197 + * @since 6.4.2
198 + *
199 + * @return bool True if the menu icon is the logo, false otherwise.
200 + */
201 + public static function is_formidable_branding() {
202 + if ( ! self::pro_is_installed() ) {
203 + return true;
204 + }
205 +
206 + $menu_icon = self::get_menu_icon_class();
207 + return strpos( $menu_icon, 'frm_logo_icon' ) !== false;
208 + }
209 +
210 + /**
156 211 * @since 3.05
212 + *
213 + * @param array $atts
214 + * @return string
157 215 */
158 216 public static function svg_logo( $atts = array() ) {
159 217 $defaults = array(
160 218 'height' => 18,
@@ -171,8 +229,11 @@
171 229 }
172 230
173 231 /**
174 232 * @since 4.0
233 + *
234 + * @param array $atts
235 + * @return void
175 236 */
176 237 public static function show_logo( $atts = array() ) {
177 238 echo self::kses( self::svg_logo( $atts ), 'all' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
178 239 }
@@ -178,8 +239,10 @@
178 239 }
179 240
180 241 /**
181 242 * @since 4.03.02
243 + *
244 + * @return void
182 245 */
183 246 public static function show_header_logo() {
184 247 $icon = self::svg_logo(
185 248 array(
@@ -201,21 +264,38 @@
201 264 }
202 265
203 266 /**
204 267 * @since 2.02.04
268 + *
269 + * @return bool
205 270 */
206 271 public static function ips_saved() {
207 272 $frm_settings = self::get_settings();
208 -
209 273 return ! $frm_settings->no_ips;
210 274 }
211 275
276 + /**
277 + * @return bool
278 + */
212 279 public static function pro_is_installed() {
213 - return apply_filters( 'frm_pro_installed', false );
280 + return (bool) apply_filters( 'frm_pro_installed', false );
214 281 }
215 282
216 283 /**
284 + * Check if the Pro plugin is installed, whether authorized or not.
285 + *
286 + * @since 6.8.3
287 + *
288 + * @return bool
289 + */
290 + public static function pro_is_included() {
291 + return function_exists( 'load_formidable_pro' );
292 + }
293 +
294 + /**
217 295 * @since 4.06.02
296 + *
297 + * @return bool
218 298 */
219 299 public static function pro_is_connected() {
220 300 global $frm_vars;
221 301 return self::pro_is_installed() && $frm_vars['pro_is_authorized'];
@@ -222,14 +302,26 @@
222 302 }
223 303
224 304 /**
225 305 * @since 4.06
306 + * @since 6.16.2 Added $check_for_settings parameter
307 + *
308 + * @param bool $check_for_settings
309 + *
310 + * @return bool
226 311 */
227 - public static function is_form_builder_page() {
228 - $action = self::simple_get( 'frm_action', 'sanitize_title' );
229 - return self::is_admin_page( 'formidable' ) && ( $action === 'edit' || $action === 'settings' || $action === 'duplicate' );
312 + public static function is_form_builder_page( $check_for_settings = true ) {
313 + $action = self::simple_get( 'frm_action', 'sanitize_title' );
314 + $check_actions = array( 'edit', 'duplicate' );
315 + if ( $check_for_settings ) {
316 + $check_actions[] = 'settings';
317 + }
318 + return self::is_admin_page( 'formidable' ) && in_array( $action, $check_actions, true );
230 319 }
231 320
321 + /**
322 + * @return bool
323 + */
232 324 public static function is_formidable_admin() {
233 325 $page = self::simple_get( 'page', 'sanitize_title' );
234 326 $is_formidable = strpos( $page, 'formidable' ) !== false;
235 327 if ( empty( $page ) ) {
@@ -243,11 +335,11 @@
243 335 * Check for certain page in Formidable settings
244 336 *
245 337 * @since 2.0
246 338 *
247 - * @param string $page The name of the page to check
339 + * @param string $page The name of the page to check.
248 340 *
249 - * @return boolean
341 + * @return bool
250 342 */
251 343 public static function is_admin_page( $page = 'formidable' ) {
252 344 global $pagenow;
253 345 $get_page = self::simple_get( 'page', 'sanitize_title' );
@@ -266,8 +358,10 @@
266 358 * If the current page is for editing or creating a view.
267 359 * Returns false for the views listing page.
268 360 *
269 361 * @since 4.0
362 + *
363 + * @return bool
270 364 */
271 365 public static function is_view_builder_page() {
272 366 global $pagenow;
273 367
@@ -277,10 +371,10 @@
277 371
278 372 $post_type = self::simple_get( 'post_type', 'sanitize_title' );
279 373
280 374 if ( empty( $post_type ) ) {
281 - $post_id = self::simple_get( 'post', 'absint' );
282 - $post = get_post( $post_id );
375 + $post_id = self::simple_get( 'post', 'absint' );
376 + $post = get_post( $post_id );
283 377 $post_type = $post ? $post->post_type : '';
284 378 }
285 379
286 380 return $post_type === 'frm_display';
@@ -290,17 +384,15 @@
290 384 * Check for the form preview page
291 385 *
292 386 * @since 2.0
293 387 *
294 - * @param None
295 - *
296 - * @return boolean
388 + * @return bool
297 389 */
298 390 public static function is_preview_page() {
299 391 global $pagenow;
300 392 $action = self::simple_get( 'action', 'sanitize_title' );
301 393
302 - return $pagenow && $pagenow == 'admin-ajax.php' && $action == 'frm_forms_preview';
394 + return $pagenow && $pagenow === 'admin-ajax.php' && $action === 'frm_forms_preview';
303 395 }
304 396
305 397 /**
306 398 * Check for ajax except the form preview page
@@ -306,16 +398,17 @@
306 398 * Check for ajax except the form preview page
307 399 *
308 400 * @since 2.0
309 401 *
310 - * @param None
311 - *
312 - * @return boolean
402 + * @return bool
313 403 */
314 404 public static function doing_ajax() {
315 405 return wp_doing_ajax() && ! self::is_preview_page();
316 406 }
317 407
408 + /**
409 + * @return string
410 + */
318 411 public static function js_suffix() {
319 412 return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
320 413 }
321 414
@@ -320,13 +413,13 @@
320 413 }
321 414
322 415 /**
323 416 * @since 2.0.8
417 + * @return bool
324 418 */
325 419 public static function prevent_caching() {
326 420 global $frm_vars;
327 -
328 - return isset( $frm_vars['prevent_caching'] ) && $frm_vars['prevent_caching'];
421 + return ! empty( $frm_vars['prevent_caching'] );
329 422 }
330 423
331 424 /**
332 425 * Check if on an admin page
@@ -332,9 +425,9 @@
332 425 * Check if on an admin page
333 426 *
334 427 * @since 2.0
335 428 *
336 - * @return boolean
429 + * @return bool
337 430 */
338 431 public static function is_admin() {
339 432 $is_admin = is_admin() && ! wp_doing_ajax();
340 433
@@ -349,17 +442,22 @@
349 442 * Check if value contains blank value or empty array
350 443 *
351 444 * @since 2.0
352 445 *
353 - * @param mixed $value - value to check
354 - * @param string
446 + * @param mixed $value Value to check.
447 + * @param string $empty
355 448 *
356 - * @return boolean
449 + * @return bool
357 450 */
358 451 public static function is_empty_value( $value, $empty = '' ) {
359 452 return ( is_array( $value ) && empty( $value ) ) || $value === $empty;
360 453 }
361 454
455 + /**
456 + * @param mixed $value
457 + * @param string $empty
458 + * @return bool
459 + */
362 460 public static function is_not_empty_value( $value, $empty = '' ) {
363 461 return ! self::is_empty_value( $value, $empty );
364 462 }
365 463
@@ -376,8 +474,28 @@
376 474 return isset( $_SERVER[ $value ] ) ? wp_strip_all_tags( wp_unslash( $_SERVER[ $value ] ) ) : '';
377 475 }
378 476
379 477 /**
478 + * Get the server OS
479 + *
480 + * @since 6.4.2
481 + *
482 + * @return string
483 + */
484 + public static function get_server_os() {
485 + if ( function_exists( 'php_uname' ) ) {
486 + return php_uname( 's' );
487 + }
488 +
489 + if ( ! defined( 'PHP_OS' ) ) {
490 + return '';
491 + }
492 +
493 + // match the same response for Windows server as php_uname('s')
494 + return in_array( PHP_OS, array( 'WIN32', 'WINNT', 'Windows_NT' ), true ) ? 'Windows NT' : PHP_OS;
495 + }
496 +
497 + /**
380 498 * Check for the IP address in several places (when custom headers are enabled).
381 499 * Used by [ip] shortcode.
382 500 *
383 501 * @return string The IP address of the current user
@@ -392,9 +510,10 @@
392 510 }
393 511
394 512 $key = self::get_server_value( $key );
395 513 foreach ( explode( ',', $key ) as $ip ) {
396 - $ip = trim( $ip ); // Just to be safe.
514 + // Just to be safe.
515 + $ip = trim( $ip );
397 516
398 517 if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
399 518 return sanitize_text_field( $ip );
400 519 }
@@ -485,15 +604,24 @@
485 604
486 605 return $value;
487 606 }
488 607
608 + /**
609 + * Get a value from $_POST data.
610 + *
611 + * @param string $param The key we are trying to access data from in $_POST.
612 + * @param mixed $default The default if nothing is being sent.
613 + * @param callable|string $sanitize Make sure to pass a sanitize method here. This function will NOT sanitize by default.
614 + * @param bool $serialized
615 + * @return mixed
616 + */
489 617 public static function get_post_param( $param, $default = '', $sanitize = '', $serialized = false ) {
490 618 return self::get_simple_request(
491 619 array(
492 - 'type' => 'post',
493 - 'param' => $param,
494 - 'default' => $default,
495 - 'sanitize' => $sanitize,
620 + 'type' => 'post',
621 + 'param' => $param,
622 + 'default' => $default,
623 + 'sanitize' => $sanitize,
496 624 'serialized' => $serialized,
497 625 )
498 626 );
499 627 }
@@ -504,9 +632,9 @@
504 632 * @param string $param
505 633 * @param string $sanitize
506 634 * @param string $default
507 635 *
508 - * @return string|array
636 + * @return array|string
509 637 */
510 638 public static function simple_get( $param, $sanitize = 'sanitize_text_field', $default = '' ) {
511 639 return self::get_simple_request(
512 640 array(
@@ -524,27 +652,27 @@
524 652 * @since 2.0.6
525 653 *
526 654 * @param array $args
527 655 *
528 - * @return string|array
656 + * @return array|string
529 657 */
530 658 public static function get_simple_request( $args ) {
531 659 $defaults = array(
532 - 'param' => '',
533 - 'default' => '',
534 - 'type' => 'get',
535 - 'sanitize' => 'sanitize_text_field',
660 + 'param' => '',
661 + 'default' => '',
662 + 'type' => 'get',
663 + 'sanitize' => 'sanitize_text_field',
536 664 'serialized' => false,
537 665 );
538 666 $args = wp_parse_args( $args, $defaults );
539 667
540 668 $value = $args['default'];
541 - if ( $args['type'] == 'get' ) {
669 + if ( $args['type'] === 'get' ) {
542 670 if ( $_GET && isset( $_GET[ $args['param'] ] ) ) {
543 671 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
544 672 $value = wp_unslash( $_GET[ $args['param'] ] );
545 673 }
546 - } elseif ( $args['type'] == 'post' ) {
674 + } elseif ( $args['type'] === 'post' ) {
547 675 if ( isset( $_POST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
548 676 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
549 677 $value = wp_unslash( $_POST[ $args['param'] ] );
550 678 if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
@@ -550,13 +678,12 @@
550 678 if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
551 679 self::unserialize_or_decode( $value );
552 680 }
553 681 }
554 - } else {
555 - if ( isset( $_REQUEST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
682 + } elseif ( isset( $_REQUEST[ $args['param'] ] ) ) {
683 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
556 684 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
557 685 $value = wp_unslash( $_REQUEST[ $args['param'] ] );
558 - }
559 686 }
560 687
561 688 self::sanitize_value( $args['sanitize'], $value );
562 689
@@ -580,19 +707,35 @@
580 707
581 708 return $value;
582 709 }
583 710
711 + /**
712 + * Sanitize a value in-place.
713 + * If $value is an array, the sanitize function will get called for each item.
714 + *
715 + * @param callable $sanitize
716 + * @param mixed $value
717 + * @return void
718 + */
584 719 public static function sanitize_value( $sanitize, &$value ) {
585 - if ( ! empty( $sanitize ) ) {
586 - if ( is_array( $value ) ) {
587 - $temp_values = $value;
588 - foreach ( $temp_values as $k => $v ) {
589 - self::sanitize_value( $sanitize, $value[ $k ] );
590 - }
591 - } else {
592 - $value = call_user_func( $sanitize, $value );
720 + if ( ! $sanitize ) {
721 + return;
722 + }
723 +
724 + if ( is_object( $value ) ) {
725 + $value = '';
726 + return;
727 + }
728 +
729 + if ( is_array( $value ) ) {
730 + $temp_values = $value;
731 + foreach ( $temp_values as $k => $v ) {
732 + self::sanitize_value( $sanitize, $value[ $k ] );
593 733 }
734 + return;
594 735 }
736 +
737 + $value = call_user_func( $sanitize, $value );
595 738 }
596 739
597 740 public static function sanitize_request( $sanitize_method, &$values ) {
598 741 $temp_values = $values;
@@ -604,15 +747,52 @@
604 747 }
605 748
606 749 /**
607 750 * @since 4.0.04
751 + *
752 + * @param mixed $value
753 + * @return void
608 754 */
609 755 public static function sanitize_with_html( &$value ) {
610 - self::sanitize_value( 'wp_kses_post', $value );
756 + if ( current_user_can( 'frm_edit_entries' ) || current_user_can( 'administrator' ) ) {
757 + // Only strip unsafe HTML like scripts for a privileged user submitting a form.
758 + self::sanitize_value( 'wp_kses_post', $value );
759 + } else {
760 + self::sanitize_value( self::class . '::strip_most_html', $value );
761 + }
611 762 self::decode_specialchars( $value );
612 763 }
613 764
614 765 /**
766 + * Allow only a small set of very basic HTML for unprivileged users.
767 + *
768 + * @since 6.7.1
769 + *
770 + * @param string $value
771 + */
772 + public static function strip_most_html( $value ) {
773 + $allowed_html = array(
774 + 'b' => array(),
775 + 'br' => array(),
776 + 'strong' => array(),
777 + 'p' => array(),
778 + 'i' => array(),
779 + 'ul' => array(),
780 + 'ol' => array(),
781 + 'li' => array(),
782 + );
783 +
784 + /**
785 + * @since 6.7.1
786 + *
787 + * @param array $allowed_html
788 + */
789 + $allowed_html = apply_filters( 'frm_allowed_form_input_html', $allowed_html );
790 +
791 + return wp_kses( $value, $allowed_html );
792 + }
793 +
794 + /**
615 795 * Do wp_specialchars_decode to get back '&' that wp_kses_post might have turned to '&'
616 796 * this MUST be done, else we'll be back to the '& entity' problem.
617 797 *
618 798 * @since 4.0.04
@@ -646,10 +826,12 @@
646 826 $translation = array(
647 827 '"' => '"',
648 828 '"' => '"',
649 829 '"' => '"',
650 - '&lt; ' => '< ', // The space preserves the HTML.
651 - '&#060; ' => '< ', // The space preserves the HTML.
830 + // The space preserves the HTML.
831 + '&lt; ' => '< ',
832 + // The space preserves the HTML.
833 + '&#060; ' => '< ',
652 834 '&gt;' => '>',
653 835 '&#062;' => '>',
654 836 '&amp;' => '&',
655 837 '&#038;' => '&',
@@ -676,10 +858,10 @@
676 858 * Sanitize the value, and allow some HTML
677 859 *
678 860 * @since 2.0
679 861 *
680 - * @param string $value
681 - * @param array|string $allowed 'all' for everything included as defaults
862 + * @param string $value
863 + * @param array|string $allowed 'all' for everything included as defaults.
682 864 *
683 865 * @return string
684 866 */
685 867 public static function kses( $value, $allowed = array() ) {
@@ -688,8 +870,21 @@
688 870 return wp_kses( $value, $allowed_html );
689 871 }
690 872
691 873 /**
874 + * Sanitizes and echoes a given value.
875 + *
876 + * @since 6.18
877 + *
878 + * @param string $value The value to sanitize and output.
879 + * @param array|string $allowed Allowed HTML tags and attributes.
880 + * @return void
881 + */
882 + public static function kses_echo( $value, $allowed = array() ) {
883 + echo self::kses( $value, $allowed ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
884 + }
885 +
886 + /**
692 887 * The regular kses function strips [button_action] from submit button HTML.
693 888 *
694 889 * @since 5.0.13
695 890 *
@@ -780,9 +975,9 @@
780 975 'id' => true,
781 976 );
782 977
783 978 return array(
784 - 'a' => array(
979 + 'a' => array(
785 980 'class' => true,
786 981 'href' => true,
787 982 'id' => true,
788 983 'rel' => true,
@@ -851,16 +1046,16 @@
851 1046 'cite' => true,
852 1047 'title' => true,
853 1048 ),
854 1049 'rect' => array(
855 - 'class' => true,
856 - 'fill' => true,
857 - 'height' => true,
858 - 'width' => true,
859 - 'x' => true,
860 - 'y' => true,
861 - 'rx' => true,
862 - 'stroke' => true,
1050 + 'class' => true,
1051 + 'fill' => true,
1052 + 'height' => true,
1053 + 'width' => true,
1054 + 'x' => true,
1055 + 'y' => true,
1056 + 'rx' => true,
1057 + 'stroke' => true,
863 1058 'stroke-opacity' => true,
864 1059 'stroke-width' => true,
865 1060 ),
866 1061 'section' => $allow_class,
@@ -895,9 +1090,9 @@
895 1090 'xlink:href' => true,
896 1091 ),
897 1092 'ul' => $allow_class,
898 1093 'label' => array(
899 - 'for' => true,
1094 + 'for' => true,
900 1095 'class' => true,
901 1096 'id' => true,
902 1097 ),
903 1098 'button' => array(
@@ -906,8 +1101,13 @@
906 1101 ),
907 1102 'legend' => array(
908 1103 'class' => true,
909 1104 ),
1105 + 'option' => array(
1106 + 'class' => true,
1107 + 'value' => true,
1108 + 'selected' => true,
1109 + ),
910 1110 );
911 1111 }
912 1112
913 1113 /**
@@ -915,9 +1115,9 @@
915 1115 *
916 1116 * @since 2.0
917 1117 */
918 1118 public static function remove_get_action() {
919 - if ( ! isset( $_GET ) ) {
1119 + if ( empty( $_GET ) ) {
920 1120 return;
921 1121 }
922 1122
923 1123 $action_name = isset( $_GET['action'] ) ? 'action' : ( isset( $_GET['action2'] ) ? 'action2' : '' );
@@ -934,9 +1134,9 @@
934 1134 /**
935 1135 * Check the WP query for a parameter
936 1136 *
937 1137 * @since 2.0
938 - * @return string|array
1138 + * @return array|string
939 1139 */
940 1140 public static function get_query_var( $value, $param ) {
941 1141 if ( $value != '' ) {
942 1142 return $value;
@@ -953,10 +1153,12 @@
953 1153 /**
954 1154 * Try to show the SVG if possible. Otherwise, use the font icon.
955 1155 *
956 1156 * @since 4.0.02
1157 + *
957 1158 * @param string $class
958 1159 * @param array $atts
1160 + * @return string|null
959 1161 */
960 1162 public static function icon_by_class( $class, $atts = array() ) {
961 1163 $echo = ! isset( $atts['echo'] ) || $atts['echo'];
962 1164 if ( isset( $atts['echo'] ) ) {
@@ -966,14 +1168,16 @@
966 1168 $html_atts = self::array_to_html_params( $atts );
967 1169
968 1170 $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
969 1171
970 - // Replace icons that have been removed.
1172 + // Replace icons that have been removed or renamed.
971 1173 $deprecated = array(
972 - 'frm_clone_solid_icon' => 'frm_clone_icon',
1174 + 'frm_clone_solid_icon' => 'frm_clone_icon',
1175 + 'frm_keyalt_icon' => 'frm_key_icon',
1176 + 'frm_keyalt_solid_icon' => 'frm_key_solid_icon',
973 1177 );
974 1178 if ( isset( $deprecated[ $icon ] ) ) {
975 - $icon = $deprecated[ $icon ];
1179 + $icon = $deprecated[ $icon ];
976 1180 $class = str_replace( $icon, $deprecated[ $icon ], $class );
977 1181 }
978 1182
979 1183 if ( $icon === $class ) {
@@ -983,11 +1187,9 @@
983 1187 if ( strpos( $icon, ' ' ) ) {
984 1188 $icon = explode( ' ', $icon );
985 1189 $icon = reset( $icon );
986 1190 }
987 - $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '>
988 - <use xlink:href="#' . esc_attr( $icon ) . '" />
989 - </svg>';
1191 + $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use xlink:href="#' . esc_attr( $icon ) . '" /></svg>';
990 1192 }
991 1193
992 1194 if ( $echo ) {
993 1195 echo self::kses_icon( $icon ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -1073,11 +1275,18 @@
1073 1275 /**
1074 1276 * Include svg images.
1075 1277 *
1076 1278 * @since 4.0.02
1279 + * @return void
1077 1280 */
1078 1281 public static function include_svg() {
1079 - include_once self::plugin_path() . '/images/icons.svg';
1282 + if ( self::$included_svg ) {
1283 + return;
1284 + }
1285 +
1286 + // Use readfile instead of include_once because of a default security rule in Snuffleupagus.
1287 + readfile( self::plugin_path() . '/images/icons.svg' );
1288 + self::$included_svg = true;
1080 1289 }
1081 1290
1082 1291 /**
1083 1292 * Convert an associative array to HTML values.
@@ -1089,9 +1298,9 @@
1089 1298 * @param bool $echo
1090 1299 * @return string|void
1091 1300 */
1092 1301 public static function array_to_html_params( $atts, $echo = false ) {
1093 - $callback = function() use ( $atts ) {
1302 + $callback = function () use ( $atts ) {
1094 1303 if ( $atts ) {
1095 1304 foreach ( $atts as $key => $value ) {
1096 1305 echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
1097 1306 }
@@ -1106,9 +1315,9 @@
1106 1315 * @since 5.0.13
1107 1316 *
1108 1317 * @param Closure $echo_function
1109 1318 * @param bool $echo
1110 - * @return string|void
1319 + * @return string|null
1111 1320 */
1112 1321 public static function clip( $echo_function, $echo = false ) {
1113 1322 if ( ! $echo ) {
1114 1323 ob_start();
@@ -1126,12 +1335,15 @@
1126 1335 }
1127 1336
1128 1337 /**
1129 1338 * @since 3.0
1339 + *
1340 + * @param array $atts
1341 + * @return void
1130 1342 */
1131 1343 public static function get_admin_header( $atts ) {
1132 - $has_nav = ( isset( $atts['form'] ) && ! empty( $atts['form'] ) && ( ! isset( $atts['is_template'] ) || ! $atts['is_template'] ) );
1133 - if ( ! isset( $atts['close'] ) || empty( $atts['close'] ) ) {
1344 + $has_nav = ! empty( $atts['form'] ) && empty( $atts['is_template'] );
1345 + if ( empty( $atts['close'] ) ) {
1134 1346 $atts['close'] = admin_url( 'admin.php?page=formidable' );
1135 1347 }
1136 1348 if ( ! isset( $atts['import_link'] ) ) {
1137 1349 $atts['import_link'] = false;
@@ -1136,9 +1348,9 @@
1136 1348 if ( ! isset( $atts['import_link'] ) ) {
1137 1349 $atts['import_link'] = false;
1138 1350 }
1139 1351
1140 - include( self::plugin_path() . '/classes/views/shared/admin-header.php' );
1352 + include self::plugin_path() . '/classes/views/shared/admin-header.php';
1141 1353 }
1142 1354
1143 1355 /**
1144 1356 * @since 6.0
@@ -1174,10 +1386,34 @@
1174 1386 return;
1175 1387 }
1176 1388 ?>
1177 1389 <div class="frm-upgrade-bar">
1178 - <span>You're using Formidable Forms Lite. To unlock more features consider</span>
1179 - <a href="<?php echo esc_url( self::admin_upgrade_link( 'top-bar' ) ); ?>" target="_blank" rel="noopener">upgrading to Pro</a>.
1390 + <div class="frm-upgrade-bar-inner">
1391 + <?php
1392 + $cta_text = FrmSalesApi::get_best_sale_value( 'lite_banner_cta_text' );
1393 + if ( ! $cta_text ) {
1394 + $cta_text = __( 'upgrading to PRO', 'formidable' );
1395 + }
1396 +
1397 + $upgrade_link = FrmSalesApi::get_best_sale_value( 'lite_banner_cta_link' );
1398 + if ( ! $upgrade_link ) {
1399 + $upgrade_link = self::admin_upgrade_link(
1400 + array(
1401 + 'medium' => 'settings-license',
1402 + 'content' => 'lite-banner',
1403 + )
1404 + );
1405 + }
1406 +
1407 + printf(
1408 + /* translators: %1$s: Start link HTML, %2$s: CTA text ("upgrading to PRO" by default), %3$s: End link HTML */
1409 + esc_html__( 'You\'re using Formidable Forms Lite. To unlock more features consider %1$s%2$s%3$s.', 'formidable' ),
1410 + '<a href="' . esc_url( $upgrade_link ) . '">',
1411 + esc_html( $cta_text ),
1412 + '</a>'
1413 + );
1414 + ?>
1415 + </div>
1180 1416 </div>
1181 1417 <?php
1182 1418 }
1183 1419
@@ -1194,8 +1430,10 @@
1194 1430 * Render a button for a new item (Form, Application, etc).
1195 1431 *
1196 1432 * @since 3.0
1197 1433 * @param array $atts {
1434 + * Details about the button.
1435 + *
1198 1436 * @type array $link_hook Custom link hook, calls do_action and exits early.
1199 1437 * @type string $new_link Href value, default #.
1200 1438 * @type string $class Custom class names, space separated.
1201 1439 * @type string $button_text Button text. Default "Add New".
@@ -1207,9 +1445,9 @@
1207 1445 do_action( $atts['link_hook']['hook'], $atts['link_hook']['param'] );
1208 1446 return;
1209 1447 }
1210 1448
1211 - if ( empty( $atts['new_link'] ) && empty( $atts['trigger_new_form_modal'] ) && empty( $atts['class'] ) ) {
1449 + if ( empty( $atts['new_link'] ) && empty( $atts['create_form'] ) && empty( $atts['class'] ) ) {
1212 1450 // Do not render a button if none of these attributes are set.
1213 1451 return;
1214 1452 }
1215 1453
@@ -1215,12 +1453,8 @@
1215 1453
1216 1454 $href = ! empty( $atts['new_link'] ) ? esc_url( $atts['new_link'] ) : '#';
1217 1455 $class = 'button button-primary frm-button-primary';
1218 1456
1219 - if ( ! empty( $atts['trigger_new_form_modal'] ) ) {
1220 - $class .= ' frm-trigger-new-form-modal';
1221 - }
1222 -
1223 1457 if ( ! empty( $atts['class'] ) ) {
1224 1458 $class .= ' ' . $atts['class'];
1225 1459 }
1226 1460
@@ -1237,10 +1471,11 @@
1237 1471 'placeholder' => '',
1238 1472 'tosearch' => '',
1239 1473 'text' => __( 'Search', 'formidable' ),
1240 1474 'input_id' => '',
1475 + 'value' => false,
1241 1476 );
1242 - $atts = array_merge( $defaults, $atts );
1477 + $atts = array_merge( $defaults, $atts );
1243 1478
1244 1479 if ( $atts['input_id'] === 'template' && empty( $atts['tosearch'] ) ) {
1245 1480 $atts['tosearch'] = 'frm-card';
1246 1481 }
@@ -1251,8 +1486,27 @@
1251 1486 }
1252 1487
1253 1488 $input_id = $atts['input_id'] . '-search-input';
1254 1489
1490 + $input_atts = array(
1491 + 'type' => 'search',
1492 + 'id' => $input_id,
1493 + 'name' => 's',
1494 + 'placeholder' => $atts['placeholder'],
1495 + 'class' => $class,
1496 + 'data-tosearch' => $atts['tosearch'],
1497 + );
1498 +
1499 + if ( is_string( $atts['value'] ) ) {
1500 + $input_atts['value'] = $atts['value'];
1501 + } elseif ( isset( $_REQUEST['s'] ) ) {
1502 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1503 + $input_atts['value'] = wp_unslash( $_REQUEST['s'] );
1504 + }
1505 +
1506 + if ( ! empty( $atts['tosearch'] ) ) {
1507 + $input_atts['autocomplete'] = 'off';
1508 + }
1255 1509 ?>
1256 1510 <p class="frm-search">
1257 1511 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1258 1512 <?php echo esc_html( $atts['text'] ); ?>:
@@ -1257,15 +1511,9 @@
1257 1511 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1258 1512 <?php echo esc_html( $atts['text'] ); ?>:
1259 1513 </label>
1260 1514 <span class="frmfont frm_search_icon"></span>
1261 - <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s"
1262 - value="<?php _admin_search_query(); ?>" placeholder="<?php echo esc_attr( $atts['placeholder'] ); ?>"
1263 - class="<?php echo esc_attr( $class ); ?>" data-tosearch="<?php echo esc_attr( $atts['tosearch'] ); ?>"
1264 - <?php if ( ! empty( $atts['tosearch'] ) ) { ?>
1265 - autocomplete="off"
1266 - <?php } ?>
1267 - />
1515 + <input <?php self::array_to_html_params( $input_atts, true ); ?> />
1268 1516 <?php
1269 1517 if ( empty( $atts['tosearch'] ) ) {
1270 1518 submit_button( $atts['text'], 'button-secondary', '', false, array( 'id' => 'search-submit' ) );
1271 1519 }
@@ -1275,8 +1523,9 @@
1275 1523 }
1276 1524
1277 1525 /**
1278 1526 * @param string $type
1527 + * @return void
1279 1528 */
1280 1529 public static function trigger_hook_load( $type, $object = null ) {
1281 1530 // Only load the form hooks once.
1282 1531 $hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
@@ -1285,11 +1534,14 @@
1285 1534 }
1286 1535 }
1287 1536
1288 1537 /**
1289 - * Save all front-end js scripts into a single file
1538 + * Save all front-end js scripts into a single file.
1539 + * And save an additional single file of all front-end Stripe JS scripts.
1290 1540 *
1291 1541 * @since 3.0
1542 + *
1543 + * @return void
1292 1544 */
1293 1545 public static function save_combined_js() {
1294 1546 $file_atts = apply_filters(
1295 1547 'frm_js_location',
@@ -1302,10 +1554,34 @@
1302 1554
1303 1555 $files = array(
1304 1556 self::plugin_path() . '/js/formidable.min.js',
1305 1557 );
1558 + /**
1559 + * @param array $files
1560 + */
1306 1561 $files = apply_filters( 'frm_combined_js_files', $files );
1307 1562 $new_file->combine_files( $files );
1563 +
1564 + // Create the minified Stripe Script.
1565 + $file_atts = apply_filters(
1566 + 'frm_stripe_js_location',
1567 + array(
1568 + 'file_name' => 'frmstrp.min.js',
1569 + 'new_file_path' => self::plugin_path() . '/js',
1570 + )
1571 + );
1572 + $new_file = new FrmCreateFile( $file_atts );
1573 + $files = array(
1574 + FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.min.js',
1575 + );
1576 +
1577 + /**
1578 + * @since 6.5
1579 + *
1580 + * @param array $files
1581 + */
1582 + $files = apply_filters( 'frm_stripe_combined_js_files', $files );
1583 + $new_file->combine_files( $files );
1308 1584 }
1309 1585
1310 1586 /**
1311 1587 * Check a value from a shortcode to see if true or false.
@@ -1312,14 +1588,14 @@
1312 1588 * True when value is 1, true, 'true', 'yes'
1313 1589 *
1314 1590 * @since 1.07.10
1315 1591 *
1316 - * @param string $value The value to compare
1592 + * @param string $value The value to compare.
1317 1593 *
1318 - * @return boolean True or False
1594 + * @return bool
1319 1595 */
1320 1596 public static function is_true( $value ) {
1321 - return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
1597 + return true === $value || 1 == $value || 'true' === $value || 'yes' === $value;
1322 1598 }
1323 1599
1324 1600 /**
1325 1601 * Gets all post from a specific post type.
@@ -1385,9 +1661,9 @@
1385 1661
1386 1662 wp_enqueue_script( 'jquery-ui-autocomplete' );
1387 1663
1388 1664 $selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
1389 - $title = '';
1665 + $title = '';
1390 1666
1391 1667 if ( $selected ) {
1392 1668 $title = get_the_title( $selected );
1393 1669 }
@@ -1403,11 +1679,11 @@
1403 1679 <?php
1404 1680 }
1405 1681
1406 1682 /**
1407 - * @param array $args
1408 - * @param string $page_id Deprecated.
1409 - * @param boolean $truncate Deprecated.
1683 + * @param array $args
1684 + * @param string $page_id Deprecated.
1685 + * @param bool $truncate Deprecated.
1410 1686 */
1411 1687 public static function wp_pages_dropdown( $args = array(), $page_id = '', $truncate = false ) {
1412 1688 self::prep_page_dropdown_params( $page_id, $truncate, $args );
1413 1689
@@ -1451,13 +1727,13 @@
1451 1727 * @since 4.10.01 Added `post_type` and `autocomplete_placeholder` to the arguments array.
1452 1728 */
1453 1729 private static function preformat_selection_args( $args ) {
1454 1730 $defaults = array(
1455 - 'truncate' => false,
1456 - 'placeholder' => ' ',
1457 - 'field_name' => '',
1458 - 'page_id' => '',
1459 - 'post_type' => 'page',
1731 + 'truncate' => false,
1732 + 'placeholder' => ' ',
1733 + 'field_name' => '',
1734 + 'page_id' => '',
1735 + 'post_type' => 'page',
1460 1736 'autocomplete_placeholder' => __( 'Select a Page', 'formidable' ),
1461 1737 );
1462 1738
1463 1739 return array_merge( $defaults, $args );
@@ -1528,25 +1804,16 @@
1528 1804 return self::is_admin_page( 'formidable-views-editor' );
1529 1805 }
1530 1806
1531 1807 /**
1532 - * @since 4.0
1533 - * @deprecated 5.5.3
1808 + * @param string $field_name
1809 + * @param array|string $capability
1810 + * @param string $multiple 'single' and 'multiple'.
1534 1811 */
1535 - public static function maybe_full_screen_link( $link ) {
1536 - _deprecated_function( __METHOD__, '5.5.3' );
1537 - return $link;
1538 - }
1539 -
1540 - /**
1541 - * @param string $field_name
1542 - * @param string|array $capability
1543 - * @param string $multiple 'single' and 'multiple'
1544 - */
1545 1812 public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
1546 1813 ?>
1547 1814 <select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>"
1548 - <?php echo ( 'multiple' === $multiple ) ? 'multiple="multiple"' : ''; ?>
1815 + <?php echo 'multiple' === $multiple ? 'multiple="multiple"' : ''; ?>
1549 1816 class="frm_multiselect">
1550 1817 <?php self::roles_options( $capability ); ?>
1551 1818 </select>
1552 1819 <?php
@@ -1554,9 +1821,9 @@
1554 1821
1555 1822 /**
1556 1823 * @since 4.07
1557 1824 * @param array|string $selected
1558 - * @param string $current
1825 + * @param string $current
1559 1826 */
1560 1827 private static function selected( $selected, $current ) {
1561 1828 if ( is_callable( 'FrmProAppHelper::selected' ) ) {
1562 1829 FrmProAppHelper::selected( $selected, $current );
@@ -1565,9 +1832,9 @@
1565 1832 }
1566 1833 }
1567 1834
1568 1835 /**
1569 - * @param string|array $capability
1836 + * @param array|string $capability
1570 1837 */
1571 1838 public static function roles_options( $capability ) {
1572 1839 global $frm_vars;
1573 1840 if ( isset( $frm_vars['editable_roles'] ) ) {
@@ -1579,9 +1846,9 @@
1579 1846
1580 1847 foreach ( $editable_roles as $role => $details ) {
1581 1848 $name = translate_user_role( $details['name'] );
1582 1849 ?>
1583 - <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_attr( $name ); ?> </option>
1850 + <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_html( $name ); ?> </option>
1584 1851 <?php
1585 1852 unset( $role, $details );
1586 1853 }
1587 1854 }
@@ -1602,9 +1869,8 @@
1602 1869 $pro_cap = array(
1603 1870 'frm_create_entries' => __( 'Add Entries from Admin Area', 'formidable' ),
1604 1871 'frm_edit_entries' => __( 'Edit Entries from Admin Area', 'formidable' ),
1605 1872 'frm_view_reports' => __( 'View Reports', 'formidable' ),
1606 - 'frm_edit_displays' => __( 'Add/Edit Views', 'formidable' ),
1607 1873 );
1608 1874 /**
1609 1875 * @since 5.3.1
1610 1876 *
@@ -1611,8 +1877,14 @@
1611 1877 * @param array<string,string> $pro_cap
1612 1878 */
1613 1879 $pro_cap = apply_filters( 'frm_pro_capabilities', $pro_cap );
1614 1880
1881 + if ( ! array_key_exists( 'frm_edit_displays', $pro_cap ) && is_callable( 'FrmProAppHelper::views_is_installed' ) && FrmProAppHelper::views_is_installed() ) {
1882 + // For backward compatibility, add the Add/Edit Views permission if Pro is not up to date.
1883 + // This was added in 6.5.4. Remove this in the future.
1884 + $pro_cap['frm_edit_displays'] = __( 'Add/Edit Views', 'formidable' );
1885 + }
1886 +
1615 1887 if ( 'pro_only' === $type ) {
1616 1888 return $pro_cap;
1617 1889 }
1618 1890
@@ -1627,9 +1899,9 @@
1627 1899 * @return array<string,string>
1628 1900 */
1629 1901 private static function get_lite_capabilities() {
1630 1902 return array(
1631 - 'frm_view_forms' => __( 'View Forms', 'formidable' ),
1903 + 'frm_view_forms' => __( 'View Forms List', 'formidable' ),
1632 1904 'frm_edit_forms' => __( 'Add and Edit Forms', 'formidable' ),
1633 1905 'frm_delete_forms' => __( 'Delete Forms', 'formidable' ),
1634 1906 'frm_change_settings' => __( 'Access this Settings Page', 'formidable' ),
1635 1907 'frm_view_entries' => __( 'View Entries from Admin Area', 'formidable' ),
@@ -1670,9 +1942,9 @@
1670 1942 return current_user_can( $role );
1671 1943 }
1672 1944
1673 1945 /**
1674 - * @param string|array $needed_role
1946 + * @param array|string $needed_role
1675 1947 * @return bool
1676 1948 */
1677 1949 public static function user_has_permission( $needed_role ) {
1678 1950 if ( is_array( $needed_role ) ) {
@@ -1728,8 +2000,11 @@
1728 2000 /**
1729 2001 * Make sure admins have permission to see the menu items
1730 2002 *
1731 2003 * @since 2.0.6
2004 + *
2005 + * @param string $cap
2006 + * @return void
1732 2007 */
1733 2008 public static function force_capability( $cap = 'frm_change_settings' ) {
1734 2009 if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
1735 2010 $role = get_role( 'administrator' );
@@ -1740,9 +2015,9 @@
1740 2015 }
1741 2016 }
1742 2017
1743 2018 /**
1744 - * Check if the user has permision for action.
2019 + * Check if the user has permission for action.
1745 2020 * Return permission message and stop the action if no permission
1746 2021 *
1747 2022 * @since 2.0
1748 2023 *
@@ -1778,9 +2053,9 @@
1778 2053 if ( empty( $nonce_name ) ) {
1779 2054 return $error;
1780 2055 }
1781 2056
1782 - $nonce_value = ( $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
2057 + $nonce_value = $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
1783 2058 if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $nonce_value, $nonce ) ) ) {
1784 2059 $frm_settings = self::get_settings();
1785 2060 $error = $frm_settings->admin_permission;
1786 2061 }
@@ -1794,12 +2069,13 @@
1794 2069 }
1795 2070 }
1796 2071
1797 2072 public static function check_selected( $values, $current ) {
1798 - $values = self::recursive_function_map( $values, 'trim' );
1799 - $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1800 - $current = htmlspecialchars_decode( trim( $current ) );
2073 + $values = self::recursive_function_map( $values, 'trim' );
2074 + $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1801 2075
2076 + $current = is_null( $current ) ? '' : htmlspecialchars_decode( trim( $current ) );
2077 +
1802 2078 return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
1803 2079 }
1804 2080
1805 2081 public static function recursive_function_map( $value, $function ) {
@@ -1819,8 +2095,9 @@
1819 2095 }
1820 2096 }
1821 2097 }
1822 2098 } else {
2099 + $value = self::maybe_update_value_if_null( $value, $function );
1823 2100 $value = call_user_func( $function, $value );
1824 2101 }
1825 2102
1826 2103 return $value;
@@ -1825,8 +2102,24 @@
1825 2102
1826 2103 return $value;
1827 2104 }
1828 2105
2106 + /**
2107 + * Updates value to empty string if it is null and being passed to a string function.
2108 + *
2109 + * @since 6.8.4
2110 + * @param mixed $value
2111 + * @param string $function
2112 + * @return mixed
2113 + */
2114 + private static function maybe_update_value_if_null( $value, $function ) {
2115 + if ( null === $value && in_array( $function, array( 'trim', 'strlen' ), true ) ) {
2116 + $value = '';
2117 + }
2118 +
2119 + return $value;
2120 + }
2121 +
1829 2122 public static function is_assoc( $array ) {
1830 2123 return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
1831 2124 }
1832 2125
@@ -1837,14 +2130,12 @@
1837 2130 $return = array();
1838 2131 foreach ( $array as $key => $value ) {
1839 2132 if ( is_array( $value ) ) {
1840 2133 $return = array_merge( $return, self::array_flatten( $value, $keys ) );
2134 + } elseif ( $keys === 'keep' ) {
2135 + $return[ $key ] = $value;
1841 2136 } else {
1842 - if ( $keys == 'keep' ) {
1843 - $return[ $key ] = $value;
1844 - } else {
1845 - $return[] = $value;
1846 - }
2137 + $return[] = $value;
1847 2138 }
1848 2139 }
1849 2140
1850 2141 return $return;
@@ -1849,8 +2140,27 @@
1849 2140
1850 2141 return $return;
1851 2142 }
1852 2143
2144 + /**
2145 + * Flatten an array before imploding it to avoid Array to string conversion warnings.
2146 + *
2147 + * @since 6.16.1
2148 + *
2149 + * @param string $sep
2150 + * @param array $array
2151 + * @return string
2152 + */
2153 + public static function safe_implode( $sep, $array ) {
2154 + $array = self::array_flatten( $array );
2155 + return implode( $sep, $array );
2156 + }
2157 +
2158 + /**
2159 + * @param string $text
2160 + * @param bool $is_rich_text
2161 + * @return string
2162 + */
1853 2163 public static function esc_textarea( $text, $is_rich_text = false ) {
1854 2164 $safe_text = str_replace( '&quot;', '"', $text );
1855 2165 if ( ! $is_rich_text ) {
1856 2166 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
@@ -1856,9 +2166,13 @@
1856 2166 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
1857 2167 }
1858 2168 $safe_text = str_replace( '&amp; ', '& ', $safe_text );
1859 2169
1860 - return apply_filters( 'esc_textarea', $safe_text, $text );
2170 + /**
2171 + * @param string $safe_text
2172 + * @param string $text
2173 + */
2174 + return (string) apply_filters( 'esc_textarea', $safe_text, $text );
1861 2175 }
1862 2176
1863 2177 /**
1864 2178 * Add auto paragraphs to text areas
@@ -1909,12 +2223,12 @@
1909 2223 * @since 5.0.13 added $echo param.
1910 2224 *
1911 2225 * @param string $url
1912 2226 * @param bool $echo
1913 - * @return string|void
2227 + * @return string|null
1914 2228 */
1915 2229 public static function js_redirect( $url, $echo = false ) {
1916 - $callback = function() use ( $url ) {
2230 + $callback = function () use ( $url ) {
1917 2231 echo '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
1918 2232 };
1919 2233 return self::clip( $callback, $echo );
1920 2234 }
@@ -1924,9 +2238,9 @@
1924 2238 return $user_id;
1925 2239 }
1926 2240
1927 2241 $user_id = sanitize_text_field( $user_id );
1928 - if ( $user_id == 'current' ) {
2242 + if ( $user_id === 'current' ) {
1929 2243 $user_id = get_current_user_id();
1930 2244 } else {
1931 2245 if ( is_email( $user_id ) ) {
1932 2246 $user = get_user_by( 'email', $user_id );
@@ -1942,8 +2256,13 @@
1942 2256
1943 2257 return $user_id;
1944 2258 }
1945 2259
2260 + /**
2261 + * @param string $filename
2262 + * @param array $atts
2263 + * @return false|string
2264 + */
1946 2265 public static function get_file_contents( $filename, $atts = array() ) {
1947 2266 if ( ! is_file( $filename ) ) {
1948 2267 return false;
1949 2268 }
@@ -1949,9 +2268,9 @@
1949 2268 }
1950 2269
1951 2270 extract( $atts ); // phpcs:ignore WordPress.PHP.DontExtract
1952 2271 ob_start();
1953 - include( $filename );
2272 + include $filename;
1954 2273 $contents = ob_get_contents();
1955 2274 ob_end_clean();
1956 2275
1957 2276 return $contents;
@@ -2006,9 +2325,9 @@
2006 2325 ++$suffix;
2007 2326 } while ( in_array( $key_check, $similar_keys, true ) );
2008 2327
2009 2328 $key = $key_check;
2010 - }
2329 + }//end if
2011 2330
2012 2331 return $key;
2013 2332 }
2014 2333
@@ -2052,9 +2371,11 @@
2052 2371 * @return string
2053 2372 */
2054 2373 private static function generate_new_key( $num_chars ) {
2055 2374 $max_slug_value = pow( 36, $num_chars );
2056 - $min_slug_value = 37; // we want to have at least 2 characters in the slug
2375 +
2376 + // We want to have at least 2 characters in the slug.
2377 + $min_slug_value = 37;
2057 2378 return base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
2058 2379 }
2059 2380
2060 2381 /**
@@ -2083,11 +2404,16 @@
2083 2404
2084 2405 /**
2085 2406 * Editing a Form or Entry
2086 2407 *
2087 - * @param string $table
2408 + * @param object $record
2409 + * @param string $table
2410 + * @param array|string $fields
2411 + * @param bool $default
2412 + * @param array $post_values
2413 + * @param array $args
2088 2414 *
2089 - * @return bool|array
2415 + * @return array|bool
2090 2416 */
2091 2417 public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
2092 2418 if ( ! $record ) {
2093 2419 return false;
@@ -2140,13 +2466,12 @@
2140 2466 $post_values = $args['post_values'];
2141 2467
2142 2468 if ( $args['default'] ) {
2143 2469 $meta_value = $field->default_value;
2144 - } else {
2145 - if ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
2146 - if ( ! isset( $field->field_options['custom_field'] ) ) {
2147 - $field->field_options['custom_field'] = '';
2148 - }
2470 + } elseif ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
2471 + if ( ! isset( $field->field_options['custom_field'] ) ) {
2472 + $field->field_options['custom_field'] = '';
2473 + }
2149 2474 $meta_value = FrmProEntryMetaHelper::get_post_value(
2150 2475 $record->post_id,
2151 2476 $field->field_options['post_field'],
2152 2477 $field->field_options['custom_field'],
@@ -2156,12 +2481,11 @@
2156 2481 'form_id' => $field->form_id,
2157 2482 'field' => $field,
2158 2483 )
2159 2484 );
2160 - } else {
2161 - $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2162 - }
2163 - }
2485 + } else {
2486 + $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2487 + }//end if
2164 2488
2165 2489 $field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
2166 2490 if ( isset( $post_values['item_meta'][ $field->id ] ) ) {
2167 2491 $new_value = $post_values['item_meta'][ $field->id ];
@@ -2209,12 +2533,15 @@
2209 2533 );
2210 2534 }
2211 2535
2212 2536 /**
2537 + * @param object $record
2213 2538 * @param string $table
2539 + * @param array $post_values
2540 + * @param array $values
2214 2541 */
2215 2542 private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
2216 - if ( $table == 'entries' ) {
2543 + if ( $table === 'entries' ) {
2217 2544 $form = $record->form_id;
2218 2545 FrmForm::maybe_get_form( $form );
2219 2546 } else {
2220 2547 $form = $record;
@@ -2250,9 +2577,9 @@
2250 2577 $form_defaults = FrmFormsHelper::get_default_opts();
2251 2578
2252 2579 foreach ( $form_defaults as $opt => $default ) {
2253 2580 if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
2254 - $values[ $opt ] = ( $post_values && isset( $post_values['options'][ $opt ] ) ) ? $post_values['options'][ $opt ] : $default;
2581 + $values[ $opt ] = $post_values && isset( $post_values['options'][ $opt ] ) ? $post_values['options'][ $opt ] : $default;
2255 2582 }
2256 2583
2257 2584 unset( $opt, $default );
2258 2585 }
@@ -2273,9 +2600,9 @@
2273 2600 * @since 2.2.10
2274 2601 *
2275 2602 * @param array $post_values
2276 2603 *
2277 - * @return boolean|int
2604 + * @return bool|int
2278 2605 */
2279 2606 public static function custom_style_value( $post_values ) {
2280 2607 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2281 2608 $custom_style = absint( $post_values['options']['custom_style'] );
@@ -2280,29 +2607,37 @@
2280 2607 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2281 2608 $custom_style = absint( $post_values['options']['custom_style'] );
2282 2609 } else {
2283 2610 $frm_settings = self::get_settings();
2284 - $custom_style = ( $frm_settings->load_style != 'none' );
2611 + $custom_style = ( $frm_settings->load_style !== 'none' );
2285 2612 }
2286 2613
2287 2614 return $custom_style;
2288 2615 }
2289 2616
2290 - public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
2291 - if ( is_array( $str ) ) {
2617 + /**
2618 + * @param mixed $original_string
2619 + * @param int|string $length
2620 + * @param int $minword
2621 + * @param string $continue
2622 + * @return string
2623 + */
2624 + public static function truncate( $original_string, $length, $minword = 3, $continue = '...' ) {
2625 + if ( ! is_string( $original_string ) && ! is_int( $original_string ) ) {
2292 2626 return '';
2293 2627 }
2294 2628
2295 2629 $length = (int) $length;
2296 - $str = wp_strip_all_tags( $str );
2630 + $str = wp_strip_all_tags( (string) $original_string );
2297 2631 $original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
2298 2632
2299 2633 if ( $length == 0 ) {
2300 2634 return '';
2301 - } elseif ( $length <= 10 ) {
2635 + }
2636 +
2637 + if ( $length <= 10 ) {
2302 2638 $sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
2303 -
2304 - return $sub . ( ( $length < $original_len ) ? $continue : '' );
2639 + return $sub . ( $length < $original_len ? $continue : '' );
2305 2640 }
2306 2641
2307 2642 $sub = '';
2308 2643 $len = 0;
@@ -2308,10 +2643,14 @@
2308 2643 $len = 0;
2309 2644
2310 2645 $words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
2311 2646
2647 + if ( ! is_array( $words ) ) {
2648 + return $original_string;
2649 + }
2650 +
2312 2651 foreach ( $words as $word ) {
2313 - $part = ( ( $sub != '' ) ? ' ' : '' ) . $word;
2652 + $part = ( $sub != '' ? ' ' : '' ) . $word;
2314 2653 $total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
2315 2654 if ( $total_len > $length && substr_count( $sub, ' ' ) ) {
2316 2655 break;
2317 2656 }
@@ -2325,11 +2664,37 @@
2325 2664
2326 2665 unset( $total_len, $word );
2327 2666 }
2328 2667
2329 - return $sub . ( ( $len < $original_len ) ? $continue : '' );
2668 + $sub = self::maybe_force_truncate_on_string_with_no_spaces( $sub, $length );
2669 +
2670 + return $sub . ( $len < $original_len ? $continue : '' );
2330 2671 }
2331 2672
2673 + /**
2674 + * If the string is still too long because there may not have been any spaces, force truncate.
2675 + *
2676 + * @since 6.5.4
2677 + *
2678 + * @param string $sub Current substring.
2679 + * @param int $length The length limit.
2680 + * @return string
2681 + */
2682 + private static function maybe_force_truncate_on_string_with_no_spaces( $sub, $length ) {
2683 + if ( strlen( $sub ) < $length + 50 ) {
2684 + // If the string isn't way over the limit, leave it.
2685 + return $sub;
2686 + }
2687 +
2688 + $first_space = strpos( $sub, ' ', $length );
2689 + if ( false !== $first_space ) {
2690 + // Ignore anything with spaces.
2691 + return $sub;
2692 + }
2693 +
2694 + return substr( $sub, 0, $length + 10 );
2695 + }
2696 +
2332 2697 public static function mb_function( $function_names, $args ) {
2333 2698 $mb_function_name = $function_names[0];
2334 2699 $function_name = $function_names[1];
2335 2700 if ( function_exists( $mb_function_name ) ) {
@@ -2362,8 +2727,13 @@
2362 2727
2363 2728 return $formatted;
2364 2729 }
2365 2730
2731 + /**
2732 + * @param string $time_format
2733 + * @param string $date
2734 + * @return string
2735 + */
2366 2736 private static function add_time_to_date( $time_format, $date ) {
2367 2737 if ( empty( $time_format ) ) {
2368 2738 $time_format = get_option( 'time_format' );
2369 2739 }
@@ -2386,12 +2756,12 @@
2386 2756 return date_i18n( $date_format, strtotime( $date ) );
2387 2757 }
2388 2758
2389 2759 /**
2390 - * Gets the time ago in words
2760 + * Gets the time ago in words.
2391 2761 *
2392 - * @param int $from in seconds
2393 - * @param int|string $to in seconds
2762 + * @param int $from In seconds.
2763 + * @param int|string $to In seconds.
2394 2764 *
2395 2765 * @return string $time_ago
2396 2766 */
2397 2767 public static function human_time_diff( $from, $to = '', $levels = 1 ) {
@@ -2406,9 +2776,9 @@
2406 2776 $diff_object = $now->diff( $ago );
2407 2777 $diff = get_object_vars( $diff_object );
2408 2778
2409 2779 // Add week amount and update day amount
2410 - $diff['w'] = floor( $diff['d'] / 7 );
2780 + $diff['w'] = floor( $diff['d'] / 7 );
2411 2781 $diff['d'] -= $diff['w'] * 7;
2412 2782
2413 2783 $time_strings = self::get_time_strings();
2414 2784
@@ -2415,9 +2785,9 @@
2415 2785 if ( ! is_numeric( $levels ) ) {
2416 2786 // Show time in specified unit.
2417 2787 $levels = self::get_unit( $levels );
2418 2788 if ( isset( $time_strings[ $levels ] ) ) {
2419 - $diff = array(
2789 + $diff = array(
2420 2790 $levels => self::time_format( $levels, $diff ),
2421 2791 );
2422 2792 $time_strings = array(
2423 2793 $levels => $time_strings[ $levels ],
@@ -2506,9 +2876,9 @@
2506 2876 }
2507 2877
2508 2878 /**
2509 2879 * Get the translatable time strings. The untranslated version is a failsafe
2510 - * in case langauges are changing for the unit set in the shortcode.
2880 + * in case languages are changing for the unit set in the shortcode.
2511 2881 *
2512 2882 * @since 2.0.20
2513 2883 * @return array
2514 2884 */
@@ -2554,23 +2924,28 @@
2554 2924
2555 2925 // Pagination Methods.
2556 2926
2557 2927 /**
2558 - * @param integer $current_p
2928 + * @param int $r_count
2929 + * @param int $current_p
2930 + * @param int $p_size
2931 + * @return int
2559 2932 */
2560 2933 public static function get_last_record_num( $r_count, $current_p, $p_size ) {
2561 - return ( ( $r_count < ( $current_p * $p_size ) ) ? $r_count : ( $current_p * $p_size ) );
2934 + return ( $r_count < $current_p * $p_size ? $r_count : $current_p * $p_size );
2562 2935 }
2563 2936
2564 2937 /**
2565 - * @param integer $current_p
2938 + * @param int $r_count
2939 + * @param int $current_p
2940 + * @param int $p_size
2941 + * @return int
2566 2942 */
2567 2943 public static function get_first_record_num( $r_count, $current_p, $p_size ) {
2568 2944 if ( $current_p == 1 ) {
2569 2945 return 1;
2570 - } else {
2571 - return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
2572 2946 }
2947 + return self::get_last_record_num( $r_count, $current_p - 1, $p_size ) + 1;
2573 2948 }
2574 2949
2575 2950 /**
2576 2951 * @return array
@@ -2593,9 +2968,9 @@
2593 2968 if ( ! isset( $l3 ) ) {
2594 2969 $l3 = $name;
2595 2970 }
2596 2971
2597 - $this_val = ( $p == $last ) ? $jv['value'] : array();
2972 + $this_val = $p == $last ? $jv['value'] : array();
2598 2973
2599 2974 switch ( $p ) {
2600 2975 case 0:
2601 2976 $l1 = $name;
@@ -2617,12 +2992,12 @@
2617 2992 self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
2618 2993 }
2619 2994
2620 2995 unset( $this_val, $n );
2621 - }
2996 + }//end foreach
2622 2997
2623 2998 unset( $last, $jv );
2624 - }
2999 + }//end foreach
2625 3000
2626 3001 return $vars;
2627 3002 }
2628 3003
@@ -2647,8 +3022,9 @@
2647 3022 'reply_to' => __( 'If you would like a different reply to address than the "from" address, add a single address here. FORMAT: Name <name@email.com> or name@email.com.', 'formidable' ),
2648 3023 'from' => __( 'Enter the name and/or email address of the sender. FORMAT: John Bates <john@example.com> or john@example.com.', 'formidable' ),
2649 3024 /* translators: %1$s: Form name, %2$s: Date */
2650 3025 'email_subject' => esc_attr( sprintf( __( 'If you leave the subject blank, the default will be used: %1$s Form submitted on %2$s', 'formidable' ), $form_name, self::site_name() ) ),
3026 + 'new_tab' => __( 'This option will open the link in a new browser tab. Please note that some popup blockers may prevent this from happening, in which case the link will be displayed.', 'formidable' ),
2651 3027 );
2652 3028
2653 3029 if ( ! isset( $tooltips[ $name ] ) ) {
2654 3030 return;
@@ -2869,8 +3245,11 @@
2869 3245 }
2870 3246
2871 3247 /**
2872 3248 * @since 4.02.03
3249 + *
3250 + * @param array|string $value
3251 + * @return string
2873 3252 */
2874 3253 public static function maybe_json_encode( $value ) {
2875 3254 if ( is_array( $value ) ) {
2876 3255 $value = wp_json_encode( $value );
@@ -2878,12 +3257,14 @@
2878 3257 return $value;
2879 3258 }
2880 3259
2881 3260 /**
3261 + * Echo The javascript to open and highlight the Formidable menu
3262 + *
2882 3263 * @since 1.07.10
2883 3264 *
2884 - * @param string $post_type The name of the post type that may need to be highlighted
2885 - * echo The javascript to open and highlight the Formidable menu
3265 + * @param string $post_type The name of the post type that may need to be highlighted.
3266 + * @return void
2886 3267 */
2887 3268 public static function maybe_highlight_menu( $post_type ) {
2888 3269 global $post;
2889 3270
@@ -2902,8 +3283,11 @@
2902 3283 /**
2903 3284 * Load the JS file on non-Formidable pages in the admin area
2904 3285 *
2905 3286 * @since 2.0
3287 + *
3288 + * @param bool $load
3289 + * @return void
2906 3290 */
2907 3291 public static function load_admin_wide_js( $load = true ) {
2908 3292 $version = self::plugin_version();
2909 3293 wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
@@ -2917,8 +3301,9 @@
2917 3301 'canAccessApplicationDashboard' => current_user_can( is_callable( 'FrmProApplicationsHelper::get_required_templates_capability' ) ? FrmProApplicationsHelper::get_required_templates_capability() : 'frm_edit_forms' ),
2918 3302 'loading' => __( 'Loading&hellip;', 'formidable' ),
2919 3303 'nonce' => wp_create_nonce( 'frm_ajax' ),
2920 3304 'proIncludesSliderJs' => is_callable( 'FrmProFormsHelper::prepare_custom_currency' ),
3305 + 'inboxSlideIn' => FrmInbox::get_inbox_slide_in_value_for_js(),
2921 3306 );
2922 3307 wp_localize_script( 'formidable_admin_global', 'frmGlobal', $global_strings );
2923 3308
2924 3309 if ( $load ) {
@@ -2927,8 +3312,9 @@
2927 3312 }
2928 3313
2929 3314 /**
2930 3315 * @since 2.0.9
3316 + * @return void
2931 3317 */
2932 3318 public static function load_font_style() {
2933 3319 wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
2934 3320 }
@@ -2934,99 +3320,133 @@
2934 3320 }
2935 3321
2936 3322 /**
2937 3323 * @param string $location
3324 + * @return void
2938 3325 */
2939 3326 public static function localize_script( $location ) {
2940 - global $wp_scripts;
3327 + global $wp_scripts, $wp_version;
2941 3328
2942 - $ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
2943 - $ajax_url = apply_filters( 'frm_ajax_url', $ajax_url );
2944 -
2945 3329 $script_strings = array(
2946 - 'ajax_url' => $ajax_url,
2947 - 'images_url' => self::plugin_url() . '/images',
2948 - 'loading' => __( 'Loading&hellip;', 'formidable' ),
2949 - 'remove' => __( 'Remove', 'formidable' ),
2950 - 'offset' => apply_filters( 'frm_scroll_offset', 4 ),
2951 - 'nonce' => wp_create_nonce( 'frm_ajax' ),
2952 - 'id' => __( 'ID', 'formidable' ),
2953 - 'no_results' => __( 'No results match', 'formidable' ),
2954 - 'file_spam' => __( 'That file looks like Spam.', 'formidable' ),
2955 - 'calc_error' => __( 'There is an error in the calculation in the field with key', 'formidable' ),
2956 - 'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
2957 - 'focus_first_error' => self::should_focus_first_error(),
2958 - 'include_alert_role' => self::should_include_alert_role_on_field_errors(),
3330 + 'ajax_url' => esc_url_raw( self::get_ajax_url() ),
3331 + 'images_url' => self::plugin_url() . '/images',
3332 + 'loading' => __( 'Loading&hellip;', 'formidable' ),
3333 + 'remove' => __( 'Remove', 'formidable' ),
3334 + 'offset' => apply_filters( 'frm_scroll_offset', 4 ),
3335 + 'nonce' => wp_create_nonce( 'frm_ajax' ),
3336 + 'id' => __( 'ID', 'formidable' ),
3337 + 'no_results' => __( 'No results match', 'formidable' ),
3338 + 'file_spam' => __( 'That file looks like Spam.', 'formidable' ),
3339 + 'calc_error' => __( 'There is an error in the calculation in the field with key', 'formidable' ),
3340 + 'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
3341 + 'focus_first_error' => self::should_focus_first_error(),
3342 + 'include_alert_role' => self::should_include_alert_role_on_field_errors(),
3343 + // We need to keep this setting for a few versions because Pro checks for this.
3344 + 'include_resend_email' => false,
2959 3345 );
2960 3346
2961 3347 $data = $wp_scripts->get_data( 'formidable', 'data' );
2962 - if ( empty( $data ) ) {
3348 + if ( ! $data ) {
2963 3349 wp_localize_script( 'formidable', 'frm_js', $script_strings );
2964 3350 }
2965 3351
2966 - if ( $location == 'admin' ) {
2967 - $frm_settings = self::get_settings();
3352 + if ( $location === 'admin' ) {
2968 3353 $admin_script_strings = array(
2969 - 'desc' => __( '(Click to add description)', 'formidable' ),
2970 - 'blank' => __( '(Blank)', 'formidable' ),
2971 - 'no_label' => __( '(no label)', 'formidable' ),
2972 - 'saving' => '', // Deprecated in 6.0.
2973 - 'saved' => '', // Deprecated in 6.0.
2974 - 'ok' => __( 'OK', 'formidable' ),
2975 - 'cancel' => __( 'Cancel', 'formidable' ),
2976 - 'default_label' => __( 'Default', 'formidable' ),
2977 - 'clear_default' => __( 'Clear default value when typing', 'formidable' ),
2978 - 'no_clear_default' => __( 'Do not clear default value when typing', 'formidable' ),
2979 - 'valid_default' => __( 'Default value will pass form validation', 'formidable' ),
2980 - 'no_valid_default' => __( 'Default value will NOT pass form validation', 'formidable' ),
2981 - 'confirm' => __( 'Are you sure?', 'formidable' ),
2982 - 'conf_delete' => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
2983 - 'conf_delete_sec' => __( 'All fields inside this Section will be deleted along with their data. Are you sure you want to delete this group of fields?', 'formidable' ),
2984 - 'conf_no_repeat' => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
2985 - 'default_unique' => $frm_settings->unique_msg,
2986 - 'default_conf' => __( 'The entered values do not match', 'formidable' ),
2987 - 'enter_email' => __( 'Enter Email', 'formidable' ),
2988 - 'confirm_email' => __( 'Confirm Email', 'formidable' ),
2989 - 'conditional_text' => __( 'Conditional content here', 'formidable' ),
2990 - 'new_option' => __( 'New Option', 'formidable' ),
2991 - 'css_invalid_size' => __( 'In certain browsers (e.g. Firefox) text will not display correctly if the field height is too small relative to the field padding and text size. Please increase your field height or decrease your field padding.', 'formidable' ),
2992 - 'enter_password' => __( 'Enter Password', 'formidable' ),
2993 - 'confirm_password' => __( 'Confirm Password', 'formidable' ),
2994 - 'import_complete' => __( 'Import Complete', 'formidable' ),
2995 - 'updating' => __( 'Please wait while your site updates.', 'formidable' ),
2996 - 'no_save_warning' => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
2997 - 'private_label' => __( 'Private', 'formidable' ),
2998 - 'jquery_ui_url' => '',
2999 - 'pro_url' => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
3000 - 'no_licenses' => __( 'No new licenses were found', 'formidable' ),
3001 - 'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3002 - 'view_shortcodes' => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
3003 - 'text_shortcodes' => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
3004 - 'only_one_action' => __( 'This form action is limited to one per form. Please edit the existing form action.', 'formidable' ),
3005 - 'unsafe_params' => FrmFormsHelper::reserved_words(),
3354 + 'desc' => __( '(Click to add description)', 'formidable' ),
3355 + 'blank' => __( '(Blank)', 'formidable' ),
3356 + 'no_label' => __( '(no label)', 'formidable' ),
3357 + 'ok' => __( 'OK', 'formidable' ),
3358 + 'cancel' => __( 'Cancel', 'formidable' ),
3359 + 'default_label' => __( 'Default', 'formidable' ),
3360 + 'clear_default' => __( 'Clear default value when typing', 'formidable' ),
3361 + 'no_clear_default' => __( 'Do not clear default value when typing', 'formidable' ),
3362 + 'valid_default' => __( 'Default value will pass form validation', 'formidable' ),
3363 + 'no_valid_default' => __( 'Default value will NOT pass form validation', 'formidable' ),
3364 + 'confirm' => __( 'Are you sure?', 'formidable' ),
3365 + 'conf_delete' => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
3366 + 'conf_delete_sec' => __( 'All fields inside this Section will be deleted along with their data. Are you sure you want to delete this group of fields?', 'formidable' ),
3367 + 'conf_no_repeat' => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
3368 + 'default_unique' => FrmFieldsHelper::default_unique_msg(),
3369 + 'default_conf' => __( 'The entered values do not match', 'formidable' ),
3370 + 'enter_email' => __( 'Enter Email', 'formidable' ),
3371 + 'confirm_email' => __( 'Confirm Email', 'formidable' ),
3372 + 'conditional_text' => __( 'Conditional content here', 'formidable' ),
3373 + 'new_option' => __( 'New Option', 'formidable' ),
3374 + 'css_invalid_size' => __( 'In certain browsers (e.g. Firefox) text will not display correctly if the field height is too small relative to the field padding and text size. Please increase your field height or decrease your field padding.', 'formidable' ),
3375 + 'enter_password' => __( 'Enter Password', 'formidable' ),
3376 + 'confirm_password' => __( 'Confirm Password', 'formidable' ),
3377 + 'import_complete' => __( 'Import Complete', 'formidable' ),
3378 + 'updating' => __( 'Please wait while your site updates.', 'formidable' ),
3379 + 'no_save_warning' => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
3380 + 'private_label' => __( 'Private', 'formidable' ),
3381 + 'jquery_ui_url' => '',
3382 + 'pro_url' => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
3383 + 'no_licenses' => __( 'No new licenses were found', 'formidable' ),
3384 + 'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3385 + 'view_shortcodes' => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
3386 + 'text_shortcodes' => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
3387 + /* translators: %d is the number of allowed actions per form */
3388 + 'only_one_action' => sprintf( __( 'This form action is limited to %d per form.', 'formidable' ), 1 ),
3389 + 'edit_action_text' => __( 'Please edit the existing form action.', 'formidable' ),
3390 + 'unsafe_params' => FrmFormsHelper::reserved_words(),
3006 3391 /* Translators: %s is the name of a Detail Page Slug that is a reserved word.*/
3007 - 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ),
3392 + 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ),
3008 3393 /* Translators: %s is the name of a parameter that is a reserved word. More than one word could be listed here, though that would not be common. */
3009 - 'param_is_reserved' => sprintf( __( 'The parameter "%s" is reserved by WordPress. This may cause problems when included in the URL. Is this intentional? ', 'formidable' ), '****' ),
3010 - 'reserved_words' => __( 'See the list of reserved words in WordPress.', 'formidable' ),
3011 - 'repeat_limit_min' => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
3012 - 'checkbox_limit' => __( 'Please select a limit between 0 and 200.', 'formidable' ),
3013 - 'install' => __( 'Install', 'formidable' ),
3014 - 'active' => __( 'Active', 'formidable' ),
3015 - 'select_a_field' => __( 'Select a Field', 'formidable' ),
3016 - 'no_items_found' => __( 'No items found.', 'formidable' ),
3017 - 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
3394 + 'param_is_reserved' => sprintf( __( 'The parameter "%s" is reserved by WordPress. This may cause problems when included in the URL. Is this intentional? ', 'formidable' ), '****' ),
3395 + 'reserved_words' => __( 'See the list of reserved words in WordPress.', 'formidable' ),
3396 + 'repeat_limit_min' => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
3397 + 'checkbox_limit' => __( 'Please select a limit between 0 and 200.', 'formidable' ),
3398 + 'install' => __( 'Install', 'formidable' ),
3399 + 'active' => __( 'Active', 'formidable' ),
3400 + 'installed' => __( 'Installed', 'formidable' ),
3401 + 'not_installed' => __( 'Not Installed', 'formidable' ),
3402 + 'select_a_field' => __( 'Select a Field', 'formidable' ),
3403 + 'no_items_found' => __( 'No items found.', 'formidable' ),
3404 + 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
3405 +
3406 + // Deprecated in 6.0.
3407 + 'saving' => '',
3408 +
3409 + // Deprecated in 6.0.
3410 + 'saved' => '',
3411 +
3412 + // translators: %1$s: HTML open tag, %2$s: HTML end tag.
3413 + 'holdShiftMsg' => esc_html__( 'You can hold %1$sShift%2$s on your keyboard to select multiple fields', 'formidable' ),
3414 + 'noTitleText' => FrmFormsHelper::get_no_title_text(),
3415 +
3416 + // In older versions this event listener causes the section to immediately close again
3417 + // when the h3 element is clicked. It's only required in WP 6.7+.
3418 + 'requireAccordionTitleClickListener' => version_compare( $wp_version, '6.7', '>=' ),
3018 3419 );
3420 + /**
3421 + * @param array $admin_script_strings
3422 + */
3019 3423 $admin_script_strings = apply_filters( 'frm_admin_script_strings', $admin_script_strings );
3020 3424
3021 3425 $data = $wp_scripts->get_data( 'formidable_admin', 'data' );
3022 - if ( empty( $data ) ) {
3426 + if ( ! $data ) {
3023 3427 wp_localize_script( 'formidable_admin', 'frm_admin_js', $admin_script_strings );
3024 3428 }
3025 - }
3429 + }//end if
3026 3430 }
3027 3431
3028 3432 /**
3433 + * @since 6.5
3434 + *
3435 + * @return string
3436 + */
3437 + public static function get_ajax_url() {
3438 + $ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
3439 +
3440 + /**
3441 + * @since 2.0.13
3442 + *
3443 + * @param string $ajax_url
3444 + */
3445 + return apply_filters( 'frm_ajax_url', $ajax_url );
3446 + }
3447 +
3448 + /**
3029 3449 * Returns whether or not the first errored input should be auto-focused (default true).
3030 3450 *
3031 3451 * @since 5.2.05
3032 3452 *
@@ -3051,9 +3471,10 @@
3051 3471 * Echo the message on the plugins listing page
3052 3472 *
3053 3473 * @since 1.07.10
3054 3474 *
3055 - * @param float $min_version The version the add-on requires
3475 + * @param float $min_version The version the add-on requires.
3476 + * @return void
3056 3477 */
3057 3478 public static function min_version_notice( $min_version ) {
3058 3479 $frm_version = self::plugin_version();
3059 3480
@@ -3087,9 +3508,8 @@
3087 3508 if ( ! $is_pro || self::meets_min_pro_version( $min_version ) ) {
3088 3509 return;
3089 3510 }
3090 3511
3091 - $pro_version = FrmProDb::$plug_version;
3092 3512 $expired = FrmAddonsController::is_license_expired();
3093 3513 ?>
3094 3514 <div class="frm-banner-alert frm_error_style frm_previous_install">
3095 3515 <?php
@@ -3107,8 +3527,11 @@
3107 3527 /**
3108 3528 * If Pro is installed, check the version number.
3109 3529 *
3110 3530 * @since 4.0.01
3531 + *
3532 + * @param string $min_version
3533 + * @return bool
3111 3534 */
3112 3535 public static function meets_min_pro_version( $min_version ) {
3113 3536 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
3114 3537 }
@@ -3113,24 +3536,19 @@
3113 3536 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
3114 3537 }
3115 3538
3116 3539 /**
3117 - * Show a message if the browser or PHP version is below the recommendations.
3540 + * Show a message if the PHP version is below the recommendations.
3118 3541 *
3119 3542 * @since 4.0.02
3543 + * @return void
3120 3544 */
3121 3545 private static function php_version_notice() {
3122 3546 $message = array();
3123 - if ( version_compare( phpversion(), '5.6', '<' ) ) {
3547 + if ( version_compare( phpversion(), '7.0', '<' ) ) {
3124 3548 $message[] = __( 'The version of PHP on your server is too low. If this is not corrected, you may see issues with Formidable Forms. Please contact your web host and ask to be updated to PHP 7.0+.', 'formidable' );
3125 3549 }
3126 3550
3127 - $browser = self::get_server_value( 'HTTP_USER_AGENT' );
3128 - $is_ie = strpos( $browser, 'MSIE' ) !== false;
3129 - if ( $is_ie ) {
3130 - $message[] = __( 'You are using an outdated browser that is not compatible with Formidable Forms. Please update to a more current browser (we recommend Chrome).', 'formidable' );
3131 - }
3132 -
3133 3551 foreach ( $message as $m ) {
3134 3552 ?>
3135 3553 <div class="frm-banner-alert frm_error_style frm_previous_install">
3136 3554 <?php echo esc_html( $m ); ?>
@@ -3260,16 +3678,10 @@
3260 3678 return $locales;
3261 3679 }
3262 3680
3263 3681 /**
3264 - * Output HTML containing reference text for accessibility
3265 - *
3266 - * @deprecated 5.1
3682 + * @return string
3267 3683 */
3268 - public static function multiselect_accessibility() {
3269 - _deprecated_function( __METHOD__, '5.1' );
3270 - }
3271 -
3272 3684 public static function get_menu_icon_class() {
3273 3685 if ( is_callable( 'FrmProAppHelper::get_settings' ) ) {
3274 3686 $settings = FrmProAppHelper::get_settings();
3275 3687 if ( is_object( $settings ) && ! empty( $settings->menu_icon ) ) {
@@ -3379,8 +3791,18 @@
3379 3791 return apply_filters( 'frm_images_dropdown_input_attrs', $input_attrs_str, $args );
3380 3792 }
3381 3793
3382 3794 /**
3795 + * @since 6.7.1
3796 + */
3797 + public static function get_images_dropdown_atts( $option, $args ) {
3798 + $image = self::get_images_dropdown_option_image( $option, $args );
3799 + $classes = self::get_images_dropdown_option_classes( $option, $args );
3800 + $custom_attrs = self::get_images_dropdown_option_html_attrs( $option, $args );
3801 + return compact( 'image', 'classes', 'custom_attrs' );
3802 + }
3803 +
3804 + /**
3383 3805 * Gets the image of each option in images_dropdown() method.
3384 3806 *
3385 3807 * @since 5.0.04
3386 3808 *
@@ -3391,9 +3813,9 @@
3391 3813 private static function get_images_dropdown_option_image( $option, $args ) {
3392 3814 $image = self::icon_by_class(
3393 3815 'frmfont ' . $option['svg'],
3394 3816 array(
3395 - 'echo' => false,
3817 + 'echo' => false,
3396 3818 )
3397 3819 );
3398 3820
3399 3821 $args['option'] = $option;
@@ -3531,15 +3953,15 @@
3531 3953 return $values;
3532 3954 }
3533 3955
3534 3956 /**
3535 - * Some back end fields allow privleged users to add scripts.
3957 + * Some back end fields allow privileged users to add scripts.
3536 3958 * A site that uses the DISALLOW_UNFILTERED_HTML always remove scripts on echo.
3537 3959 *
3538 3960 * @since 5.0.13
3539 3961 *
3540 3962 * @param string $value
3541 - * @param array|string $allowed 'all' for everything included as defaults
3963 + * @param array|string $allowed 'all' for everything included as defaults.
3542 3964 * @return string
3543 3965 */
3544 3966 public static function maybe_kses( $value, $allowed = 'all' ) {
3545 3967 if ( self::should_never_allow_unfiltered_html() ) {
@@ -3548,8 +3970,64 @@
3548 3970 return $value;
3549 3971 }
3550 3972
3551 3973 /**
3974 + * Check if an option attribute used in an [input] shortcode is safe.
3975 + *
3976 + * @since 6.11.2
3977 + *
3978 + * @param string $key
3979 + * @param string $context Either 'display' or 'update'. On update, we want to allow a few keys that are never displayed.
3980 + * @return bool
3981 + */
3982 + public static function input_key_is_safe( $key, $context = 'display' ) {
3983 + if ( 'update' === $context && in_array( $key, array( 'opt', 'label' ), true ) ) {
3984 + $safe = true;
3985 + } elseif ( 0 === strpos( $key, 'data-' ) ) {
3986 + // Allow all data attributes.
3987 + $safe = true;
3988 + } elseif ( 0 === strpos( $key, 'aria-' ) ) {
3989 + // Allow all aria attributes.
3990 + $safe = true;
3991 + } else {
3992 + $safe_keys = array(
3993 + 'class',
3994 + 'required',
3995 + 'title',
3996 + 'placeholder',
3997 + 'value',
3998 + 'readonly',
3999 + 'disabled',
4000 + 'size',
4001 + 'maxlength',
4002 + 'min',
4003 + 'max',
4004 + 'pattern',
4005 + 'step',
4006 + 'autofocus',
4007 + 'width',
4008 + 'height',
4009 + 'autocomplete',
4010 + 'tabindex',
4011 + 'role',
4012 + 'style',
4013 + );
4014 + $safe = in_array( $key, $safe_keys, true );
4015 + }//end if
4016 +
4017 + /**
4018 + * Filter the $safe value so additional keys can be allowed or disallowed.
4019 + *
4020 + * @since 6.11.2
4021 + *
4022 + * @param bool $safe True if the key is considered safe.
4023 + * @param string $key
4024 + * @param string $context Either 'display' or 'update'.
4025 + */
4026 + return (bool) apply_filters( 'frm_input_key_is_safe', $safe, $key, $context );
4027 + }
4028 +
4029 + /**
3552 4030 * @since 5.0.16
3553 4031 *
3554 4032 * @return bool
3555 4033 */
@@ -3574,20 +4052,9 @@
3574 4052
3575 4053 /**
3576 4054 * @since 5.0.17
3577 4055 *
3578 - * @param string $plugin
3579 - * @return string|false
3580 - */
3581 - private static function get_plan_required( $plugin ) {
3582 - $link = FrmAddonsController::install_link( $plugin );
3583 - return FrmFormsHelper::get_plan_required( $link );
3584 - }
3585 -
3586 - /**
3587 - * @since 5.0.17
3588 - *
3589 - * @param string
4056 + * @param string $feature
3590 4057 * @return bool
3591 4058 */
3592 4059 public static function show_new_feature( $feature ) {
3593 4060 $link = FrmAddonsController::install_link( $feature );
@@ -3660,9 +4127,9 @@
3660 4127 public static function show_pill_text( $text = null ) {
3661 4128 if ( null === $text ) {
3662 4129 $text = __( 'NEW', 'formidable' );
3663 4130 }
3664 - echo '<span class="frm-new-pill">' . esc_html( $text ) . '</span>';
4131 + echo '<span class="frm-meta-tag frm-new-pill">' . esc_html( $text ) . '</span>';
3665 4132 }
3666 4133
3667 4134 /**
3668 4135 * Count the number of decimals digits.
@@ -3669,9 +4136,9 @@
3669 4136 *
3670 4137 * @since 5.2.07
3671 4138 *
3672 4139 * @param mixed $num Number.
3673 - * @return int|false Returns `false` if the passed parameter is not number.
4140 + * @return false|int Returns `false` if the passed parameter is not number.
3674 4141 */
3675 4142 public static function count_decimals( $num ) {
3676 4143 if ( ! is_numeric( $num ) ) {
3677 4144 return false;
@@ -3702,9 +4169,9 @@
3702 4169 }
3703 4170
3704 4171 add_filter(
3705 4172 'option_gmt_offset',
3706 - function( $offset ) {
4173 + function ( $offset ) {
3707 4174 if ( ! is_string( $offset ) || is_numeric( $offset ) ) {
3708 4175 // Leave a valid value alone.
3709 4176 return $offset;
3710 4177 }
@@ -3786,65 +4253,8 @@
3786 4253 return true;
3787 4254 }
3788 4255
3789 4256 /**
3790 - * @since 4.08
3791 - * @deprecated 4.09.01
3792 - */
3793 - public static function expiring_message() {
3794 - _deprecated_function( __METHOD__, '4.09.01', 'FrmProAddonsController::expiring_message' );
3795 - if ( is_callable( 'FrmProAddonsController::expiring_message' ) ) {
3796 - FrmProAddonsController::expiring_message();
3797 - }
3798 - }
3799 -
3800 - /**
3801 - * Use the WP 4.7 wp_doing_ajax function
3802 - *
3803 - * @since 2.05.07
3804 - * @deprecated 4.04.04
3805 - */
3806 - public static function wp_doing_ajax() {
3807 - _deprecated_function( __METHOD__, '4.04.04', 'wp_doing_ajax' );
3808 - return wp_doing_ajax();
3809 - }
3810 -
3811 - /**
3812 - * @deprecated 4.0
3813 - */
3814 - public static function insert_opt_html( $args ) {
3815 - _deprecated_function( __METHOD__, '4.0', 'FrmFormsHelper::insert_opt_html' );
3816 - FrmFormsHelper::insert_opt_html( $args );
3817 - }
3818 -
3819 - /**
3820 - * @deprecated 3.01
3821 - * @codeCoverageIgnore
3822 - */
3823 - public static function sanitize_array( &$values ) {
3824 - FrmDeprecated::sanitize_array( $values );
3825 - }
3826 -
3827 - /**
3828 - * @since 2.0
3829 - * @deprecated 5.0.13
3830 - *
3831 - * @return string The base Google APIS url for the current version of jQuery UI
3832 - */
3833 - public static function jquery_ui_base_url() {
3834 - _deprecated_function( __FUNCTION__, '5.0.13', 'FrmProAppHelper::jquery_ui_base_url' );
3835 - return is_callable( 'FrmProAppHelper::jquery_ui_base_url' ) ? FrmProAppHelper::jquery_ui_base_url() : '';
3836 - }
3837 -
3838 - /**
3839 - * @since 4.07
3840 - * @deprecated 6.0
3841 - */
3842 - public static function renewal_message() {
3843 - _deprecated_function( __METHOD__, '6.0', 'FrmProAddonsController::renewal_message' );
3844 - }
3845 -
3846 - /**
3847 4257 * Display a dismissable warning message and save its dismissal state.
3848 4258 *
3849 4259 * @since 6.3
3850 4260 *
@@ -3856,9 +4266,9 @@
3856 4266 if ( ! $message || ! $option ) {
3857 4267 return;
3858 4268 }
3859 4269
3860 - $ajax_callback = function() use ( $option ) {
4270 + $ajax_callback = function () use ( $option ) {
3861 4271 self::dismiss_warning_message( $option );
3862 4272 };
3863 4273
3864 4274 // We're handling JS codes with `doJsonPost` and it adds 'frm_' to the beginning of the action.
@@ -3866,9 +4276,9 @@
3866 4276 add_action( 'wp_ajax_frm_' . $option, $ajax_callback );
3867 4277
3868 4278 add_filter(
3869 4279 'frm_message_list',
3870 - function( $show_messages ) use ( $message, $option ) {
4280 + function ( $show_messages ) use ( $message, $option ) {
3871 4281 if ( get_option( $option, false ) ) {
3872 4282 return $show_messages;
3873 4283 }
3874 4284
@@ -3875,9 +4285,9 @@
3875 4285 $dismiss_icon = self::icon_by_class(
3876 4286 'frmfont frm_close_icon',
3877 4287 array(
3878 4288 'aria-label' => _x( 'Dismiss', 'warning message: close icon label', 'formidable' ),
3879 - 'echo' => false,
4289 + 'echo' => false,
3880 4290 )
3881 4291 );
3882 4292
3883 4293 $show_messages[] = $message;
@@ -3904,6 +4314,100 @@
3904 4314 update_option( $option, true, 'no' );
3905 4315 }
3906 4316
3907 4317 wp_send_json_success();
4318 + }
4319 +
4320 + /**
4321 + * Lite license copy.
4322 + * Used in FrmDashboardController & FrmSettingsController
4323 + *
4324 + * @since 6.8
4325 + *
4326 + * @return string
4327 + */
4328 + public static function copy_for_lite_license() {
4329 + $message = __( 'You\'re using Formidable Forms Lite - no license needed. Enjoy!', 'formidable' ) . ' 🙂';
4330 +
4331 + if ( is_callable( 'FrmProAddonsController::get_readable_license_type' ) && ! class_exists( 'FrmProDashboardController' ) ) {
4332 + // Manage PRO versions without PRO dashboard functionality.
4333 + $license_type = FrmProAddonsController::get_readable_license_type();
4334 + if ( 'lite' !== strtolower( $license_type ) ) {
4335 + $message = 'Formidable Pro ' . $license_type;
4336 + }
4337 + }
4338 +
4339 + return apply_filters( 'frm_license_type_text', $message );
4340 + }
4341 +
4342 + /**
4343 + * Removes scripts that are unnecessarily loaded across the pages!
4344 + *
4345 + * @since 6.9
4346 + * @return void
4347 + */
4348 + public static function dequeue_extra_global_scripts() {
4349 + wp_dequeue_script( 'frm-surveys-admin' );
4350 + wp_dequeue_script( 'frm-quizzes-form-action' );
4351 + }
4352 +
4353 + /**
4354 + * Shows tooltip icon.
4355 + *
4356 + * @since 6.12
4357 + *
4358 + * @param string $tooltip_text Tooltip text.
4359 + * @param array $atts Tooltip wrapper HTML attributes.
4360 + *
4361 + * @return void
4362 + */
4363 + public static function tooltip_icon( $tooltip_text, $atts = array() ) {
4364 + $atts['title'] = $tooltip_text;
4365 + if ( isset( $atts['class'] ) ) {
4366 + $atts['class'] .= ' frm_help';
4367 + } else {
4368 + $atts['class'] = 'frm_help';
4369 + }
4370 + ?>
4371 + <span <?php self::array_to_html_params( $atts, true ); ?>>
4372 + <?php self::icon_by_class( 'frmfont frm_tooltip_icon' ); ?>
4373 + </span>
4374 + <?php
4375 + }
4376 +
4377 + /**
4378 + * Prints errors for settings in onboarding wizard or template settings.
4379 + *
4380 + * @since 6.15
4381 + *
4382 + * @param array $args Args.
4383 + *
4384 + * @return void
4385 + */
4386 + public static function print_setting_error( $args ) {
4387 + $args = wp_parse_args(
4388 + $args,
4389 + array(
4390 + 'id' => '',
4391 + 'errors' => array(),
4392 + 'class' => '',
4393 + )
4394 + );
4395 +
4396 + $args['class'] .= ' frm-validation-error frm-mt-xs frm_hidden';
4397 + ?>
4398 + <span id="<?php echo esc_attr( $args['id'] ); ?>" class="<?php echo esc_attr( $args['class'] ); ?>">
4399 + <?php
4400 + if ( is_array( $args['errors'] ) ) {
4401 + foreach ( $args['errors'] as $key => $msg ) {
4402 + ?>
4403 + <span frm-error="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $msg ); ?></span>
4404 + <?php
4405 + }
4406 + } else {
4407 + echo '<span>' . esc_html( $args['errors'] ) . '</span>';
4408 + }
4409 + ?>
4410 + </span>
4411 + <?php
3908 4412 }
3909 4413 }