PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.20
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.20
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 +919 -354 6.36.20 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.20';
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 ) ) {
@@ -239,15 +331,52 @@
239 331 return $is_formidable;
240 332 }
241 333
242 334 /**
335 + * Checks if is a list page.
336 + *
337 + * @since 6.19
338 + *
339 + * @param string $page The name of the page to check.
340 + * @return bool
341 + */
342 + public static function is_admin_list_page( $page = 'formidable' ) {
343 + if ( 'formidable' === $page ) {
344 + return self::on_form_listing_page();
345 + }
346 +
347 + if ( ! self::is_admin_page( $page ) ) {
348 + return false;
349 + }
350 +
351 + if ( 'formidable-entries' === $page ) {
352 + $action = self::simple_get( 'frm_action' );
353 + if ( ! $action || in_array( $action, self::get_entries_listing_page_form_actions(), true ) ) {
354 + return true;
355 + }
356 + }
357 +
358 + // Check edit or settings page.
359 + return ! self::simple_get( 'frm_action' );
360 + }
361 +
362 + /**
363 + * @since 6.20
364 + *
365 + * @return array<string>
366 + */
367 + private static function get_entries_listing_page_form_actions() {
368 + return array( 'list', 'destroy' );
369 + }
370 +
371 + /**
243 372 * Check for certain page in Formidable settings
244 373 *
245 374 * @since 2.0
246 375 *
247 - * @param string $page The name of the page to check
376 + * @param string $page The name of the page to check.
248 377 *
249 - * @return boolean
378 + * @return bool
250 379 */
251 380 public static function is_admin_page( $page = 'formidable' ) {
252 381 global $pagenow;
253 382 $get_page = self::simple_get( 'page', 'sanitize_title' );
@@ -266,8 +395,10 @@
266 395 * If the current page is for editing or creating a view.
267 396 * Returns false for the views listing page.
268 397 *
269 398 * @since 4.0
399 + *
400 + * @return bool
270 401 */
271 402 public static function is_view_builder_page() {
272 403 global $pagenow;
273 404
@@ -277,10 +408,10 @@
277 408
278 409 $post_type = self::simple_get( 'post_type', 'sanitize_title' );
279 410
280 411 if ( empty( $post_type ) ) {
281 - $post_id = self::simple_get( 'post', 'absint' );
282 - $post = get_post( $post_id );
412 + $post_id = self::simple_get( 'post', 'absint' );
413 + $post = get_post( $post_id );
283 414 $post_type = $post ? $post->post_type : '';
284 415 }
285 416
286 417 return $post_type === 'frm_display';
@@ -290,17 +421,15 @@
290 421 * Check for the form preview page
291 422 *
292 423 * @since 2.0
293 424 *
294 - * @param None
295 - *
296 - * @return boolean
425 + * @return bool
297 426 */
298 427 public static function is_preview_page() {
299 428 global $pagenow;
300 429 $action = self::simple_get( 'action', 'sanitize_title' );
301 430
302 - return $pagenow && $pagenow == 'admin-ajax.php' && $action == 'frm_forms_preview';
431 + return $pagenow && $pagenow === 'admin-ajax.php' && $action === 'frm_forms_preview';
303 432 }
304 433
305 434 /**
306 435 * Check for ajax except the form preview page
@@ -306,16 +435,17 @@
306 435 * Check for ajax except the form preview page
307 436 *
308 437 * @since 2.0
309 438 *
310 - * @param None
311 - *
312 - * @return boolean
439 + * @return bool
313 440 */
314 441 public static function doing_ajax() {
315 442 return wp_doing_ajax() && ! self::is_preview_page();
316 443 }
317 444
445 + /**
446 + * @return string
447 + */
318 448 public static function js_suffix() {
319 449 return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
320 450 }
321 451
@@ -320,13 +450,13 @@
320 450 }
321 451
322 452 /**
323 453 * @since 2.0.8
454 + * @return bool
324 455 */
325 456 public static function prevent_caching() {
326 457 global $frm_vars;
327 -
328 - return isset( $frm_vars['prevent_caching'] ) && $frm_vars['prevent_caching'];
458 + return ! empty( $frm_vars['prevent_caching'] );
329 459 }
330 460
331 461 /**
332 462 * Check if on an admin page
@@ -332,9 +462,9 @@
332 462 * Check if on an admin page
333 463 *
334 464 * @since 2.0
335 465 *
336 - * @return boolean
466 + * @return bool
337 467 */
338 468 public static function is_admin() {
339 469 $is_admin = is_admin() && ! wp_doing_ajax();
340 470
@@ -349,17 +479,22 @@
349 479 * Check if value contains blank value or empty array
350 480 *
351 481 * @since 2.0
352 482 *
353 - * @param mixed $value - value to check
354 - * @param string
483 + * @param mixed $value Value to check.
484 + * @param string $empty
355 485 *
356 - * @return boolean
486 + * @return bool
357 487 */
358 488 public static function is_empty_value( $value, $empty = '' ) {
359 489 return ( is_array( $value ) && empty( $value ) ) || $value === $empty;
360 490 }
361 491
492 + /**
493 + * @param mixed $value
494 + * @param string $empty
495 + * @return bool
496 + */
362 497 public static function is_not_empty_value( $value, $empty = '' ) {
363 498 return ! self::is_empty_value( $value, $empty );
364 499 }
365 500
@@ -376,8 +511,28 @@
376 511 return isset( $_SERVER[ $value ] ) ? wp_strip_all_tags( wp_unslash( $_SERVER[ $value ] ) ) : '';
377 512 }
378 513
379 514 /**
515 + * Get the server OS
516 + *
517 + * @since 6.4.2
518 + *
519 + * @return string
520 + */
521 + public static function get_server_os() {
522 + if ( function_exists( 'php_uname' ) ) {
523 + return php_uname( 's' );
524 + }
525 +
526 + if ( ! defined( 'PHP_OS' ) ) {
527 + return '';
528 + }
529 +
530 + // match the same response for Windows server as php_uname('s')
531 + return in_array( PHP_OS, array( 'WIN32', 'WINNT', 'Windows_NT' ), true ) ? 'Windows NT' : PHP_OS;
532 + }
533 +
534 + /**
380 535 * Check for the IP address in several places (when custom headers are enabled).
381 536 * Used by [ip] shortcode.
382 537 *
383 538 * @return string The IP address of the current user
@@ -392,9 +547,10 @@
392 547 }
393 548
394 549 $key = self::get_server_value( $key );
395 550 foreach ( explode( ',', $key ) as $ip ) {
396 - $ip = trim( $ip ); // Just to be safe.
551 + // Just to be safe.
552 + $ip = trim( $ip );
397 553
398 554 if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
399 555 return sanitize_text_field( $ip );
400 556 }
@@ -485,15 +641,24 @@
485 641
486 642 return $value;
487 643 }
488 644
645 + /**
646 + * Get a value from $_POST data.
647 + *
648 + * @param string $param The key we are trying to access data from in $_POST.
649 + * @param mixed $default The default if nothing is being sent.
650 + * @param callable|string $sanitize Make sure to pass a sanitize method here. This function will NOT sanitize by default.
651 + * @param bool $serialized
652 + * @return mixed
653 + */
489 654 public static function get_post_param( $param, $default = '', $sanitize = '', $serialized = false ) {
490 655 return self::get_simple_request(
491 656 array(
492 - 'type' => 'post',
493 - 'param' => $param,
494 - 'default' => $default,
495 - 'sanitize' => $sanitize,
657 + 'type' => 'post',
658 + 'param' => $param,
659 + 'default' => $default,
660 + 'sanitize' => $sanitize,
496 661 'serialized' => $serialized,
497 662 )
498 663 );
499 664 }
@@ -504,9 +669,9 @@
504 669 * @param string $param
505 670 * @param string $sanitize
506 671 * @param string $default
507 672 *
508 - * @return string|array
673 + * @return array|string
509 674 */
510 675 public static function simple_get( $param, $sanitize = 'sanitize_text_field', $default = '' ) {
511 676 return self::get_simple_request(
512 677 array(
@@ -524,27 +689,27 @@
524 689 * @since 2.0.6
525 690 *
526 691 * @param array $args
527 692 *
528 - * @return string|array
693 + * @return array|string
529 694 */
530 695 public static function get_simple_request( $args ) {
531 696 $defaults = array(
532 - 'param' => '',
533 - 'default' => '',
534 - 'type' => 'get',
535 - 'sanitize' => 'sanitize_text_field',
697 + 'param' => '',
698 + 'default' => '',
699 + 'type' => 'get',
700 + 'sanitize' => 'sanitize_text_field',
536 701 'serialized' => false,
537 702 );
538 703 $args = wp_parse_args( $args, $defaults );
539 704
540 705 $value = $args['default'];
541 - if ( $args['type'] == 'get' ) {
706 + if ( $args['type'] === 'get' ) {
542 707 if ( $_GET && isset( $_GET[ $args['param'] ] ) ) {
543 708 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
544 709 $value = wp_unslash( $_GET[ $args['param'] ] );
545 710 }
546 - } elseif ( $args['type'] == 'post' ) {
711 + } elseif ( $args['type'] === 'post' ) {
547 712 if ( isset( $_POST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
548 713 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
549 714 $value = wp_unslash( $_POST[ $args['param'] ] );
550 715 if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
@@ -550,13 +715,12 @@
550 715 if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
551 716 self::unserialize_or_decode( $value );
552 717 }
553 718 }
554 - } else {
555 - if ( isset( $_REQUEST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
719 + } elseif ( isset( $_REQUEST[ $args['param'] ] ) ) {
720 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
556 721 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
557 722 $value = wp_unslash( $_REQUEST[ $args['param'] ] );
558 - }
559 723 }
560 724
561 725 self::sanitize_value( $args['sanitize'], $value );
562 726
@@ -580,19 +744,35 @@
580 744
581 745 return $value;
582 746 }
583 747
748 + /**
749 + * Sanitize a value in-place.
750 + * If $value is an array, the sanitize function will get called for each item.
751 + *
752 + * @param callable $sanitize
753 + * @param mixed $value
754 + * @return void
755 + */
584 756 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 );
757 + if ( ! $sanitize ) {
758 + return;
759 + }
760 +
761 + if ( is_object( $value ) ) {
762 + $value = '';
763 + return;
764 + }
765 +
766 + if ( is_array( $value ) ) {
767 + $temp_values = $value;
768 + foreach ( $temp_values as $k => $v ) {
769 + self::sanitize_value( $sanitize, $value[ $k ] );
593 770 }
771 + return;
594 772 }
773 +
774 + $value = call_user_func( $sanitize, $value );
595 775 }
596 776
597 777 public static function sanitize_request( $sanitize_method, &$values ) {
598 778 $temp_values = $values;
@@ -604,15 +784,52 @@
604 784 }
605 785
606 786 /**
607 787 * @since 4.0.04
788 + *
789 + * @param mixed $value
790 + * @return void
608 791 */
609 792 public static function sanitize_with_html( &$value ) {
610 - self::sanitize_value( 'wp_kses_post', $value );
793 + if ( current_user_can( 'frm_edit_entries' ) || current_user_can( 'administrator' ) ) {
794 + // Only strip unsafe HTML like scripts for a privileged user submitting a form.
795 + self::sanitize_value( 'wp_kses_post', $value );
796 + } else {
797 + self::sanitize_value( self::class . '::strip_most_html', $value );
798 + }
611 799 self::decode_specialchars( $value );
612 800 }
613 801
614 802 /**
803 + * Allow only a small set of very basic HTML for unprivileged users.
804 + *
805 + * @since 6.7.1
806 + *
807 + * @param string $value
808 + */
809 + public static function strip_most_html( $value ) {
810 + $allowed_html = array(
811 + 'b' => array(),
812 + 'br' => array(),
813 + 'strong' => array(),
814 + 'p' => array(),
815 + 'i' => array(),
816 + 'ul' => array(),
817 + 'ol' => array(),
818 + 'li' => array(),
819 + );
820 +
821 + /**
822 + * @since 6.7.1
823 + *
824 + * @param array $allowed_html
825 + */
826 + $allowed_html = apply_filters( 'frm_allowed_form_input_html', $allowed_html );
827 +
828 + return wp_kses( $value, $allowed_html );
829 + }
830 +
831 + /**
615 832 * Do wp_specialchars_decode to get back '&' that wp_kses_post might have turned to '&amp;'
616 833 * this MUST be done, else we'll be back to the '& entity' problem.
617 834 *
618 835 * @since 4.0.04
@@ -646,10 +863,12 @@
646 863 $translation = array(
647 864 '&quot;' => '"',
648 865 '&#034;' => '"',
649 866 '&#x22;' => '"',
650 - '&lt; ' => '< ', // The space preserves the HTML.
651 - '&#060; ' => '< ', // The space preserves the HTML.
867 + // The space preserves the HTML.
868 + '&lt; ' => '< ',
869 + // The space preserves the HTML.
870 + '&#060; ' => '< ',
652 871 '&gt;' => '>',
653 872 '&#062;' => '>',
654 873 '&amp;' => '&',
655 874 '&#038;' => '&',
@@ -676,10 +895,10 @@
676 895 * Sanitize the value, and allow some HTML
677 896 *
678 897 * @since 2.0
679 898 *
680 - * @param string $value
681 - * @param array|string $allowed 'all' for everything included as defaults
899 + * @param string $value
900 + * @param array|string $allowed 'all' for everything included as defaults.
682 901 *
683 902 * @return string
684 903 */
685 904 public static function kses( $value, $allowed = array() ) {
@@ -688,8 +907,21 @@
688 907 return wp_kses( $value, $allowed_html );
689 908 }
690 909
691 910 /**
911 + * Sanitizes and echoes a given value.
912 + *
913 + * @since 6.18
914 + *
915 + * @param string $value The value to sanitize and output.
916 + * @param array|string $allowed Allowed HTML tags and attributes.
917 + * @return void
918 + */
919 + public static function kses_echo( $value, $allowed = array() ) {
920 + echo self::kses( $value, $allowed ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
921 + }
922 +
923 + /**
692 924 * The regular kses function strips [button_action] from submit button HTML.
693 925 *
694 926 * @since 5.0.13
695 927 *
@@ -780,9 +1012,9 @@
780 1012 'id' => true,
781 1013 );
782 1014
783 1015 return array(
784 - 'a' => array(
1016 + 'a' => array(
785 1017 'class' => true,
786 1018 'href' => true,
787 1019 'id' => true,
788 1020 'rel' => true,
@@ -851,16 +1083,16 @@
851 1083 'cite' => true,
852 1084 'title' => true,
853 1085 ),
854 1086 '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,
1087 + 'class' => true,
1088 + 'fill' => true,
1089 + 'height' => true,
1090 + 'width' => true,
1091 + 'x' => true,
1092 + 'y' => true,
1093 + 'rx' => true,
1094 + 'stroke' => true,
863 1095 'stroke-opacity' => true,
864 1096 'stroke-width' => true,
865 1097 ),
866 1098 'section' => $allow_class,
@@ -895,9 +1127,9 @@
895 1127 'xlink:href' => true,
896 1128 ),
897 1129 'ul' => $allow_class,
898 1130 'label' => array(
899 - 'for' => true,
1131 + 'for' => true,
900 1132 'class' => true,
901 1133 'id' => true,
902 1134 ),
903 1135 'button' => array(
@@ -906,8 +1138,13 @@
906 1138 ),
907 1139 'legend' => array(
908 1140 'class' => true,
909 1141 ),
1142 + 'option' => array(
1143 + 'class' => true,
1144 + 'value' => true,
1145 + 'selected' => true,
1146 + ),
910 1147 );
911 1148 }
912 1149
913 1150 /**
@@ -915,9 +1152,9 @@
915 1152 *
916 1153 * @since 2.0
917 1154 */
918 1155 public static function remove_get_action() {
919 - if ( ! isset( $_GET ) ) {
1156 + if ( empty( $_GET ) ) {
920 1157 return;
921 1158 }
922 1159
923 1160 $action_name = isset( $_GET['action'] ) ? 'action' : ( isset( $_GET['action2'] ) ? 'action2' : '' );
@@ -934,9 +1171,9 @@
934 1171 /**
935 1172 * Check the WP query for a parameter
936 1173 *
937 1174 * @since 2.0
938 - * @return string|array
1175 + * @return array|string
939 1176 */
940 1177 public static function get_query_var( $value, $param ) {
941 1178 if ( $value != '' ) {
942 1179 return $value;
@@ -953,10 +1190,12 @@
953 1190 /**
954 1191 * Try to show the SVG if possible. Otherwise, use the font icon.
955 1192 *
956 1193 * @since 4.0.02
1194 + *
957 1195 * @param string $class
958 1196 * @param array $atts
1197 + * @return string|null
959 1198 */
960 1199 public static function icon_by_class( $class, $atts = array() ) {
961 1200 $echo = ! isset( $atts['echo'] ) || $atts['echo'];
962 1201 if ( isset( $atts['echo'] ) ) {
@@ -966,14 +1205,16 @@
966 1205 $html_atts = self::array_to_html_params( $atts );
967 1206
968 1207 $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
969 1208
970 - // Replace icons that have been removed.
1209 + // Replace icons that have been removed or renamed.
971 1210 $deprecated = array(
972 - 'frm_clone_solid_icon' => 'frm_clone_icon',
1211 + 'frm_clone_solid_icon' => 'frm_clone_icon',
1212 + 'frm_keyalt_icon' => 'frm_key_icon',
1213 + 'frm_keyalt_solid_icon' => 'frm_key_solid_icon',
973 1214 );
974 1215 if ( isset( $deprecated[ $icon ] ) ) {
975 - $icon = $deprecated[ $icon ];
1216 + $icon = $deprecated[ $icon ];
976 1217 $class = str_replace( $icon, $deprecated[ $icon ], $class );
977 1218 }
978 1219
979 1220 if ( $icon === $class ) {
@@ -983,11 +1224,9 @@
983 1224 if ( strpos( $icon, ' ' ) ) {
984 1225 $icon = explode( ' ', $icon );
985 1226 $icon = reset( $icon );
986 1227 }
987 - $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '>
988 - <use xlink:href="#' . esc_attr( $icon ) . '" />
989 - </svg>';
1228 + $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use xlink:href="#' . esc_attr( $icon ) . '" /></svg>';
990 1229 }
991 1230
992 1231 if ( $echo ) {
993 1232 echo self::kses_icon( $icon ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -1073,11 +1312,18 @@
1073 1312 /**
1074 1313 * Include svg images.
1075 1314 *
1076 1315 * @since 4.0.02
1316 + * @return void
1077 1317 */
1078 1318 public static function include_svg() {
1079 - include_once self::plugin_path() . '/images/icons.svg';
1319 + if ( self::$included_svg ) {
1320 + return;
1321 + }
1322 +
1323 + // Use readfile instead of include_once because of a default security rule in Snuffleupagus.
1324 + readfile( self::plugin_path() . '/images/icons.svg' );
1325 + self::$included_svg = true;
1080 1326 }
1081 1327
1082 1328 /**
1083 1329 * Convert an associative array to HTML values.
@@ -1089,9 +1335,9 @@
1089 1335 * @param bool $echo
1090 1336 * @return string|void
1091 1337 */
1092 1338 public static function array_to_html_params( $atts, $echo = false ) {
1093 - $callback = function() use ( $atts ) {
1339 + $callback = function () use ( $atts ) {
1094 1340 if ( $atts ) {
1095 1341 foreach ( $atts as $key => $value ) {
1096 1342 echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
1097 1343 }
@@ -1106,9 +1352,9 @@
1106 1352 * @since 5.0.13
1107 1353 *
1108 1354 * @param Closure $echo_function
1109 1355 * @param bool $echo
1110 - * @return string|void
1356 + * @return string|null
1111 1357 */
1112 1358 public static function clip( $echo_function, $echo = false ) {
1113 1359 if ( ! $echo ) {
1114 1360 ob_start();
@@ -1126,12 +1372,15 @@
1126 1372 }
1127 1373
1128 1374 /**
1129 1375 * @since 3.0
1376 + *
1377 + * @param array $atts
1378 + * @return void
1130 1379 */
1131 1380 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'] ) ) {
1381 + $has_nav = ! empty( $atts['form'] ) && empty( $atts['is_template'] );
1382 + if ( empty( $atts['close'] ) ) {
1134 1383 $atts['close'] = admin_url( 'admin.php?page=formidable' );
1135 1384 }
1136 1385 if ( ! isset( $atts['import_link'] ) ) {
1137 1386 $atts['import_link'] = false;
@@ -1136,9 +1385,9 @@
1136 1385 if ( ! isset( $atts['import_link'] ) ) {
1137 1386 $atts['import_link'] = false;
1138 1387 }
1139 1388
1140 - include( self::plugin_path() . '/classes/views/shared/admin-header.php' );
1389 + include self::plugin_path() . '/classes/views/shared/admin-header.php';
1141 1390 }
1142 1391
1143 1392 /**
1144 1393 * @since 6.0
@@ -1174,10 +1423,34 @@
1174 1423 return;
1175 1424 }
1176 1425 ?>
1177 1426 <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>.
1427 + <div class="frm-upgrade-bar-inner">
1428 + <?php
1429 + $cta_text = FrmSalesApi::get_best_sale_value( 'lite_banner_cta_text' );
1430 + if ( ! $cta_text ) {
1431 + $cta_text = __( 'upgrading to PRO', 'formidable' );
1432 + }
1433 +
1434 + $upgrade_link = FrmSalesApi::get_best_sale_value( 'lite_banner_cta_link' );
1435 + if ( ! $upgrade_link ) {
1436 + $upgrade_link = self::admin_upgrade_link(
1437 + array(
1438 + 'medium' => 'settings-license',
1439 + 'content' => 'lite-banner',
1440 + )
1441 + );
1442 + }
1443 +
1444 + printf(
1445 + /* translators: %1$s: Start link HTML, %2$s: CTA text ("upgrading to PRO" by default), %3$s: End link HTML */
1446 + esc_html__( 'You\'re using Formidable Forms Lite. To unlock more features consider %1$s%2$s%3$s.', 'formidable' ),
1447 + '<a href="' . esc_url( $upgrade_link ) . '">',
1448 + esc_html( $cta_text ),
1449 + '</a>'
1450 + );
1451 + ?>
1452 + </div>
1180 1453 </div>
1181 1454 <?php
1182 1455 }
1183 1456
@@ -1194,8 +1467,10 @@
1194 1467 * Render a button for a new item (Form, Application, etc).
1195 1468 *
1196 1469 * @since 3.0
1197 1470 * @param array $atts {
1471 + * Details about the button.
1472 + *
1198 1473 * @type array $link_hook Custom link hook, calls do_action and exits early.
1199 1474 * @type string $new_link Href value, default #.
1200 1475 * @type string $class Custom class names, space separated.
1201 1476 * @type string $button_text Button text. Default "Add New".
@@ -1207,9 +1482,9 @@
1207 1482 do_action( $atts['link_hook']['hook'], $atts['link_hook']['param'] );
1208 1483 return;
1209 1484 }
1210 1485
1211 - if ( empty( $atts['new_link'] ) && empty( $atts['trigger_new_form_modal'] ) && empty( $atts['class'] ) ) {
1486 + if ( empty( $atts['new_link'] ) && empty( $atts['create_form'] ) && empty( $atts['class'] ) ) {
1212 1487 // Do not render a button if none of these attributes are set.
1213 1488 return;
1214 1489 }
1215 1490
@@ -1215,12 +1490,8 @@
1215 1490
1216 1491 $href = ! empty( $atts['new_link'] ) ? esc_url( $atts['new_link'] ) : '#';
1217 1492 $class = 'button button-primary frm-button-primary';
1218 1493
1219 - if ( ! empty( $atts['trigger_new_form_modal'] ) ) {
1220 - $class .= ' frm-trigger-new-form-modal';
1221 - }
1222 -
1223 1494 if ( ! empty( $atts['class'] ) ) {
1224 1495 $class .= ' ' . $atts['class'];
1225 1496 }
1226 1497
@@ -1237,10 +1508,11 @@
1237 1508 'placeholder' => '',
1238 1509 'tosearch' => '',
1239 1510 'text' => __( 'Search', 'formidable' ),
1240 1511 'input_id' => '',
1512 + 'value' => false,
1241 1513 );
1242 - $atts = array_merge( $defaults, $atts );
1514 + $atts = array_merge( $defaults, $atts );
1243 1515
1244 1516 if ( $atts['input_id'] === 'template' && empty( $atts['tosearch'] ) ) {
1245 1517 $atts['tosearch'] = 'frm-card';
1246 1518 }
@@ -1251,8 +1523,27 @@
1251 1523 }
1252 1524
1253 1525 $input_id = $atts['input_id'] . '-search-input';
1254 1526
1527 + $input_atts = array(
1528 + 'type' => 'search',
1529 + 'id' => $input_id,
1530 + 'name' => 's',
1531 + 'placeholder' => $atts['placeholder'],
1532 + 'class' => $class,
1533 + 'data-tosearch' => $atts['tosearch'],
1534 + );
1535 +
1536 + if ( is_string( $atts['value'] ) ) {
1537 + $input_atts['value'] = $atts['value'];
1538 + } elseif ( isset( $_REQUEST['s'] ) ) {
1539 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1540 + $input_atts['value'] = wp_unslash( $_REQUEST['s'] );
1541 + }
1542 +
1543 + if ( ! empty( $atts['tosearch'] ) ) {
1544 + $input_atts['autocomplete'] = 'off';
1545 + }
1255 1546 ?>
1256 1547 <p class="frm-search">
1257 1548 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1258 1549 <?php echo esc_html( $atts['text'] ); ?>:
@@ -1257,15 +1548,9 @@
1257 1548 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1258 1549 <?php echo esc_html( $atts['text'] ); ?>:
1259 1550 </label>
1260 1551 <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 - />
1552 + <input <?php self::array_to_html_params( $input_atts, true ); ?> />
1268 1553 <?php
1269 1554 if ( empty( $atts['tosearch'] ) ) {
1270 1555 submit_button( $atts['text'], 'button-secondary', '', false, array( 'id' => 'search-submit' ) );
1271 1556 }
@@ -1275,8 +1560,9 @@
1275 1560 }
1276 1561
1277 1562 /**
1278 1563 * @param string $type
1564 + * @return void
1279 1565 */
1280 1566 public static function trigger_hook_load( $type, $object = null ) {
1281 1567 // Only load the form hooks once.
1282 1568 $hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
@@ -1285,11 +1571,14 @@
1285 1571 }
1286 1572 }
1287 1573
1288 1574 /**
1289 - * Save all front-end js scripts into a single file
1575 + * Save all front-end js scripts into a single file.
1576 + * And save an additional single file of all front-end Stripe JS scripts.
1290 1577 *
1291 1578 * @since 3.0
1579 + *
1580 + * @return void
1292 1581 */
1293 1582 public static function save_combined_js() {
1294 1583 $file_atts = apply_filters(
1295 1584 'frm_js_location',
@@ -1302,10 +1591,34 @@
1302 1591
1303 1592 $files = array(
1304 1593 self::plugin_path() . '/js/formidable.min.js',
1305 1594 );
1595 + /**
1596 + * @param array $files
1597 + */
1306 1598 $files = apply_filters( 'frm_combined_js_files', $files );
1307 1599 $new_file->combine_files( $files );
1600 +
1601 + // Create the minified Stripe Script.
1602 + $file_atts = apply_filters(
1603 + 'frm_stripe_js_location',
1604 + array(
1605 + 'file_name' => 'frmstrp.min.js',
1606 + 'new_file_path' => self::plugin_path() . '/js',
1607 + )
1608 + );
1609 + $new_file = new FrmCreateFile( $file_atts );
1610 + $files = array(
1611 + FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.min.js',
1612 + );
1613 +
1614 + /**
1615 + * @since 6.5
1616 + *
1617 + * @param array $files
1618 + */
1619 + $files = apply_filters( 'frm_stripe_combined_js_files', $files );
1620 + $new_file->combine_files( $files );
1308 1621 }
1309 1622
1310 1623 /**
1311 1624 * Check a value from a shortcode to see if true or false.
@@ -1312,14 +1625,14 @@
1312 1625 * True when value is 1, true, 'true', 'yes'
1313 1626 *
1314 1627 * @since 1.07.10
1315 1628 *
1316 - * @param string $value The value to compare
1629 + * @param string $value The value to compare.
1317 1630 *
1318 - * @return boolean True or False
1631 + * @return bool
1319 1632 */
1320 1633 public static function is_true( $value ) {
1321 - return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
1634 + return true === $value || 1 == $value || 'true' === $value || 'yes' === $value;
1322 1635 }
1323 1636
1324 1637 /**
1325 1638 * Gets all post from a specific post type.
@@ -1385,9 +1698,9 @@
1385 1698
1386 1699 wp_enqueue_script( 'jquery-ui-autocomplete' );
1387 1700
1388 1701 $selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
1389 - $title = '';
1702 + $title = '';
1390 1703
1391 1704 if ( $selected ) {
1392 1705 $title = get_the_title( $selected );
1393 1706 }
@@ -1403,11 +1716,11 @@
1403 1716 <?php
1404 1717 }
1405 1718
1406 1719 /**
1407 - * @param array $args
1408 - * @param string $page_id Deprecated.
1409 - * @param boolean $truncate Deprecated.
1720 + * @param array $args
1721 + * @param string $page_id Deprecated.
1722 + * @param bool $truncate Deprecated.
1410 1723 */
1411 1724 public static function wp_pages_dropdown( $args = array(), $page_id = '', $truncate = false ) {
1412 1725 self::prep_page_dropdown_params( $page_id, $truncate, $args );
1413 1726
@@ -1451,13 +1764,13 @@
1451 1764 * @since 4.10.01 Added `post_type` and `autocomplete_placeholder` to the arguments array.
1452 1765 */
1453 1766 private static function preformat_selection_args( $args ) {
1454 1767 $defaults = array(
1455 - 'truncate' => false,
1456 - 'placeholder' => ' ',
1457 - 'field_name' => '',
1458 - 'page_id' => '',
1459 - 'post_type' => 'page',
1768 + 'truncate' => false,
1769 + 'placeholder' => ' ',
1770 + 'field_name' => '',
1771 + 'page_id' => '',
1772 + 'post_type' => 'page',
1460 1773 'autocomplete_placeholder' => __( 'Select a Page', 'formidable' ),
1461 1774 );
1462 1775
1463 1776 return array_merge( $defaults, $args );
@@ -1528,25 +1841,16 @@
1528 1841 return self::is_admin_page( 'formidable-views-editor' );
1529 1842 }
1530 1843
1531 1844 /**
1532 - * @since 4.0
1533 - * @deprecated 5.5.3
1845 + * @param string $field_name
1846 + * @param array|string $capability
1847 + * @param string $multiple 'single' and 'multiple'.
1534 1848 */
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 1849 public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
1546 1850 ?>
1547 1851 <select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>"
1548 - <?php echo ( 'multiple' === $multiple ) ? 'multiple="multiple"' : ''; ?>
1852 + <?php echo 'multiple' === $multiple ? 'multiple="multiple"' : ''; ?>
1549 1853 class="frm_multiselect">
1550 1854 <?php self::roles_options( $capability ); ?>
1551 1855 </select>
1552 1856 <?php
@@ -1554,9 +1858,9 @@
1554 1858
1555 1859 /**
1556 1860 * @since 4.07
1557 1861 * @param array|string $selected
1558 - * @param string $current
1862 + * @param string $current
1559 1863 */
1560 1864 private static function selected( $selected, $current ) {
1561 1865 if ( is_callable( 'FrmProAppHelper::selected' ) ) {
1562 1866 FrmProAppHelper::selected( $selected, $current );
@@ -1565,9 +1869,9 @@
1565 1869 }
1566 1870 }
1567 1871
1568 1872 /**
1569 - * @param string|array $capability
1873 + * @param array|string $capability
1570 1874 */
1571 1875 public static function roles_options( $capability ) {
1572 1876 global $frm_vars;
1573 1877 if ( isset( $frm_vars['editable_roles'] ) ) {
@@ -1579,9 +1883,9 @@
1579 1883
1580 1884 foreach ( $editable_roles as $role => $details ) {
1581 1885 $name = translate_user_role( $details['name'] );
1582 1886 ?>
1583 - <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_attr( $name ); ?> </option>
1887 + <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_html( $name ); ?> </option>
1584 1888 <?php
1585 1889 unset( $role, $details );
1586 1890 }
1587 1891 }
@@ -1602,9 +1906,8 @@
1602 1906 $pro_cap = array(
1603 1907 'frm_create_entries' => __( 'Add Entries from Admin Area', 'formidable' ),
1604 1908 'frm_edit_entries' => __( 'Edit Entries from Admin Area', 'formidable' ),
1605 1909 'frm_view_reports' => __( 'View Reports', 'formidable' ),
1606 - 'frm_edit_displays' => __( 'Add/Edit Views', 'formidable' ),
1607 1910 );
1608 1911 /**
1609 1912 * @since 5.3.1
1610 1913 *
@@ -1611,8 +1914,14 @@
1611 1914 * @param array<string,string> $pro_cap
1612 1915 */
1613 1916 $pro_cap = apply_filters( 'frm_pro_capabilities', $pro_cap );
1614 1917
1918 + if ( ! array_key_exists( 'frm_edit_displays', $pro_cap ) && is_callable( 'FrmProAppHelper::views_is_installed' ) && FrmProAppHelper::views_is_installed() ) {
1919 + // For backward compatibility, add the Add/Edit Views permission if Pro is not up to date.
1920 + // This was added in 6.5.4. Remove this in the future.
1921 + $pro_cap['frm_edit_displays'] = __( 'Add/Edit Views', 'formidable' );
1922 + }
1923 +
1615 1924 if ( 'pro_only' === $type ) {
1616 1925 return $pro_cap;
1617 1926 }
1618 1927
@@ -1627,9 +1936,9 @@
1627 1936 * @return array<string,string>
1628 1937 */
1629 1938 private static function get_lite_capabilities() {
1630 1939 return array(
1631 - 'frm_view_forms' => __( 'View Forms', 'formidable' ),
1940 + 'frm_view_forms' => __( 'View Forms List', 'formidable' ),
1632 1941 'frm_edit_forms' => __( 'Add and Edit Forms', 'formidable' ),
1633 1942 'frm_delete_forms' => __( 'Delete Forms', 'formidable' ),
1634 1943 'frm_change_settings' => __( 'Access this Settings Page', 'formidable' ),
1635 1944 'frm_view_entries' => __( 'View Entries from Admin Area', 'formidable' ),
@@ -1670,9 +1979,9 @@
1670 1979 return current_user_can( $role );
1671 1980 }
1672 1981
1673 1982 /**
1674 - * @param string|array $needed_role
1983 + * @param array|string $needed_role
1675 1984 * @return bool
1676 1985 */
1677 1986 public static function user_has_permission( $needed_role ) {
1678 1987 if ( is_array( $needed_role ) ) {
@@ -1728,8 +2037,11 @@
1728 2037 /**
1729 2038 * Make sure admins have permission to see the menu items
1730 2039 *
1731 2040 * @since 2.0.6
2041 + *
2042 + * @param string $cap
2043 + * @return void
1732 2044 */
1733 2045 public static function force_capability( $cap = 'frm_change_settings' ) {
1734 2046 if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
1735 2047 $role = get_role( 'administrator' );
@@ -1740,9 +2052,9 @@
1740 2052 }
1741 2053 }
1742 2054
1743 2055 /**
1744 - * Check if the user has permision for action.
2056 + * Check if the user has permission for action.
1745 2057 * Return permission message and stop the action if no permission
1746 2058 *
1747 2059 * @since 2.0
1748 2060 *
@@ -1778,9 +2090,9 @@
1778 2090 if ( empty( $nonce_name ) ) {
1779 2091 return $error;
1780 2092 }
1781 2093
1782 - $nonce_value = ( $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
2094 + $nonce_value = $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
1783 2095 if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $nonce_value, $nonce ) ) ) {
1784 2096 $frm_settings = self::get_settings();
1785 2097 $error = $frm_settings->admin_permission;
1786 2098 }
@@ -1794,12 +2106,13 @@
1794 2106 }
1795 2107 }
1796 2108
1797 2109 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 ) );
2110 + $values = self::recursive_function_map( $values, 'trim' );
2111 + $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1801 2112
2113 + $current = is_null( $current ) ? '' : htmlspecialchars_decode( trim( $current ) );
2114 +
1802 2115 return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
1803 2116 }
1804 2117
1805 2118 public static function recursive_function_map( $value, $function ) {
@@ -1819,8 +2132,9 @@
1819 2132 }
1820 2133 }
1821 2134 }
1822 2135 } else {
2136 + $value = self::maybe_update_value_if_null( $value, $function );
1823 2137 $value = call_user_func( $function, $value );
1824 2138 }
1825 2139
1826 2140 return $value;
@@ -1825,8 +2139,24 @@
1825 2139
1826 2140 return $value;
1827 2141 }
1828 2142
2143 + /**
2144 + * Updates value to empty string if it is null and being passed to a string function.
2145 + *
2146 + * @since 6.8.4
2147 + * @param mixed $value
2148 + * @param string $function
2149 + * @return mixed
2150 + */
2151 + private static function maybe_update_value_if_null( $value, $function ) {
2152 + if ( null === $value && in_array( $function, array( 'trim', 'strlen' ), true ) ) {
2153 + $value = '';
2154 + }
2155 +
2156 + return $value;
2157 + }
2158 +
1829 2159 public static function is_assoc( $array ) {
1830 2160 return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
1831 2161 }
1832 2162
@@ -1837,14 +2167,12 @@
1837 2167 $return = array();
1838 2168 foreach ( $array as $key => $value ) {
1839 2169 if ( is_array( $value ) ) {
1840 2170 $return = array_merge( $return, self::array_flatten( $value, $keys ) );
2171 + } elseif ( $keys === 'keep' ) {
2172 + $return[ $key ] = $value;
1841 2173 } else {
1842 - if ( $keys == 'keep' ) {
1843 - $return[ $key ] = $value;
1844 - } else {
1845 - $return[] = $value;
1846 - }
2174 + $return[] = $value;
1847 2175 }
1848 2176 }
1849 2177
1850 2178 return $return;
@@ -1849,8 +2177,27 @@
1849 2177
1850 2178 return $return;
1851 2179 }
1852 2180
2181 + /**
2182 + * Flatten an array before imploding it to avoid Array to string conversion warnings.
2183 + *
2184 + * @since 6.16.1
2185 + *
2186 + * @param string $sep
2187 + * @param array $array
2188 + * @return string
2189 + */
2190 + public static function safe_implode( $sep, $array ) {
2191 + $array = self::array_flatten( $array );
2192 + return implode( $sep, $array );
2193 + }
2194 +
2195 + /**
2196 + * @param string $text
2197 + * @param bool $is_rich_text
2198 + * @return string
2199 + */
1853 2200 public static function esc_textarea( $text, $is_rich_text = false ) {
1854 2201 $safe_text = str_replace( '&quot;', '"', $text );
1855 2202 if ( ! $is_rich_text ) {
1856 2203 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
@@ -1856,9 +2203,13 @@
1856 2203 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
1857 2204 }
1858 2205 $safe_text = str_replace( '&amp; ', '& ', $safe_text );
1859 2206
1860 - return apply_filters( 'esc_textarea', $safe_text, $text );
2207 + /**
2208 + * @param string $safe_text
2209 + * @param string $text
2210 + */
2211 + return (string) apply_filters( 'esc_textarea', $safe_text, $text );
1861 2212 }
1862 2213
1863 2214 /**
1864 2215 * Add auto paragraphs to text areas
@@ -1865,9 +2216,9 @@
1865 2216 *
1866 2217 * @since 2.0
1867 2218 */
1868 2219 public static function use_wpautop( $content ) {
1869 - if ( apply_filters( 'frm_use_wpautop', true ) && ! is_array( $content ) ) {
2220 + if ( apply_filters( 'frm_use_wpautop', true ) && is_string( $content ) ) {
1870 2221 $content = wpautop( str_replace( '<br>', '<br />', $content ) );
1871 2222 }
1872 2223
1873 2224 return $content;
@@ -1909,12 +2260,12 @@
1909 2260 * @since 5.0.13 added $echo param.
1910 2261 *
1911 2262 * @param string $url
1912 2263 * @param bool $echo
1913 - * @return string|void
2264 + * @return string|null
1914 2265 */
1915 2266 public static function js_redirect( $url, $echo = false ) {
1916 - $callback = function() use ( $url ) {
2267 + $callback = function () use ( $url ) {
1917 2268 echo '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
1918 2269 };
1919 2270 return self::clip( $callback, $echo );
1920 2271 }
@@ -1924,9 +2275,9 @@
1924 2275 return $user_id;
1925 2276 }
1926 2277
1927 2278 $user_id = sanitize_text_field( $user_id );
1928 - if ( $user_id == 'current' ) {
2279 + if ( $user_id === 'current' ) {
1929 2280 $user_id = get_current_user_id();
1930 2281 } else {
1931 2282 if ( is_email( $user_id ) ) {
1932 2283 $user = get_user_by( 'email', $user_id );
@@ -1942,8 +2293,13 @@
1942 2293
1943 2294 return $user_id;
1944 2295 }
1945 2296
2297 + /**
2298 + * @param string $filename
2299 + * @param array $atts
2300 + * @return false|string
2301 + */
1946 2302 public static function get_file_contents( $filename, $atts = array() ) {
1947 2303 if ( ! is_file( $filename ) ) {
1948 2304 return false;
1949 2305 }
@@ -1949,9 +2305,9 @@
1949 2305 }
1950 2306
1951 2307 extract( $atts ); // phpcs:ignore WordPress.PHP.DontExtract
1952 2308 ob_start();
1953 - include( $filename );
2309 + include $filename;
1954 2310 $contents = ob_get_contents();
1955 2311 ob_end_clean();
1956 2312
1957 2313 return $contents;
@@ -2006,9 +2362,9 @@
2006 2362 ++$suffix;
2007 2363 } while ( in_array( $key_check, $similar_keys, true ) );
2008 2364
2009 2365 $key = $key_check;
2010 - }
2366 + }//end if
2011 2367
2012 2368 return $key;
2013 2369 }
2014 2370
@@ -2052,9 +2408,11 @@
2052 2408 * @return string
2053 2409 */
2054 2410 private static function generate_new_key( $num_chars ) {
2055 2411 $max_slug_value = pow( 36, $num_chars );
2056 - $min_slug_value = 37; // we want to have at least 2 characters in the slug
2412 +
2413 + // We want to have at least 2 characters in the slug.
2414 + $min_slug_value = 37;
2057 2415 return base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
2058 2416 }
2059 2417
2060 2418 /**
@@ -2083,11 +2441,16 @@
2083 2441
2084 2442 /**
2085 2443 * Editing a Form or Entry
2086 2444 *
2087 - * @param string $table
2445 + * @param object $record
2446 + * @param string $table
2447 + * @param array|string $fields
2448 + * @param bool $default
2449 + * @param array $post_values
2450 + * @param array $args
2088 2451 *
2089 - * @return bool|array
2452 + * @return array|bool
2090 2453 */
2091 2454 public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
2092 2455 if ( ! $record ) {
2093 2456 return false;
@@ -2140,13 +2503,12 @@
2140 2503 $post_values = $args['post_values'];
2141 2504
2142 2505 if ( $args['default'] ) {
2143 2506 $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 - }
2507 + } elseif ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
2508 + if ( ! isset( $field->field_options['custom_field'] ) ) {
2509 + $field->field_options['custom_field'] = '';
2510 + }
2149 2511 $meta_value = FrmProEntryMetaHelper::get_post_value(
2150 2512 $record->post_id,
2151 2513 $field->field_options['post_field'],
2152 2514 $field->field_options['custom_field'],
@@ -2156,12 +2518,11 @@
2156 2518 'form_id' => $field->form_id,
2157 2519 'field' => $field,
2158 2520 )
2159 2521 );
2160 - } else {
2161 - $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2162 - }
2163 - }
2522 + } else {
2523 + $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2524 + }//end if
2164 2525
2165 2526 $field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
2166 2527 if ( isset( $post_values['item_meta'][ $field->id ] ) ) {
2167 2528 $new_value = $post_values['item_meta'][ $field->id ];
@@ -2209,12 +2570,15 @@
2209 2570 );
2210 2571 }
2211 2572
2212 2573 /**
2574 + * @param object $record
2213 2575 * @param string $table
2576 + * @param array $post_values
2577 + * @param array $values
2214 2578 */
2215 2579 private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
2216 - if ( $table == 'entries' ) {
2580 + if ( $table === 'entries' ) {
2217 2581 $form = $record->form_id;
2218 2582 FrmForm::maybe_get_form( $form );
2219 2583 } else {
2220 2584 $form = $record;
@@ -2250,9 +2614,9 @@
2250 2614 $form_defaults = FrmFormsHelper::get_default_opts();
2251 2615
2252 2616 foreach ( $form_defaults as $opt => $default ) {
2253 2617 if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
2254 - $values[ $opt ] = ( $post_values && isset( $post_values['options'][ $opt ] ) ) ? $post_values['options'][ $opt ] : $default;
2618 + $values[ $opt ] = $post_values && isset( $post_values['options'][ $opt ] ) ? $post_values['options'][ $opt ] : $default;
2255 2619 }
2256 2620
2257 2621 unset( $opt, $default );
2258 2622 }
@@ -2273,9 +2637,9 @@
2273 2637 * @since 2.2.10
2274 2638 *
2275 2639 * @param array $post_values
2276 2640 *
2277 - * @return boolean|int
2641 + * @return bool|int
2278 2642 */
2279 2643 public static function custom_style_value( $post_values ) {
2280 2644 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2281 2645 $custom_style = absint( $post_values['options']['custom_style'] );
@@ -2280,29 +2644,37 @@
2280 2644 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2281 2645 $custom_style = absint( $post_values['options']['custom_style'] );
2282 2646 } else {
2283 2647 $frm_settings = self::get_settings();
2284 - $custom_style = ( $frm_settings->load_style != 'none' );
2648 + $custom_style = ( $frm_settings->load_style !== 'none' );
2285 2649 }
2286 2650
2287 2651 return $custom_style;
2288 2652 }
2289 2653
2290 - public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
2291 - if ( is_array( $str ) ) {
2654 + /**
2655 + * @param mixed $original_string
2656 + * @param int|string $length
2657 + * @param int $minword
2658 + * @param string $continue
2659 + * @return string
2660 + */
2661 + public static function truncate( $original_string, $length, $minword = 3, $continue = '...' ) {
2662 + if ( ! is_string( $original_string ) && ! is_int( $original_string ) ) {
2292 2663 return '';
2293 2664 }
2294 2665
2295 2666 $length = (int) $length;
2296 - $str = wp_strip_all_tags( $str );
2667 + $str = wp_strip_all_tags( (string) $original_string );
2297 2668 $original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
2298 2669
2299 2670 if ( $length == 0 ) {
2300 2671 return '';
2301 - } elseif ( $length <= 10 ) {
2672 + }
2673 +
2674 + if ( $length <= 10 ) {
2302 2675 $sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
2303 -
2304 - return $sub . ( ( $length < $original_len ) ? $continue : '' );
2676 + return $sub . ( $length < $original_len ? $continue : '' );
2305 2677 }
2306 2678
2307 2679 $sub = '';
2308 2680 $len = 0;
@@ -2308,10 +2680,14 @@
2308 2680 $len = 0;
2309 2681
2310 2682 $words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
2311 2683
2684 + if ( ! is_array( $words ) ) {
2685 + return $original_string;
2686 + }
2687 +
2312 2688 foreach ( $words as $word ) {
2313 - $part = ( ( $sub != '' ) ? ' ' : '' ) . $word;
2689 + $part = ( $sub != '' ? ' ' : '' ) . $word;
2314 2690 $total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
2315 2691 if ( $total_len > $length && substr_count( $sub, ' ' ) ) {
2316 2692 break;
2317 2693 }
@@ -2325,11 +2701,37 @@
2325 2701
2326 2702 unset( $total_len, $word );
2327 2703 }
2328 2704
2329 - return $sub . ( ( $len < $original_len ) ? $continue : '' );
2705 + $sub = self::maybe_force_truncate_on_string_with_no_spaces( $sub, $length );
2706 +
2707 + return $sub . ( $len < $original_len ? $continue : '' );
2330 2708 }
2331 2709
2710 + /**
2711 + * If the string is still too long because there may not have been any spaces, force truncate.
2712 + *
2713 + * @since 6.5.4
2714 + *
2715 + * @param string $sub Current substring.
2716 + * @param int $length The length limit.
2717 + * @return string
2718 + */
2719 + private static function maybe_force_truncate_on_string_with_no_spaces( $sub, $length ) {
2720 + if ( strlen( $sub ) < $length + 50 ) {
2721 + // If the string isn't way over the limit, leave it.
2722 + return $sub;
2723 + }
2724 +
2725 + $first_space = strpos( $sub, ' ', $length );
2726 + if ( false !== $first_space ) {
2727 + // Ignore anything with spaces.
2728 + return $sub;
2729 + }
2730 +
2731 + return substr( $sub, 0, $length + 10 );
2732 + }
2733 +
2332 2734 public static function mb_function( $function_names, $args ) {
2333 2735 $mb_function_name = $function_names[0];
2334 2736 $function_name = $function_names[1];
2335 2737 if ( function_exists( $mb_function_name ) ) {
@@ -2362,8 +2764,13 @@
2362 2764
2363 2765 return $formatted;
2364 2766 }
2365 2767
2768 + /**
2769 + * @param string $time_format
2770 + * @param string $date
2771 + * @return string
2772 + */
2366 2773 private static function add_time_to_date( $time_format, $date ) {
2367 2774 if ( empty( $time_format ) ) {
2368 2775 $time_format = get_option( 'time_format' );
2369 2776 }
@@ -2386,12 +2793,12 @@
2386 2793 return date_i18n( $date_format, strtotime( $date ) );
2387 2794 }
2388 2795
2389 2796 /**
2390 - * Gets the time ago in words
2797 + * Gets the time ago in words.
2391 2798 *
2392 - * @param int $from in seconds
2393 - * @param int|string $to in seconds
2799 + * @param int $from In seconds.
2800 + * @param int|string $to In seconds.
2394 2801 *
2395 2802 * @return string $time_ago
2396 2803 */
2397 2804 public static function human_time_diff( $from, $to = '', $levels = 1 ) {
@@ -2406,9 +2813,9 @@
2406 2813 $diff_object = $now->diff( $ago );
2407 2814 $diff = get_object_vars( $diff_object );
2408 2815
2409 2816 // Add week amount and update day amount
2410 - $diff['w'] = floor( $diff['d'] / 7 );
2817 + $diff['w'] = floor( $diff['d'] / 7 );
2411 2818 $diff['d'] -= $diff['w'] * 7;
2412 2819
2413 2820 $time_strings = self::get_time_strings();
2414 2821
@@ -2415,9 +2822,9 @@
2415 2822 if ( ! is_numeric( $levels ) ) {
2416 2823 // Show time in specified unit.
2417 2824 $levels = self::get_unit( $levels );
2418 2825 if ( isset( $time_strings[ $levels ] ) ) {
2419 - $diff = array(
2826 + $diff = array(
2420 2827 $levels => self::time_format( $levels, $diff ),
2421 2828 );
2422 2829 $time_strings = array(
2423 2830 $levels => $time_strings[ $levels ],
@@ -2506,9 +2913,9 @@
2506 2913 }
2507 2914
2508 2915 /**
2509 2916 * Get the translatable time strings. The untranslated version is a failsafe
2510 - * in case langauges are changing for the unit set in the shortcode.
2917 + * in case languages are changing for the unit set in the shortcode.
2511 2918 *
2512 2919 * @since 2.0.20
2513 2920 * @return array
2514 2921 */
@@ -2554,23 +2961,28 @@
2554 2961
2555 2962 // Pagination Methods.
2556 2963
2557 2964 /**
2558 - * @param integer $current_p
2965 + * @param int $r_count
2966 + * @param int $current_p
2967 + * @param int $p_size
2968 + * @return int
2559 2969 */
2560 2970 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 ) );
2971 + return ( $r_count < $current_p * $p_size ? $r_count : $current_p * $p_size );
2562 2972 }
2563 2973
2564 2974 /**
2565 - * @param integer $current_p
2975 + * @param int $r_count
2976 + * @param int $current_p
2977 + * @param int $p_size
2978 + * @return int
2566 2979 */
2567 2980 public static function get_first_record_num( $r_count, $current_p, $p_size ) {
2568 2981 if ( $current_p == 1 ) {
2569 2982 return 1;
2570 - } else {
2571 - return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
2572 2983 }
2984 + return self::get_last_record_num( $r_count, $current_p - 1, $p_size ) + 1;
2573 2985 }
2574 2986
2575 2987 /**
2576 2988 * @return array
@@ -2593,9 +3005,9 @@
2593 3005 if ( ! isset( $l3 ) ) {
2594 3006 $l3 = $name;
2595 3007 }
2596 3008
2597 - $this_val = ( $p == $last ) ? $jv['value'] : array();
3009 + $this_val = $p == $last ? $jv['value'] : array();
2598 3010
2599 3011 switch ( $p ) {
2600 3012 case 0:
2601 3013 $l1 = $name;
@@ -2617,12 +3029,12 @@
2617 3029 self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
2618 3030 }
2619 3031
2620 3032 unset( $this_val, $n );
2621 - }
3033 + }//end foreach
2622 3034
2623 3035 unset( $last, $jv );
2624 - }
3036 + }//end foreach
2625 3037
2626 3038 return $vars;
2627 3039 }
2628 3040
@@ -2647,8 +3059,9 @@
2647 3059 '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 3060 'from' => __( 'Enter the name and/or email address of the sender. FORMAT: John Bates <john@example.com> or john@example.com.', 'formidable' ),
2649 3061 /* translators: %1$s: Form name, %2$s: Date */
2650 3062 '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() ) ),
3063 + '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 3064 );
2652 3065
2653 3066 if ( ! isset( $tooltips[ $name ] ) ) {
2654 3067 return;
@@ -2869,8 +3282,11 @@
2869 3282 }
2870 3283
2871 3284 /**
2872 3285 * @since 4.02.03
3286 + *
3287 + * @param array|string $value
3288 + * @return string
2873 3289 */
2874 3290 public static function maybe_json_encode( $value ) {
2875 3291 if ( is_array( $value ) ) {
2876 3292 $value = wp_json_encode( $value );
@@ -2878,12 +3294,14 @@
2878 3294 return $value;
2879 3295 }
2880 3296
2881 3297 /**
3298 + * Echo The javascript to open and highlight the Formidable menu
3299 + *
2882 3300 * @since 1.07.10
2883 3301 *
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
3302 + * @param string $post_type The name of the post type that may need to be highlighted.
3303 + * @return void
2886 3304 */
2887 3305 public static function maybe_highlight_menu( $post_type ) {
2888 3306 global $post;
2889 3307
@@ -2902,8 +3320,11 @@
2902 3320 /**
2903 3321 * Load the JS file on non-Formidable pages in the admin area
2904 3322 *
2905 3323 * @since 2.0
3324 + *
3325 + * @param bool $load
3326 + * @return void
2906 3327 */
2907 3328 public static function load_admin_wide_js( $load = true ) {
2908 3329 $version = self::plugin_version();
2909 3330 wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
@@ -2917,8 +3338,9 @@
2917 3338 'canAccessApplicationDashboard' => current_user_can( is_callable( 'FrmProApplicationsHelper::get_required_templates_capability' ) ? FrmProApplicationsHelper::get_required_templates_capability() : 'frm_edit_forms' ),
2918 3339 'loading' => __( 'Loading&hellip;', 'formidable' ),
2919 3340 'nonce' => wp_create_nonce( 'frm_ajax' ),
2920 3341 'proIncludesSliderJs' => is_callable( 'FrmProFormsHelper::prepare_custom_currency' ),
3342 + 'inboxSlideIn' => FrmInbox::get_inbox_slide_in_value_for_js(),
2921 3343 );
2922 3344 wp_localize_script( 'formidable_admin_global', 'frmGlobal', $global_strings );
2923 3345
2924 3346 if ( $load ) {
@@ -2927,8 +3349,9 @@
2927 3349 }
2928 3350
2929 3351 /**
2930 3352 * @since 2.0.9
3353 + * @return void
2931 3354 */
2932 3355 public static function load_font_style() {
2933 3356 wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
2934 3357 }
@@ -2934,99 +3357,133 @@
2934 3357 }
2935 3358
2936 3359 /**
2937 3360 * @param string $location
3361 + * @return void
2938 3362 */
2939 3363 public static function localize_script( $location ) {
2940 - global $wp_scripts;
3364 + global $wp_scripts, $wp_version;
2941 3365
2942 - $ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
2943 - $ajax_url = apply_filters( 'frm_ajax_url', $ajax_url );
2944 -
2945 3366 $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(),
3367 + 'ajax_url' => esc_url_raw( self::get_ajax_url() ),
3368 + 'images_url' => self::plugin_url() . '/images',
3369 + 'loading' => __( 'Loading&hellip;', 'formidable' ),
3370 + 'remove' => __( 'Remove', 'formidable' ),
3371 + 'offset' => apply_filters( 'frm_scroll_offset', 4 ),
3372 + 'nonce' => wp_create_nonce( 'frm_ajax' ),
3373 + 'id' => __( 'ID', 'formidable' ),
3374 + 'no_results' => __( 'No results match', 'formidable' ),
3375 + 'file_spam' => __( 'That file looks like Spam.', 'formidable' ),
3376 + 'calc_error' => __( 'There is an error in the calculation in the field with key', 'formidable' ),
3377 + 'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
3378 + 'focus_first_error' => self::should_focus_first_error(),
3379 + 'include_alert_role' => self::should_include_alert_role_on_field_errors(),
3380 + // We need to keep this setting for a few versions because Pro checks for this.
3381 + 'include_resend_email' => false,
2959 3382 );
2960 3383
2961 3384 $data = $wp_scripts->get_data( 'formidable', 'data' );
2962 - if ( empty( $data ) ) {
3385 + if ( ! $data ) {
2963 3386 wp_localize_script( 'formidable', 'frm_js', $script_strings );
2964 3387 }
2965 3388
2966 - if ( $location == 'admin' ) {
2967 - $frm_settings = self::get_settings();
3389 + if ( $location === 'admin' ) {
2968 3390 $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(),
3391 + 'desc' => __( '(Click to add description)', 'formidable' ),
3392 + 'blank' => __( '(Blank)', 'formidable' ),
3393 + 'no_label' => __( '(no label)', 'formidable' ),
3394 + 'ok' => __( 'OK', 'formidable' ),
3395 + 'cancel' => __( 'Cancel', 'formidable' ),
3396 + 'default_label' => __( 'Default', 'formidable' ),
3397 + 'clear_default' => __( 'Clear default value when typing', 'formidable' ),
3398 + 'no_clear_default' => __( 'Do not clear default value when typing', 'formidable' ),
3399 + 'valid_default' => __( 'Default value will pass form validation', 'formidable' ),
3400 + 'no_valid_default' => __( 'Default value will NOT pass form validation', 'formidable' ),
3401 + 'confirm' => __( 'Are you sure?', 'formidable' ),
3402 + 'conf_delete' => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
3403 + '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' ),
3404 + 'conf_no_repeat' => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
3405 + 'default_unique' => FrmFieldsHelper::default_unique_msg(),
3406 + 'default_conf' => __( 'The entered values do not match', 'formidable' ),
3407 + 'enter_email' => __( 'Enter Email', 'formidable' ),
3408 + 'confirm_email' => __( 'Confirm Email', 'formidable' ),
3409 + 'conditional_text' => __( 'Conditional content here', 'formidable' ),
3410 + 'new_option' => __( 'New Option', 'formidable' ),
3411 + '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' ),
3412 + 'enter_password' => __( 'Enter Password', 'formidable' ),
3413 + 'confirm_password' => __( 'Confirm Password', 'formidable' ),
3414 + 'import_complete' => __( 'Import Complete', 'formidable' ),
3415 + 'updating' => __( 'Please wait while your site updates.', 'formidable' ),
3416 + 'no_save_warning' => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
3417 + 'private_label' => __( 'Private', 'formidable' ),
3418 + 'jquery_ui_url' => '',
3419 + 'pro_url' => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
3420 + 'no_licenses' => __( 'No new licenses were found', 'formidable' ),
3421 + 'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3422 + 'view_shortcodes' => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
3423 + 'text_shortcodes' => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
3424 + /* translators: %d is the number of allowed actions per form */
3425 + 'only_one_action' => sprintf( __( 'This form action is limited to %d per form.', 'formidable' ), 1 ),
3426 + 'edit_action_text' => __( 'Please edit the existing form action.', 'formidable' ),
3427 + 'unsafe_params' => FrmFormsHelper::reserved_words(),
3006 3428 /* 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' ), '****' ),
3429 + 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ),
3008 3430 /* 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' ),
3431 + 'param_is_reserved' => sprintf( __( 'The parameter "%s" is reserved by WordPress. This may cause problems when included in the URL. Is this intentional? ', 'formidable' ), '****' ),
3432 + 'reserved_words' => __( 'See the list of reserved words in WordPress.', 'formidable' ),
3433 + 'repeat_limit_min' => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
3434 + 'checkbox_limit' => __( 'Please select a limit between 0 and 200.', 'formidable' ),
3435 + 'install' => __( 'Install', 'formidable' ),
3436 + 'active' => __( 'Active', 'formidable' ),
3437 + 'installed' => __( 'Installed', 'formidable' ),
3438 + 'not_installed' => __( 'Not Installed', 'formidable' ),
3439 + 'select_a_field' => __( 'Select a Field', 'formidable' ),
3440 + 'no_items_found' => __( 'No items found.', 'formidable' ),
3441 + 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
3442 +
3443 + // Deprecated in 6.0.
3444 + 'saving' => '',
3445 +
3446 + // Deprecated in 6.0.
3447 + 'saved' => '',
3448 +
3449 + // translators: %1$s: HTML open tag, %2$s: HTML end tag.
3450 + 'holdShiftMsg' => esc_html__( 'You can hold %1$sShift%2$s on your keyboard to select multiple fields', 'formidable' ),
3451 + 'noTitleText' => FrmFormsHelper::get_no_title_text(),
3452 +
3453 + // In older versions this event listener causes the section to immediately close again
3454 + // when the h3 element is clicked. It's only required in WP 6.7+.
3455 + 'requireAccordionTitleClickListener' => version_compare( $wp_version, '6.7', '>=' ),
3018 3456 );
3457 + /**
3458 + * @param array $admin_script_strings
3459 + */
3019 3460 $admin_script_strings = apply_filters( 'frm_admin_script_strings', $admin_script_strings );
3020 3461
3021 3462 $data = $wp_scripts->get_data( 'formidable_admin', 'data' );
3022 - if ( empty( $data ) ) {
3463 + if ( ! $data ) {
3023 3464 wp_localize_script( 'formidable_admin', 'frm_admin_js', $admin_script_strings );
3024 3465 }
3025 - }
3466 + }//end if
3026 3467 }
3027 3468
3028 3469 /**
3470 + * @since 6.5
3471 + *
3472 + * @return string
3473 + */
3474 + public static function get_ajax_url() {
3475 + $ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
3476 +
3477 + /**
3478 + * @since 2.0.13
3479 + *
3480 + * @param string $ajax_url
3481 + */
3482 + return apply_filters( 'frm_ajax_url', $ajax_url );
3483 + }
3484 +
3485 + /**
3029 3486 * Returns whether or not the first errored input should be auto-focused (default true).
3030 3487 *
3031 3488 * @since 5.2.05
3032 3489 *
@@ -3051,9 +3508,10 @@
3051 3508 * Echo the message on the plugins listing page
3052 3509 *
3053 3510 * @since 1.07.10
3054 3511 *
3055 - * @param float $min_version The version the add-on requires
3512 + * @param float $min_version The version the add-on requires.
3513 + * @return void
3056 3514 */
3057 3515 public static function min_version_notice( $min_version ) {
3058 3516 $frm_version = self::plugin_version();
3059 3517
@@ -3087,9 +3545,8 @@
3087 3545 if ( ! $is_pro || self::meets_min_pro_version( $min_version ) ) {
3088 3546 return;
3089 3547 }
3090 3548
3091 - $pro_version = FrmProDb::$plug_version;
3092 3549 $expired = FrmAddonsController::is_license_expired();
3093 3550 ?>
3094 3551 <div class="frm-banner-alert frm_error_style frm_previous_install">
3095 3552 <?php
@@ -3107,8 +3564,11 @@
3107 3564 /**
3108 3565 * If Pro is installed, check the version number.
3109 3566 *
3110 3567 * @since 4.0.01
3568 + *
3569 + * @param string $min_version
3570 + * @return bool
3111 3571 */
3112 3572 public static function meets_min_pro_version( $min_version ) {
3113 3573 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
3114 3574 }
@@ -3113,24 +3573,19 @@
3113 3573 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
3114 3574 }
3115 3575
3116 3576 /**
3117 - * Show a message if the browser or PHP version is below the recommendations.
3577 + * Show a message if the PHP version is below the recommendations.
3118 3578 *
3119 3579 * @since 4.0.02
3580 + * @return void
3120 3581 */
3121 3582 private static function php_version_notice() {
3122 3583 $message = array();
3123 - if ( version_compare( phpversion(), '5.6', '<' ) ) {
3584 + if ( version_compare( phpversion(), '7.0', '<' ) ) {
3124 3585 $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 3586 }
3126 3587
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 3588 foreach ( $message as $m ) {
3134 3589 ?>
3135 3590 <div class="frm-banner-alert frm_error_style frm_previous_install">
3136 3591 <?php echo esc_html( $m ); ?>
@@ -3260,16 +3715,10 @@
3260 3715 return $locales;
3261 3716 }
3262 3717
3263 3718 /**
3264 - * Output HTML containing reference text for accessibility
3265 - *
3266 - * @deprecated 5.1
3719 + * @return string
3267 3720 */
3268 - public static function multiselect_accessibility() {
3269 - _deprecated_function( __METHOD__, '5.1' );
3270 - }
3271 -
3272 3721 public static function get_menu_icon_class() {
3273 3722 if ( is_callable( 'FrmProAppHelper::get_settings' ) ) {
3274 3723 $settings = FrmProAppHelper::get_settings();
3275 3724 if ( is_object( $settings ) && ! empty( $settings->menu_icon ) ) {
@@ -3379,8 +3828,18 @@
3379 3828 return apply_filters( 'frm_images_dropdown_input_attrs', $input_attrs_str, $args );
3380 3829 }
3381 3830
3382 3831 /**
3832 + * @since 6.7.1
3833 + */
3834 + public static function get_images_dropdown_atts( $option, $args ) {
3835 + $image = self::get_images_dropdown_option_image( $option, $args );
3836 + $classes = self::get_images_dropdown_option_classes( $option, $args );
3837 + $custom_attrs = self::get_images_dropdown_option_html_attrs( $option, $args );
3838 + return compact( 'image', 'classes', 'custom_attrs' );
3839 + }
3840 +
3841 + /**
3383 3842 * Gets the image of each option in images_dropdown() method.
3384 3843 *
3385 3844 * @since 5.0.04
3386 3845 *
@@ -3391,9 +3850,9 @@
3391 3850 private static function get_images_dropdown_option_image( $option, $args ) {
3392 3851 $image = self::icon_by_class(
3393 3852 'frmfont ' . $option['svg'],
3394 3853 array(
3395 - 'echo' => false,
3854 + 'echo' => false,
3396 3855 )
3397 3856 );
3398 3857
3399 3858 $args['option'] = $option;
@@ -3531,15 +3990,15 @@
3531 3990 return $values;
3532 3991 }
3533 3992
3534 3993 /**
3535 - * Some back end fields allow privleged users to add scripts.
3994 + * Some back end fields allow privileged users to add scripts.
3536 3995 * A site that uses the DISALLOW_UNFILTERED_HTML always remove scripts on echo.
3537 3996 *
3538 3997 * @since 5.0.13
3539 3998 *
3540 3999 * @param string $value
3541 - * @param array|string $allowed 'all' for everything included as defaults
4000 + * @param array|string $allowed 'all' for everything included as defaults.
3542 4001 * @return string
3543 4002 */
3544 4003 public static function maybe_kses( $value, $allowed = 'all' ) {
3545 4004 if ( self::should_never_allow_unfiltered_html() ) {
@@ -3548,8 +4007,64 @@
3548 4007 return $value;
3549 4008 }
3550 4009
3551 4010 /**
4011 + * Check if an option attribute used in an [input] shortcode is safe.
4012 + *
4013 + * @since 6.11.2
4014 + *
4015 + * @param string $key
4016 + * @param string $context Either 'display' or 'update'. On update, we want to allow a few keys that are never displayed.
4017 + * @return bool
4018 + */
4019 + public static function input_key_is_safe( $key, $context = 'display' ) {
4020 + if ( 'update' === $context && in_array( $key, array( 'opt', 'label' ), true ) ) {
4021 + $safe = true;
4022 + } elseif ( 0 === strpos( $key, 'data-' ) ) {
4023 + // Allow all data attributes.
4024 + $safe = true;
4025 + } elseif ( 0 === strpos( $key, 'aria-' ) ) {
4026 + // Allow all aria attributes.
4027 + $safe = true;
4028 + } else {
4029 + $safe_keys = array(
4030 + 'class',
4031 + 'required',
4032 + 'title',
4033 + 'placeholder',
4034 + 'value',
4035 + 'readonly',
4036 + 'disabled',
4037 + 'size',
4038 + 'maxlength',
4039 + 'min',
4040 + 'max',
4041 + 'pattern',
4042 + 'step',
4043 + 'autofocus',
4044 + 'width',
4045 + 'height',
4046 + 'autocomplete',
4047 + 'tabindex',
4048 + 'role',
4049 + 'style',
4050 + );
4051 + $safe = in_array( $key, $safe_keys, true );
4052 + }//end if
4053 +
4054 + /**
4055 + * Filter the $safe value so additional keys can be allowed or disallowed.
4056 + *
4057 + * @since 6.11.2
4058 + *
4059 + * @param bool $safe True if the key is considered safe.
4060 + * @param string $key
4061 + * @param string $context Either 'display' or 'update'.
4062 + */
4063 + return (bool) apply_filters( 'frm_input_key_is_safe', $safe, $key, $context );
4064 + }
4065 +
4066 + /**
3552 4067 * @since 5.0.16
3553 4068 *
3554 4069 * @return bool
3555 4070 */
@@ -3574,20 +4089,9 @@
3574 4089
3575 4090 /**
3576 4091 * @since 5.0.17
3577 4092 *
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
4093 + * @param string $feature
3590 4094 * @return bool
3591 4095 */
3592 4096 public static function show_new_feature( $feature ) {
3593 4097 $link = FrmAddonsController::install_link( $feature );
@@ -3660,9 +4164,9 @@
3660 4164 public static function show_pill_text( $text = null ) {
3661 4165 if ( null === $text ) {
3662 4166 $text = __( 'NEW', 'formidable' );
3663 4167 }
3664 - echo '<span class="frm-new-pill">' . esc_html( $text ) . '</span>';
4168 + echo '<span class="frm-meta-tag frm-new-pill">' . esc_html( $text ) . '</span>';
3665 4169 }
3666 4170
3667 4171 /**
3668 4172 * Count the number of decimals digits.
@@ -3669,9 +4173,9 @@
3669 4173 *
3670 4174 * @since 5.2.07
3671 4175 *
3672 4176 * @param mixed $num Number.
3673 - * @return int|false Returns `false` if the passed parameter is not number.
4177 + * @return false|int Returns `false` if the passed parameter is not number.
3674 4178 */
3675 4179 public static function count_decimals( $num ) {
3676 4180 if ( ! is_numeric( $num ) ) {
3677 4181 return false;
@@ -3702,9 +4206,9 @@
3702 4206 }
3703 4207
3704 4208 add_filter(
3705 4209 'option_gmt_offset',
3706 - function( $offset ) {
4210 + function ( $offset ) {
3707 4211 if ( ! is_string( $offset ) || is_numeric( $offset ) ) {
3708 4212 // Leave a valid value alone.
3709 4213 return $offset;
3710 4214 }
@@ -3786,65 +4290,8 @@
3786 4290 return true;
3787 4291 }
3788 4292
3789 4293 /**
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 4294 * Display a dismissable warning message and save its dismissal state.
3848 4295 *
3849 4296 * @since 6.3
3850 4297 *
@@ -3856,9 +4303,9 @@
3856 4303 if ( ! $message || ! $option ) {
3857 4304 return;
3858 4305 }
3859 4306
3860 - $ajax_callback = function() use ( $option ) {
4307 + $ajax_callback = function () use ( $option ) {
3861 4308 self::dismiss_warning_message( $option );
3862 4309 };
3863 4310
3864 4311 // We're handling JS codes with `doJsonPost` and it adds 'frm_' to the beginning of the action.
@@ -3866,9 +4313,9 @@
3866 4313 add_action( 'wp_ajax_frm_' . $option, $ajax_callback );
3867 4314
3868 4315 add_filter(
3869 4316 'frm_message_list',
3870 - function( $show_messages ) use ( $message, $option ) {
4317 + function ( $show_messages ) use ( $message, $option ) {
3871 4318 if ( get_option( $option, false ) ) {
3872 4319 return $show_messages;
3873 4320 }
3874 4321
@@ -3875,9 +4322,9 @@
3875 4322 $dismiss_icon = self::icon_by_class(
3876 4323 'frmfont frm_close_icon',
3877 4324 array(
3878 4325 'aria-label' => _x( 'Dismiss', 'warning message: close icon label', 'formidable' ),
3879 - 'echo' => false,
4326 + 'echo' => false,
3880 4327 )
3881 4328 );
3882 4329
3883 4330 $show_messages[] = $message;
@@ -3904,6 +4351,124 @@
3904 4351 update_option( $option, true, 'no' );
3905 4352 }
3906 4353
3907 4354 wp_send_json_success();
4355 + }
4356 +
4357 + /**
4358 + * Lite license copy.
4359 + * Used in FrmDashboardController & FrmSettingsController
4360 + *
4361 + * @since 6.8
4362 + *
4363 + * @return string
4364 + */
4365 + public static function copy_for_lite_license() {
4366 + $message = __( 'You\'re using Formidable Forms Lite - no license needed. Enjoy!', 'formidable' ) . ' 🙂';
4367 +
4368 + if ( is_callable( 'FrmProAddonsController::get_readable_license_type' ) && ! class_exists( 'FrmProDashboardController' ) ) {
4369 + // Manage PRO versions without PRO dashboard functionality.
4370 + $license_type = FrmProAddonsController::get_readable_license_type();
4371 + if ( 'lite' !== strtolower( $license_type ) ) {
4372 + $message = 'Formidable Pro ' . $license_type;
4373 + }
4374 + }
4375 +
4376 + return apply_filters( 'frm_license_type_text', $message );
4377 + }
4378 +
4379 + /**
4380 + * Removes scripts that are unnecessarily loaded across the pages!
4381 + *
4382 + * @since 6.9
4383 + * @return void
4384 + */
4385 + public static function dequeue_extra_global_scripts() {
4386 + wp_dequeue_script( 'frm-surveys-admin' );
4387 + wp_dequeue_script( 'frm-quizzes-form-action' );
4388 + }
4389 +
4390 + /**
4391 + * Shows tooltip icon.
4392 + *
4393 + * @since 6.12
4394 + *
4395 + * @param string $tooltip_text Tooltip text.
4396 + * @param array $atts Tooltip wrapper HTML attributes.
4397 + *
4398 + * @return void
4399 + */
4400 + public static function tooltip_icon( $tooltip_text, $atts = array() ) {
4401 + $atts['title'] = $tooltip_text;
4402 + if ( isset( $atts['class'] ) ) {
4403 + $atts['class'] .= ' frm_help';
4404 + } else {
4405 + $atts['class'] = 'frm_help';
4406 + }
4407 + ?>
4408 + <span <?php self::array_to_html_params( $atts, true ); ?>>
4409 + <?php self::icon_by_class( 'frmfont frm_tooltip_icon' ); ?>
4410 + </span>
4411 + <?php
4412 + }
4413 +
4414 + /**
4415 + * Prints errors for settings in onboarding wizard or template settings.
4416 + *
4417 + * @since 6.15
4418 + *
4419 + * @param array $args Args.
4420 + *
4421 + * @return void
4422 + */
4423 + public static function print_setting_error( $args ) {
4424 + $args = wp_parse_args(
4425 + $args,
4426 + array(
4427 + 'id' => '',
4428 + 'errors' => array(),
4429 + 'class' => '',
4430 + )
4431 + );
4432 +
4433 + $args['class'] .= ' frm-validation-error frm-mt-xs frm_hidden';
4434 + ?>
4435 + <span id="<?php echo esc_attr( $args['id'] ); ?>" class="<?php echo esc_attr( $args['class'] ); ?>">
4436 + <?php
4437 + if ( is_array( $args['errors'] ) ) {
4438 + foreach ( $args['errors'] as $key => $msg ) {
4439 + ?>
4440 + <span frm-error="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $msg ); ?></span>
4441 + <?php
4442 + }
4443 + } else {
4444 + echo '<span>' . esc_html( $args['errors'] ) . '</span>';
4445 + }
4446 + ?>
4447 + </span>
4448 + <?php
4449 + }
4450 +
4451 + /**
4452 + * Check if GDPR is enabled.
4453 + *
4454 + * @since 6.19
4455 + *
4456 + * @return bool
4457 + */
4458 + public static function is_gdpr_enabled() {
4459 + $frm_settings = self::get_settings();
4460 + return $frm_settings->enable_gdpr || $frm_settings->no_ips || $frm_settings->custom_header_ip || $frm_settings->no_gdpr_cookies;
4461 + }
4462 +
4463 + /**
4464 + * Check if GDPR cookies are disabled.
4465 + *
4466 + * @since 6.19
4467 + *
4468 + * @return bool
4469 + */
4470 + public static function no_gdpr_cookies() {
4471 + $frm_settings = self::get_settings();
4472 + return $frm_settings->enable_gdpr && $frm_settings->no_gdpr_cookies;
3908 4473 }
3909 4474 }