PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.16
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.16
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 +671 -296 6.56.16 View file →
@@ -3,27 +3,47 @@
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;
7 + /**
8 + * Version of the database we are moving to.
9 + *
10 + * @var int
11 + */
12 + public static $db_version = 101;
10 13
11 14 /**
12 - * @var bool $added_gmt_offset_filter
15 + * Deprecated.
16 + *
17 + * @var int
13 18 */
19 + public static $pro_db_version = 37;
20 +
21 + /**
22 + * @var float
23 + */
24 + public static $font_version = 7;
25 +
26 + /**
27 + * @var bool
28 + */
14 29 private static $added_gmt_offset_filter = false;
15 30
16 31 /**
17 32 * @since 2.0
33 + *
34 + * @var string
18 35 */
19 - public static $plug_version = '6.5';
36 + public static $plug_version = '6.16';
20 37
21 38 /**
39 + * @var bool
40 + */
41 + private static $included_svg = false;
42 +
43 + /**
22 44 * @since 1.07.02
23 45 *
24 - * @param none
25 - *
26 46 * @return string The version of this plugin
27 47 */
28 48 public static function plugin_version() {
29 49 return self::$plug_version;
@@ -28,21 +48,33 @@
28 48 public static function plugin_version() {
29 49 return self::$plug_version;
30 50 }
31 51
52 + /**
53 + * @return string
54 + */
32 55 public static function plugin_folder() {
33 56 return basename( self::plugin_path() );
34 57 }
35 58
59 + /**
60 + * @return string
61 + */
36 62 public static function plugin_path() {
37 - return dirname( dirname( dirname( __FILE__ ) ) );
63 + return dirname( dirname( __DIR__ ) );
38 64 }
39 65
66 + /**
67 + * @return string
68 + */
40 69 public static function plugin_url() {
41 - // Prevously FRM_URL constant.
70 + // Previously FRM_URL constant.
42 71 return plugins_url( '', self::plugin_path() . '/formidable.php' );
43 72 }
44 73
74 + /**
75 + * @return string
76 + */
45 77 public static function relative_plugin_url() {
46 78 return str_replace( array( 'https:', 'http:' ), '', self::plugin_url() );
47 79 }
48 80
@@ -63,8 +95,12 @@
63 95 public static function site_name() {
64 96 return get_option( 'blogname' );
65 97 }
66 98
99 + /**
100 + * @param string $url
101 + * @return string
102 + */
67 103 public static function make_affiliate_url( $url ) {
68 104 $affiliate_id = self::get_affiliate();
69 105 if ( ! empty( $affiliate_id ) ) {
70 106 $url = str_replace( array( 'http://', 'https://' ), '', $url );
@@ -73,8 +109,11 @@
73 109
74 110 return $url;
75 111 }
76 112
113 + /**
114 + * @return int
115 + */
77 116 public static function get_affiliate() {
78 117 return absint( apply_filters( 'frm_affiliate_id', 0 ) );
79 118 }
80 119
@@ -131,9 +170,9 @@
131 170 *
132 171 * @since 2.0
133 172 *
134 173 * @param array $args - May include the form id when values need translation.
135 - * @return FrmSettings $frm_setings
174 + * @return FrmSettings $frm_settings
136 175 */
137 176 public static function get_settings( $args = array() ) {
138 177 global $frm_settings;
139 178 if ( empty( $frm_settings ) ) {
@@ -145,32 +184,39 @@
145 184
146 185 return $frm_settings;
147 186 }
148 187
188 + /**
189 + * @return string
190 + */
149 191 public static function get_menu_name() {
150 192 $frm_settings = self::get_settings();
151 193
152 - return $frm_settings->menu;
194 + return FrmAddonsController::is_license_expired() ? 'Formidable' : $frm_settings->menu;
153 195 }
154 196
155 197 /**
156 198 * Determine if the current branding is set to 'formidable'.
199 + * Checks the menu icon, and verifies if it matches the formidable branding.
157 200 *
158 - * Checks the menu title, retrieved through get_menu_name,
159 - * and verifies if it matches the 'formidable' branding.
160 - *
161 201 * @since 6.4.2
162 202 *
163 - * @return bool True if the menu title is 'formidable', false otherwise.
203 + * @return bool True if the menu icon is the logo, false otherwise.
164 204 */
165 205 public static function is_formidable_branding() {
166 - $menu_title = self::get_menu_name();
206 + if ( ! self::pro_is_installed() ) {
207 + return true;
208 + }
167 209
168 - return 'formidable' === strtolower( trim( $menu_title ) );
210 + $menu_icon = self::get_menu_icon_class();
211 + return strpos( $menu_icon, 'frm_logo_icon' ) !== false;
169 212 }
170 213
171 214 /**
172 215 * @since 3.05
216 + *
217 + * @param array $atts
218 + * @return string
173 219 */
174 220 public static function svg_logo( $atts = array() ) {
175 221 $defaults = array(
176 222 'height' => 18,
@@ -187,8 +233,11 @@
187 233 }
188 234
189 235 /**
190 236 * @since 4.0
237 + *
238 + * @param array $atts
239 + * @return void
191 240 */
192 241 public static function show_logo( $atts = array() ) {
193 242 echo self::kses( self::svg_logo( $atts ), 'all' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
194 243 }
@@ -194,8 +243,10 @@
194 243 }
195 244
196 245 /**
197 246 * @since 4.03.02
247 + *
248 + * @return void
198 249 */
199 250 public static function show_header_logo() {
200 251 $icon = self::svg_logo(
201 252 array(
@@ -217,21 +268,38 @@
217 268 }
218 269
219 270 /**
220 271 * @since 2.02.04
272 + *
273 + * @return bool
221 274 */
222 275 public static function ips_saved() {
223 276 $frm_settings = self::get_settings();
224 -
225 277 return ! $frm_settings->no_ips;
226 278 }
227 279
280 + /**
281 + * @return bool
282 + */
228 283 public static function pro_is_installed() {
229 - return apply_filters( 'frm_pro_installed', false );
284 + return (bool) apply_filters( 'frm_pro_installed', false );
230 285 }
231 286
232 287 /**
288 + * Check if the Pro plugin is installed, whether authorized or not.
289 + *
290 + * @since 6.8.3
291 + *
292 + * @return bool
293 + */
294 + public static function pro_is_included() {
295 + return function_exists( 'load_formidable_pro' );
296 + }
297 +
298 + /**
233 299 * @since 4.06.02
300 + *
301 + * @return bool
234 302 */
235 303 public static function pro_is_connected() {
236 304 global $frm_vars;
237 305 return self::pro_is_installed() && $frm_vars['pro_is_authorized'];
@@ -238,8 +306,10 @@
238 306 }
239 307
240 308 /**
241 309 * @since 4.06
310 + *
311 + * @return bool
242 312 */
243 313 public static function is_form_builder_page() {
244 314 $action = self::simple_get( 'frm_action', 'sanitize_title' );
245 315 return self::is_admin_page( 'formidable' ) && ( $action === 'edit' || $action === 'settings' || $action === 'duplicate' );
@@ -244,8 +314,11 @@
244 314 $action = self::simple_get( 'frm_action', 'sanitize_title' );
245 315 return self::is_admin_page( 'formidable' ) && ( $action === 'edit' || $action === 'settings' || $action === 'duplicate' );
246 316 }
247 317
318 + /**
319 + * @return bool
320 + */
248 321 public static function is_formidable_admin() {
249 322 $page = self::simple_get( 'page', 'sanitize_title' );
250 323 $is_formidable = strpos( $page, 'formidable' ) !== false;
251 324 if ( empty( $page ) ) {
@@ -259,11 +332,11 @@
259 332 * Check for certain page in Formidable settings
260 333 *
261 334 * @since 2.0
262 335 *
263 - * @param string $page The name of the page to check
336 + * @param string $page The name of the page to check.
264 337 *
265 - * @return boolean
338 + * @return bool
266 339 */
267 340 public static function is_admin_page( $page = 'formidable' ) {
268 341 global $pagenow;
269 342 $get_page = self::simple_get( 'page', 'sanitize_title' );
@@ -282,8 +355,10 @@
282 355 * If the current page is for editing or creating a view.
283 356 * Returns false for the views listing page.
284 357 *
285 358 * @since 4.0
359 + *
360 + * @return bool
286 361 */
287 362 public static function is_view_builder_page() {
288 363 global $pagenow;
289 364
@@ -293,10 +368,10 @@
293 368
294 369 $post_type = self::simple_get( 'post_type', 'sanitize_title' );
295 370
296 371 if ( empty( $post_type ) ) {
297 - $post_id = self::simple_get( 'post', 'absint' );
298 - $post = get_post( $post_id );
372 + $post_id = self::simple_get( 'post', 'absint' );
373 + $post = get_post( $post_id );
299 374 $post_type = $post ? $post->post_type : '';
300 375 }
301 376
302 377 return $post_type === 'frm_display';
@@ -306,17 +381,15 @@
306 381 * Check for the form preview page
307 382 *
308 383 * @since 2.0
309 384 *
310 - * @param None
311 - *
312 - * @return boolean
385 + * @return bool
313 386 */
314 387 public static function is_preview_page() {
315 388 global $pagenow;
316 389 $action = self::simple_get( 'action', 'sanitize_title' );
317 390
318 - return $pagenow && $pagenow == 'admin-ajax.php' && $action == 'frm_forms_preview';
391 + return $pagenow && $pagenow === 'admin-ajax.php' && $action === 'frm_forms_preview';
319 392 }
320 393
321 394 /**
322 395 * Check for ajax except the form preview page
@@ -322,16 +395,17 @@
322 395 * Check for ajax except the form preview page
323 396 *
324 397 * @since 2.0
325 398 *
326 - * @param None
327 - *
328 - * @return boolean
399 + * @return bool
329 400 */
330 401 public static function doing_ajax() {
331 402 return wp_doing_ajax() && ! self::is_preview_page();
332 403 }
333 404
405 + /**
406 + * @return string
407 + */
334 408 public static function js_suffix() {
335 409 return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
336 410 }
337 411
@@ -336,13 +410,13 @@
336 410 }
337 411
338 412 /**
339 413 * @since 2.0.8
414 + * @return bool
340 415 */
341 416 public static function prevent_caching() {
342 417 global $frm_vars;
343 -
344 - return isset( $frm_vars['prevent_caching'] ) && $frm_vars['prevent_caching'];
418 + return ! empty( $frm_vars['prevent_caching'] );
345 419 }
346 420
347 421 /**
348 422 * Check if on an admin page
@@ -348,9 +422,9 @@
348 422 * Check if on an admin page
349 423 *
350 424 * @since 2.0
351 425 *
352 - * @return boolean
426 + * @return bool
353 427 */
354 428 public static function is_admin() {
355 429 $is_admin = is_admin() && ! wp_doing_ajax();
356 430
@@ -365,17 +439,22 @@
365 439 * Check if value contains blank value or empty array
366 440 *
367 441 * @since 2.0
368 442 *
369 - * @param mixed $value - value to check
370 - * @param string
443 + * @param mixed $value Value to check.
444 + * @param string $empty
371 445 *
372 - * @return boolean
446 + * @return bool
373 447 */
374 448 public static function is_empty_value( $value, $empty = '' ) {
375 449 return ( is_array( $value ) && empty( $value ) ) || $value === $empty;
376 450 }
377 451
452 + /**
453 + * @param mixed $value
454 + * @param string $empty
455 + * @return bool
456 + */
378 457 public static function is_not_empty_value( $value, $empty = '' ) {
379 458 return ! self::is_empty_value( $value, $empty );
380 459 }
381 460
@@ -394,14 +473,13 @@
394 473
395 474 /**
396 475 * Get the server OS
397 476 *
398 - * @since 6.4.x
477 + * @since 6.4.2
399 478 *
400 479 * @return string
401 480 */
402 481 public static function get_server_os() {
403 -
404 482 if ( function_exists( 'php_uname' ) ) {
405 483 return php_uname( 's' );
406 484 }
407 485
@@ -429,9 +507,10 @@
429 507 }
430 508
431 509 $key = self::get_server_value( $key );
432 510 foreach ( explode( ',', $key ) as $ip ) {
433 - $ip = trim( $ip ); // Just to be safe.
511 + // Just to be safe.
512 + $ip = trim( $ip );
434 513
435 514 if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
436 515 return sanitize_text_field( $ip );
437 516 }
@@ -522,15 +601,24 @@
522 601
523 602 return $value;
524 603 }
525 604
605 + /**
606 + * Get a value from $_POST data.
607 + *
608 + * @param string $param The key we are trying to access data from in $_POST.
609 + * @param mixed $default The default if nothing is being sent.
610 + * @param callable|string $sanitize Make sure to pass a sanitize method here. This function will NOT sanitize by default.
611 + * @param bool $serialized
612 + * @return mixed
613 + */
526 614 public static function get_post_param( $param, $default = '', $sanitize = '', $serialized = false ) {
527 615 return self::get_simple_request(
528 616 array(
529 - 'type' => 'post',
530 - 'param' => $param,
531 - 'default' => $default,
532 - 'sanitize' => $sanitize,
617 + 'type' => 'post',
618 + 'param' => $param,
619 + 'default' => $default,
620 + 'sanitize' => $sanitize,
533 621 'serialized' => $serialized,
534 622 )
535 623 );
536 624 }
@@ -541,9 +629,9 @@
541 629 * @param string $param
542 630 * @param string $sanitize
543 631 * @param string $default
544 632 *
545 - * @return string|array
633 + * @return array|string
546 634 */
547 635 public static function simple_get( $param, $sanitize = 'sanitize_text_field', $default = '' ) {
548 636 return self::get_simple_request(
549 637 array(
@@ -561,16 +649,16 @@
561 649 * @since 2.0.6
562 650 *
563 651 * @param array $args
564 652 *
565 - * @return string|array
653 + * @return array|string
566 654 */
567 655 public static function get_simple_request( $args ) {
568 656 $defaults = array(
569 - 'param' => '',
570 - 'default' => '',
571 - 'type' => 'get',
572 - 'sanitize' => 'sanitize_text_field',
657 + 'param' => '',
658 + 'default' => '',
659 + 'type' => 'get',
660 + 'sanitize' => 'sanitize_text_field',
573 661 'serialized' => false,
574 662 );
575 663 $args = wp_parse_args( $args, $defaults );
576 664
@@ -587,13 +675,12 @@
587 675 if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
588 676 self::unserialize_or_decode( $value );
589 677 }
590 678 }
591 - } else {
592 - if ( isset( $_REQUEST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
679 + } elseif ( isset( $_REQUEST[ $args['param'] ] ) ) {
680 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
593 681 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
594 682 $value = wp_unslash( $_REQUEST[ $args['param'] ] );
595 - }
596 683 }
597 684
598 685 self::sanitize_value( $args['sanitize'], $value );
599 686
@@ -617,19 +704,35 @@
617 704
618 705 return $value;
619 706 }
620 707
708 + /**
709 + * Sanitize a value in-place.
710 + * If $value is an array, the sanitize function will get called for each item.
711 + *
712 + * @param callable $sanitize
713 + * @param mixed $value
714 + * @return void
715 + */
621 716 public static function sanitize_value( $sanitize, &$value ) {
622 - if ( ! empty( $sanitize ) ) {
623 - if ( is_array( $value ) ) {
624 - $temp_values = $value;
625 - foreach ( $temp_values as $k => $v ) {
626 - self::sanitize_value( $sanitize, $value[ $k ] );
627 - }
628 - } else {
629 - $value = call_user_func( $sanitize, $value );
717 + if ( ! $sanitize ) {
718 + return;
719 + }
720 +
721 + if ( is_object( $value ) ) {
722 + $value = '';
723 + return;
724 + }
725 +
726 + if ( is_array( $value ) ) {
727 + $temp_values = $value;
728 + foreach ( $temp_values as $k => $v ) {
729 + self::sanitize_value( $sanitize, $value[ $k ] );
630 730 }
731 + return;
631 732 }
733 +
734 + $value = call_user_func( $sanitize, $value );
632 735 }
633 736
634 737 public static function sanitize_request( $sanitize_method, &$values ) {
635 738 $temp_values = $values;
@@ -641,15 +744,52 @@
641 744 }
642 745
643 746 /**
644 747 * @since 4.0.04
748 + *
749 + * @param mixed $value
750 + * @return void
645 751 */
646 752 public static function sanitize_with_html( &$value ) {
647 - self::sanitize_value( 'wp_kses_post', $value );
753 + if ( current_user_can( 'frm_edit_entries' ) || current_user_can( 'administrator' ) ) {
754 + // Only strip unsafe HTML like scripts for a privileged user submitting a form.
755 + self::sanitize_value( 'wp_kses_post', $value );
756 + } else {
757 + self::sanitize_value( self::class . '::strip_most_html', $value );
758 + }
648 759 self::decode_specialchars( $value );
649 760 }
650 761
651 762 /**
763 + * Allow only a small set of very basic HTML for unprivileged users.
764 + *
765 + * @since 6.7.1
766 + *
767 + * @param string $value
768 + */
769 + public static function strip_most_html( $value ) {
770 + $allowed_html = array(
771 + 'b' => array(),
772 + 'br' => array(),
773 + 'strong' => array(),
774 + 'p' => array(),
775 + 'i' => array(),
776 + 'ul' => array(),
777 + 'ol' => array(),
778 + 'li' => array(),
779 + );
780 +
781 + /**
782 + * @since 6.7.1
783 + *
784 + * @param array $allowed_html
785 + */
786 + $allowed_html = apply_filters( 'frm_allowed_form_input_html', $allowed_html );
787 +
788 + return wp_kses( $value, $allowed_html );
789 + }
790 +
791 + /**
652 792 * Do wp_specialchars_decode to get back '&' that wp_kses_post might have turned to '&'
653 793 * this MUST be done, else we'll be back to the '& entity' problem.
654 794 *
655 795 * @since 4.0.04
@@ -683,10 +823,12 @@
683 823 $translation = array(
684 824 '"' => '"',
685 825 '"' => '"',
686 826 '"' => '"',
687 - '&lt; ' => '< ', // The space preserves the HTML.
688 - '&#060; ' => '< ', // The space preserves the HTML.
827 + // The space preserves the HTML.
828 + '&lt; ' => '< ',
829 + // The space preserves the HTML.
830 + '&#060; ' => '< ',
689 831 '&gt;' => '>',
690 832 '&#062;' => '>',
691 833 '&amp;' => '&',
692 834 '&#038;' => '&',
@@ -713,10 +855,10 @@
713 855 * Sanitize the value, and allow some HTML
714 856 *
715 857 * @since 2.0
716 858 *
717 - * @param string $value
718 - * @param array|string $allowed 'all' for everything included as defaults
859 + * @param string $value
860 + * @param array|string $allowed 'all' for everything included as defaults.
719 861 *
720 862 * @return string
721 863 */
722 864 public static function kses( $value, $allowed = array() ) {
@@ -817,9 +959,9 @@
817 959 'id' => true,
818 960 );
819 961
820 962 return array(
821 - 'a' => array(
963 + 'a' => array(
822 964 'class' => true,
823 965 'href' => true,
824 966 'id' => true,
825 967 'rel' => true,
@@ -888,16 +1030,16 @@
888 1030 'cite' => true,
889 1031 'title' => true,
890 1032 ),
891 1033 'rect' => array(
892 - 'class' => true,
893 - 'fill' => true,
894 - 'height' => true,
895 - 'width' => true,
896 - 'x' => true,
897 - 'y' => true,
898 - 'rx' => true,
899 - 'stroke' => true,
1034 + 'class' => true,
1035 + 'fill' => true,
1036 + 'height' => true,
1037 + 'width' => true,
1038 + 'x' => true,
1039 + 'y' => true,
1040 + 'rx' => true,
1041 + 'stroke' => true,
900 1042 'stroke-opacity' => true,
901 1043 'stroke-width' => true,
902 1044 ),
903 1045 'section' => $allow_class,
@@ -932,9 +1074,9 @@
932 1074 'xlink:href' => true,
933 1075 ),
934 1076 'ul' => $allow_class,
935 1077 'label' => array(
936 - 'for' => true,
1078 + 'for' => true,
937 1079 'class' => true,
938 1080 'id' => true,
939 1081 ),
940 1082 'button' => array(
@@ -952,9 +1094,9 @@
952 1094 *
953 1095 * @since 2.0
954 1096 */
955 1097 public static function remove_get_action() {
956 - if ( ! isset( $_GET ) ) {
1098 + if ( empty( $_GET ) ) {
957 1099 return;
958 1100 }
959 1101
960 1102 $action_name = isset( $_GET['action'] ) ? 'action' : ( isset( $_GET['action2'] ) ? 'action2' : '' );
@@ -971,9 +1113,9 @@
971 1113 /**
972 1114 * Check the WP query for a parameter
973 1115 *
974 1116 * @since 2.0
975 - * @return string|array
1117 + * @return array|string
976 1118 */
977 1119 public static function get_query_var( $value, $param ) {
978 1120 if ( $value != '' ) {
979 1121 return $value;
@@ -990,10 +1132,12 @@
990 1132 /**
991 1133 * Try to show the SVG if possible. Otherwise, use the font icon.
992 1134 *
993 1135 * @since 4.0.02
1136 + *
994 1137 * @param string $class
995 1138 * @param array $atts
1139 + * @return string|null
996 1140 */
997 1141 public static function icon_by_class( $class, $atts = array() ) {
998 1142 $echo = ! isset( $atts['echo'] ) || $atts['echo'];
999 1143 if ( isset( $atts['echo'] ) ) {
@@ -1003,14 +1147,16 @@
1003 1147 $html_atts = self::array_to_html_params( $atts );
1004 1148
1005 1149 $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
1006 1150
1007 - // Replace icons that have been removed.
1151 + // Replace icons that have been removed or renamed.
1008 1152 $deprecated = array(
1009 - 'frm_clone_solid_icon' => 'frm_clone_icon',
1153 + 'frm_clone_solid_icon' => 'frm_clone_icon',
1154 + 'frm_keyalt_icon' => 'frm_key_icon',
1155 + 'frm_keyalt_solid_icon' => 'frm_key_solid_icon',
1010 1156 );
1011 1157 if ( isset( $deprecated[ $icon ] ) ) {
1012 - $icon = $deprecated[ $icon ];
1158 + $icon = $deprecated[ $icon ];
1013 1159 $class = str_replace( $icon, $deprecated[ $icon ], $class );
1014 1160 }
1015 1161
1016 1162 if ( $icon === $class ) {
@@ -1020,11 +1166,9 @@
1020 1166 if ( strpos( $icon, ' ' ) ) {
1021 1167 $icon = explode( ' ', $icon );
1022 1168 $icon = reset( $icon );
1023 1169 }
1024 - $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '>
1025 - <use xlink:href="#' . esc_attr( $icon ) . '" />
1026 - </svg>';
1170 + $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use xlink:href="#' . esc_attr( $icon ) . '" /></svg>';
1027 1171 }
1028 1172
1029 1173 if ( $echo ) {
1030 1174 echo self::kses_icon( $icon ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -1110,11 +1254,18 @@
1110 1254 /**
1111 1255 * Include svg images.
1112 1256 *
1113 1257 * @since 4.0.02
1258 + * @return void
1114 1259 */
1115 1260 public static function include_svg() {
1116 - include_once self::plugin_path() . '/images/icons.svg';
1261 + if ( self::$included_svg ) {
1262 + return;
1263 + }
1264 +
1265 + // Use readfile instead of include_once because of a default security rule in Snuffleupagus.
1266 + readfile( self::plugin_path() . '/images/icons.svg' );
1267 + self::$included_svg = true;
1117 1268 }
1118 1269
1119 1270 /**
1120 1271 * Convert an associative array to HTML values.
@@ -1126,9 +1277,9 @@
1126 1277 * @param bool $echo
1127 1278 * @return string|void
1128 1279 */
1129 1280 public static function array_to_html_params( $atts, $echo = false ) {
1130 - $callback = function() use ( $atts ) {
1281 + $callback = function () use ( $atts ) {
1131 1282 if ( $atts ) {
1132 1283 foreach ( $atts as $key => $value ) {
1133 1284 echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
1134 1285 }
@@ -1143,9 +1294,9 @@
1143 1294 * @since 5.0.13
1144 1295 *
1145 1296 * @param Closure $echo_function
1146 1297 * @param bool $echo
1147 - * @return string|void
1298 + * @return string|null
1148 1299 */
1149 1300 public static function clip( $echo_function, $echo = false ) {
1150 1301 if ( ! $echo ) {
1151 1302 ob_start();
@@ -1163,12 +1314,15 @@
1163 1314 }
1164 1315
1165 1316 /**
1166 1317 * @since 3.0
1318 + *
1319 + * @param array $atts
1320 + * @return void
1167 1321 */
1168 1322 public static function get_admin_header( $atts ) {
1169 - $has_nav = ( isset( $atts['form'] ) && ! empty( $atts['form'] ) && ( ! isset( $atts['is_template'] ) || ! $atts['is_template'] ) );
1170 - if ( ! isset( $atts['close'] ) || empty( $atts['close'] ) ) {
1323 + $has_nav = ! empty( $atts['form'] ) && empty( $atts['is_template'] );
1324 + if ( empty( $atts['close'] ) ) {
1171 1325 $atts['close'] = admin_url( 'admin.php?page=formidable' );
1172 1326 }
1173 1327 if ( ! isset( $atts['import_link'] ) ) {
1174 1328 $atts['import_link'] = false;
@@ -1173,9 +1327,9 @@
1173 1327 if ( ! isset( $atts['import_link'] ) ) {
1174 1328 $atts['import_link'] = false;
1175 1329 }
1176 1330
1177 - include( self::plugin_path() . '/classes/views/shared/admin-header.php' );
1331 + include self::plugin_path() . '/classes/views/shared/admin-header.php';
1178 1332 }
1179 1333
1180 1334 /**
1181 1335 * @since 6.0
@@ -1211,10 +1365,22 @@
1211 1365 return;
1212 1366 }
1213 1367 ?>
1214 1368 <div class="frm-upgrade-bar">
1215 - <span>You're using Formidable Forms Lite. To unlock more features consider</span>
1216 - <a href="<?php echo esc_url( self::admin_upgrade_link( 'top-bar' ) ); ?>" target="_blank" rel="noopener">upgrading to Pro</a>.
1369 + <?php
1370 + $upgrade_link = self::admin_upgrade_link(
1371 + array(
1372 + 'medium' => 'settings-license',
1373 + 'content' => 'lite-banner',
1374 + )
1375 + );
1376 + printf(
1377 + /* translators: %1$s: Start link HTML, %2$s: End link HTML */
1378 + esc_html__( 'You\'re using Formidable Forms Lite. To unlock more features consider %1$supgrading to PRO%2$s.', 'formidable' ),
1379 + '<a href="' . esc_url( $upgrade_link ) . '">',
1380 + '</a>'
1381 + );
1382 + ?>
1217 1383 </div>
1218 1384 <?php
1219 1385 }
1220 1386
@@ -1231,8 +1397,10 @@
1231 1397 * Render a button for a new item (Form, Application, etc).
1232 1398 *
1233 1399 * @since 3.0
1234 1400 * @param array $atts {
1401 + * Details about the button.
1402 + *
1235 1403 * @type array $link_hook Custom link hook, calls do_action and exits early.
1236 1404 * @type string $new_link Href value, default #.
1237 1405 * @type string $class Custom class names, space separated.
1238 1406 * @type string $button_text Button text. Default "Add New".
@@ -1244,9 +1412,9 @@
1244 1412 do_action( $atts['link_hook']['hook'], $atts['link_hook']['param'] );
1245 1413 return;
1246 1414 }
1247 1415
1248 - if ( empty( $atts['new_link'] ) && empty( $atts['trigger_new_form_modal'] ) && empty( $atts['class'] ) ) {
1416 + if ( empty( $atts['new_link'] ) && empty( $atts['create_form'] ) && empty( $atts['class'] ) ) {
1249 1417 // Do not render a button if none of these attributes are set.
1250 1418 return;
1251 1419 }
1252 1420
@@ -1252,12 +1420,8 @@
1252 1420
1253 1421 $href = ! empty( $atts['new_link'] ) ? esc_url( $atts['new_link'] ) : '#';
1254 1422 $class = 'button button-primary frm-button-primary';
1255 1423
1256 - if ( ! empty( $atts['trigger_new_form_modal'] ) ) {
1257 - $class .= ' frm-trigger-new-form-modal';
1258 - }
1259 -
1260 1424 if ( ! empty( $atts['class'] ) ) {
1261 1425 $class .= ' ' . $atts['class'];
1262 1426 }
1263 1427
@@ -1274,10 +1438,11 @@
1274 1438 'placeholder' => '',
1275 1439 'tosearch' => '',
1276 1440 'text' => __( 'Search', 'formidable' ),
1277 1441 'input_id' => '',
1442 + 'value' => false,
1278 1443 );
1279 - $atts = array_merge( $defaults, $atts );
1444 + $atts = array_merge( $defaults, $atts );
1280 1445
1281 1446 if ( $atts['input_id'] === 'template' && empty( $atts['tosearch'] ) ) {
1282 1447 $atts['tosearch'] = 'frm-card';
1283 1448 }
@@ -1288,8 +1453,27 @@
1288 1453 }
1289 1454
1290 1455 $input_id = $atts['input_id'] . '-search-input';
1291 1456
1457 + $input_atts = array(
1458 + 'type' => 'search',
1459 + 'id' => $input_id,
1460 + 'name' => 's',
1461 + 'placeholder' => $atts['placeholder'],
1462 + 'class' => $class,
1463 + 'data-tosearch' => $atts['tosearch'],
1464 + );
1465 +
1466 + if ( is_string( $atts['value'] ) ) {
1467 + $input_atts['value'] = $atts['value'];
1468 + } elseif ( isset( $_REQUEST['s'] ) ) {
1469 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1470 + $input_atts['value'] = wp_unslash( $_REQUEST['s'] );
1471 + }
1472 +
1473 + if ( ! empty( $atts['tosearch'] ) ) {
1474 + $input_atts['autocomplete'] = 'off';
1475 + }
1292 1476 ?>
1293 1477 <p class="frm-search">
1294 1478 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1295 1479 <?php echo esc_html( $atts['text'] ); ?>:
@@ -1294,15 +1478,9 @@
1294 1478 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1295 1479 <?php echo esc_html( $atts['text'] ); ?>:
1296 1480 </label>
1297 1481 <span class="frmfont frm_search_icon"></span>
1298 - <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s"
1299 - value="<?php _admin_search_query(); ?>" placeholder="<?php echo esc_attr( $atts['placeholder'] ); ?>"
1300 - class="<?php echo esc_attr( $class ); ?>" data-tosearch="<?php echo esc_attr( $atts['tosearch'] ); ?>"
1301 - <?php if ( ! empty( $atts['tosearch'] ) ) { ?>
1302 - autocomplete="off"
1303 - <?php } ?>
1304 - />
1482 + <input <?php self::array_to_html_params( $input_atts, true ); ?> />
1305 1483 <?php
1306 1484 if ( empty( $atts['tosearch'] ) ) {
1307 1485 submit_button( $atts['text'], 'button-secondary', '', false, array( 'id' => 'search-submit' ) );
1308 1486 }
@@ -1312,8 +1490,9 @@
1312 1490 }
1313 1491
1314 1492 /**
1315 1493 * @param string $type
1494 + * @return void
1316 1495 */
1317 1496 public static function trigger_hook_load( $type, $object = null ) {
1318 1497 // Only load the form hooks once.
1319 1498 $hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
@@ -1357,9 +1536,9 @@
1357 1536 'new_file_path' => self::plugin_path() . '/js',
1358 1537 )
1359 1538 );
1360 1539 $new_file = new FrmCreateFile( $file_atts );
1361 - $files = array(
1540 + $files = array(
1362 1541 FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.min.js',
1363 1542 );
1364 1543
1365 1544 /**
@@ -1376,14 +1555,14 @@
1376 1555 * True when value is 1, true, 'true', 'yes'
1377 1556 *
1378 1557 * @since 1.07.10
1379 1558 *
1380 - * @param string $value The value to compare
1559 + * @param string $value The value to compare.
1381 1560 *
1382 - * @return boolean True or False
1561 + * @return bool
1383 1562 */
1384 1563 public static function is_true( $value ) {
1385 - return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
1564 + return true === $value || 1 == $value || 'true' === $value || 'yes' === $value;
1386 1565 }
1387 1566
1388 1567 /**
1389 1568 * Gets all post from a specific post type.
@@ -1449,9 +1628,9 @@
1449 1628
1450 1629 wp_enqueue_script( 'jquery-ui-autocomplete' );
1451 1630
1452 1631 $selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
1453 - $title = '';
1632 + $title = '';
1454 1633
1455 1634 if ( $selected ) {
1456 1635 $title = get_the_title( $selected );
1457 1636 }
@@ -1467,11 +1646,11 @@
1467 1646 <?php
1468 1647 }
1469 1648
1470 1649 /**
1471 - * @param array $args
1472 - * @param string $page_id Deprecated.
1473 - * @param boolean $truncate Deprecated.
1650 + * @param array $args
1651 + * @param string $page_id Deprecated.
1652 + * @param bool $truncate Deprecated.
1474 1653 */
1475 1654 public static function wp_pages_dropdown( $args = array(), $page_id = '', $truncate = false ) {
1476 1655 self::prep_page_dropdown_params( $page_id, $truncate, $args );
1477 1656
@@ -1515,13 +1694,13 @@
1515 1694 * @since 4.10.01 Added `post_type` and `autocomplete_placeholder` to the arguments array.
1516 1695 */
1517 1696 private static function preformat_selection_args( $args ) {
1518 1697 $defaults = array(
1519 - 'truncate' => false,
1520 - 'placeholder' => ' ',
1521 - 'field_name' => '',
1522 - 'page_id' => '',
1523 - 'post_type' => 'page',
1698 + 'truncate' => false,
1699 + 'placeholder' => ' ',
1700 + 'field_name' => '',
1701 + 'page_id' => '',
1702 + 'post_type' => 'page',
1524 1703 'autocomplete_placeholder' => __( 'Select a Page', 'formidable' ),
1525 1704 );
1526 1705
1527 1706 return array_merge( $defaults, $args );
@@ -1601,16 +1780,16 @@
1601 1780 return $link;
1602 1781 }
1603 1782
1604 1783 /**
1605 - * @param string $field_name
1606 - * @param string|array $capability
1607 - * @param string $multiple 'single' and 'multiple'
1784 + * @param string $field_name
1785 + * @param array|string $capability
1786 + * @param string $multiple 'single' and 'multiple'.
1608 1787 */
1609 1788 public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
1610 1789 ?>
1611 1790 <select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>"
1612 - <?php echo ( 'multiple' === $multiple ) ? 'multiple="multiple"' : ''; ?>
1791 + <?php echo 'multiple' === $multiple ? 'multiple="multiple"' : ''; ?>
1613 1792 class="frm_multiselect">
1614 1793 <?php self::roles_options( $capability ); ?>
1615 1794 </select>
1616 1795 <?php
@@ -1618,9 +1797,9 @@
1618 1797
1619 1798 /**
1620 1799 * @since 4.07
1621 1800 * @param array|string $selected
1622 - * @param string $current
1801 + * @param string $current
1623 1802 */
1624 1803 private static function selected( $selected, $current ) {
1625 1804 if ( is_callable( 'FrmProAppHelper::selected' ) ) {
1626 1805 FrmProAppHelper::selected( $selected, $current );
@@ -1629,9 +1808,9 @@
1629 1808 }
1630 1809 }
1631 1810
1632 1811 /**
1633 - * @param string|array $capability
1812 + * @param array|string $capability
1634 1813 */
1635 1814 public static function roles_options( $capability ) {
1636 1815 global $frm_vars;
1637 1816 if ( isset( $frm_vars['editable_roles'] ) ) {
@@ -1643,9 +1822,9 @@
1643 1822
1644 1823 foreach ( $editable_roles as $role => $details ) {
1645 1824 $name = translate_user_role( $details['name'] );
1646 1825 ?>
1647 - <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_attr( $name ); ?> </option>
1826 + <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_html( $name ); ?> </option>
1648 1827 <?php
1649 1828 unset( $role, $details );
1650 1829 }
1651 1830 }
@@ -1666,9 +1845,8 @@
1666 1845 $pro_cap = array(
1667 1846 'frm_create_entries' => __( 'Add Entries from Admin Area', 'formidable' ),
1668 1847 'frm_edit_entries' => __( 'Edit Entries from Admin Area', 'formidable' ),
1669 1848 'frm_view_reports' => __( 'View Reports', 'formidable' ),
1670 - 'frm_edit_displays' => __( 'Add/Edit Views', 'formidable' ),
1671 1849 );
1672 1850 /**
1673 1851 * @since 5.3.1
1674 1852 *
@@ -1675,8 +1853,14 @@
1675 1853 * @param array<string,string> $pro_cap
1676 1854 */
1677 1855 $pro_cap = apply_filters( 'frm_pro_capabilities', $pro_cap );
1678 1856
1857 + if ( ! array_key_exists( 'frm_edit_displays', $pro_cap ) && is_callable( 'FrmProAppHelper::views_is_installed' ) && FrmProAppHelper::views_is_installed() ) {
1858 + // For backward compatibility, add the Add/Edit Views permission if Pro is not up to date.
1859 + // This was added in 6.5.4. Remove this in the future.
1860 + $pro_cap['frm_edit_displays'] = __( 'Add/Edit Views', 'formidable' );
1861 + }
1862 +
1679 1863 if ( 'pro_only' === $type ) {
1680 1864 return $pro_cap;
1681 1865 }
1682 1866
@@ -1691,9 +1875,9 @@
1691 1875 * @return array<string,string>
1692 1876 */
1693 1877 private static function get_lite_capabilities() {
1694 1878 return array(
1695 - 'frm_view_forms' => __( 'View Forms', 'formidable' ),
1879 + 'frm_view_forms' => __( 'View Forms List', 'formidable' ),
1696 1880 'frm_edit_forms' => __( 'Add and Edit Forms', 'formidable' ),
1697 1881 'frm_delete_forms' => __( 'Delete Forms', 'formidable' ),
1698 1882 'frm_change_settings' => __( 'Access this Settings Page', 'formidable' ),
1699 1883 'frm_view_entries' => __( 'View Entries from Admin Area', 'formidable' ),
@@ -1734,9 +1918,9 @@
1734 1918 return current_user_can( $role );
1735 1919 }
1736 1920
1737 1921 /**
1738 - * @param string|array $needed_role
1922 + * @param array|string $needed_role
1739 1923 * @return bool
1740 1924 */
1741 1925 public static function user_has_permission( $needed_role ) {
1742 1926 if ( is_array( $needed_role ) ) {
@@ -1792,8 +1976,11 @@
1792 1976 /**
1793 1977 * Make sure admins have permission to see the menu items
1794 1978 *
1795 1979 * @since 2.0.6
1980 + *
1981 + * @param string $cap
1982 + * @return void
1796 1983 */
1797 1984 public static function force_capability( $cap = 'frm_change_settings' ) {
1798 1985 if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
1799 1986 $role = get_role( 'administrator' );
@@ -1804,9 +1991,9 @@
1804 1991 }
1805 1992 }
1806 1993
1807 1994 /**
1808 - * Check if the user has permision for action.
1995 + * Check if the user has permission for action.
1809 1996 * Return permission message and stop the action if no permission
1810 1997 *
1811 1998 * @since 2.0
1812 1999 *
@@ -1842,9 +2029,9 @@
1842 2029 if ( empty( $nonce_name ) ) {
1843 2030 return $error;
1844 2031 }
1845 2032
1846 - $nonce_value = ( $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
2033 + $nonce_value = $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
1847 2034 if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $nonce_value, $nonce ) ) ) {
1848 2035 $frm_settings = self::get_settings();
1849 2036 $error = $frm_settings->admin_permission;
1850 2037 }
@@ -1858,12 +2045,13 @@
1858 2045 }
1859 2046 }
1860 2047
1861 2048 public static function check_selected( $values, $current ) {
1862 - $values = self::recursive_function_map( $values, 'trim' );
1863 - $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1864 - $current = htmlspecialchars_decode( trim( $current ) );
2049 + $values = self::recursive_function_map( $values, 'trim' );
2050 + $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1865 2051
2052 + $current = is_null( $current ) ? '' : htmlspecialchars_decode( trim( $current ) );
2053 +
1866 2054 return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
1867 2055 }
1868 2056
1869 2057 public static function recursive_function_map( $value, $function ) {
@@ -1883,8 +2071,9 @@
1883 2071 }
1884 2072 }
1885 2073 }
1886 2074 } else {
2075 + $value = self::maybe_update_value_if_null( $value, $function );
1887 2076 $value = call_user_func( $function, $value );
1888 2077 }
1889 2078
1890 2079 return $value;
@@ -1889,8 +2078,24 @@
1889 2078
1890 2079 return $value;
1891 2080 }
1892 2081
2082 + /**
2083 + * Updates value to empty string if it is null and being passed to a string function.
2084 + *
2085 + * @since 6.8.4
2086 + * @param mixed $value
2087 + * @param string $function
2088 + * @return mixed
2089 + */
2090 + private static function maybe_update_value_if_null( $value, $function ) {
2091 + if ( null === $value && in_array( $function, array( 'trim', 'strlen' ), true ) ) {
2092 + $value = '';
2093 + }
2094 +
2095 + return $value;
2096 + }
2097 +
1893 2098 public static function is_assoc( $array ) {
1894 2099 return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
1895 2100 }
1896 2101
@@ -1901,14 +2106,12 @@
1901 2106 $return = array();
1902 2107 foreach ( $array as $key => $value ) {
1903 2108 if ( is_array( $value ) ) {
1904 2109 $return = array_merge( $return, self::array_flatten( $value, $keys ) );
2110 + } elseif ( $keys === 'keep' ) {
2111 + $return[ $key ] = $value;
1905 2112 } else {
1906 - if ( $keys === 'keep' ) {
1907 - $return[ $key ] = $value;
1908 - } else {
1909 - $return[] = $value;
1910 - }
2113 + $return[] = $value;
1911 2114 }
1912 2115 }
1913 2116
1914 2117 return $return;
@@ -1913,8 +2116,13 @@
1913 2116
1914 2117 return $return;
1915 2118 }
1916 2119
2120 + /**
2121 + * @param string $text
2122 + * @param bool $is_rich_text
2123 + * @return string
2124 + */
1917 2125 public static function esc_textarea( $text, $is_rich_text = false ) {
1918 2126 $safe_text = str_replace( '&quot;', '"', $text );
1919 2127 if ( ! $is_rich_text ) {
1920 2128 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
@@ -1920,9 +2128,13 @@
1920 2128 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
1921 2129 }
1922 2130 $safe_text = str_replace( '&amp; ', '& ', $safe_text );
1923 2131
1924 - return apply_filters( 'esc_textarea', $safe_text, $text );
2132 + /**
2133 + * @param string $safe_text
2134 + * @param string $text
2135 + */
2136 + return (string) apply_filters( 'esc_textarea', $safe_text, $text );
1925 2137 }
1926 2138
1927 2139 /**
1928 2140 * Add auto paragraphs to text areas
@@ -1973,12 +2185,12 @@
1973 2185 * @since 5.0.13 added $echo param.
1974 2186 *
1975 2187 * @param string $url
1976 2188 * @param bool $echo
1977 - * @return string|void
2189 + * @return string|null
1978 2190 */
1979 2191 public static function js_redirect( $url, $echo = false ) {
1980 - $callback = function() use ( $url ) {
2192 + $callback = function () use ( $url ) {
1981 2193 echo '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
1982 2194 };
1983 2195 return self::clip( $callback, $echo );
1984 2196 }
@@ -2006,8 +2218,13 @@
2006 2218
2007 2219 return $user_id;
2008 2220 }
2009 2221
2222 + /**
2223 + * @param string $filename
2224 + * @param array $atts
2225 + * @return false|string
2226 + */
2010 2227 public static function get_file_contents( $filename, $atts = array() ) {
2011 2228 if ( ! is_file( $filename ) ) {
2012 2229 return false;
2013 2230 }
@@ -2013,9 +2230,9 @@
2013 2230 }
2014 2231
2015 2232 extract( $atts ); // phpcs:ignore WordPress.PHP.DontExtract
2016 2233 ob_start();
2017 - include( $filename );
2234 + include $filename;
2018 2235 $contents = ob_get_contents();
2019 2236 ob_end_clean();
2020 2237
2021 2238 return $contents;
@@ -2070,9 +2287,9 @@
2070 2287 ++$suffix;
2071 2288 } while ( in_array( $key_check, $similar_keys, true ) );
2072 2289
2073 2290 $key = $key_check;
2074 - }
2291 + }//end if
2075 2292
2076 2293 return $key;
2077 2294 }
2078 2295
@@ -2116,9 +2333,11 @@
2116 2333 * @return string
2117 2334 */
2118 2335 private static function generate_new_key( $num_chars ) {
2119 2336 $max_slug_value = pow( 36, $num_chars );
2120 - $min_slug_value = 37; // we want to have at least 2 characters in the slug
2337 +
2338 + // We want to have at least 2 characters in the slug.
2339 + $min_slug_value = 37;
2121 2340 return base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
2122 2341 }
2123 2342
2124 2343 /**
@@ -2147,11 +2366,16 @@
2147 2366
2148 2367 /**
2149 2368 * Editing a Form or Entry
2150 2369 *
2151 - * @param string $table
2370 + * @param object $record
2371 + * @param string $table
2372 + * @param array|string $fields
2373 + * @param bool $default
2374 + * @param array $post_values
2375 + * @param array $args
2152 2376 *
2153 - * @return bool|array
2377 + * @return array|bool
2154 2378 */
2155 2379 public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
2156 2380 if ( ! $record ) {
2157 2381 return false;
@@ -2204,13 +2428,12 @@
2204 2428 $post_values = $args['post_values'];
2205 2429
2206 2430 if ( $args['default'] ) {
2207 2431 $meta_value = $field->default_value;
2208 - } else {
2209 - if ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
2210 - if ( ! isset( $field->field_options['custom_field'] ) ) {
2211 - $field->field_options['custom_field'] = '';
2212 - }
2432 + } elseif ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
2433 + if ( ! isset( $field->field_options['custom_field'] ) ) {
2434 + $field->field_options['custom_field'] = '';
2435 + }
2213 2436 $meta_value = FrmProEntryMetaHelper::get_post_value(
2214 2437 $record->post_id,
2215 2438 $field->field_options['post_field'],
2216 2439 $field->field_options['custom_field'],
@@ -2220,12 +2443,11 @@
2220 2443 'form_id' => $field->form_id,
2221 2444 'field' => $field,
2222 2445 )
2223 2446 );
2224 - } else {
2225 - $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2226 - }
2227 - }
2447 + } else {
2448 + $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2449 + }//end if
2228 2450
2229 2451 $field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
2230 2452 if ( isset( $post_values['item_meta'][ $field->id ] ) ) {
2231 2453 $new_value = $post_values['item_meta'][ $field->id ];
@@ -2273,12 +2495,15 @@
2273 2495 );
2274 2496 }
2275 2497
2276 2498 /**
2499 + * @param object $record
2277 2500 * @param string $table
2501 + * @param array $post_values
2502 + * @param array $values
2278 2503 */
2279 2504 private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
2280 - if ( $table == 'entries' ) {
2505 + if ( $table === 'entries' ) {
2281 2506 $form = $record->form_id;
2282 2507 FrmForm::maybe_get_form( $form );
2283 2508 } else {
2284 2509 $form = $record;
@@ -2314,9 +2539,9 @@
2314 2539 $form_defaults = FrmFormsHelper::get_default_opts();
2315 2540
2316 2541 foreach ( $form_defaults as $opt => $default ) {
2317 2542 if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
2318 - $values[ $opt ] = ( $post_values && isset( $post_values['options'][ $opt ] ) ) ? $post_values['options'][ $opt ] : $default;
2543 + $values[ $opt ] = $post_values && isset( $post_values['options'][ $opt ] ) ? $post_values['options'][ $opt ] : $default;
2319 2544 }
2320 2545
2321 2546 unset( $opt, $default );
2322 2547 }
@@ -2337,9 +2562,9 @@
2337 2562 * @since 2.2.10
2338 2563 *
2339 2564 * @param array $post_values
2340 2565 *
2341 - * @return boolean|int
2566 + * @return bool|int
2342 2567 */
2343 2568 public static function custom_style_value( $post_values ) {
2344 2569 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2345 2570 $custom_style = absint( $post_values['options']['custom_style'] );
@@ -2344,29 +2569,37 @@
2344 2569 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2345 2570 $custom_style = absint( $post_values['options']['custom_style'] );
2346 2571 } else {
2347 2572 $frm_settings = self::get_settings();
2348 - $custom_style = ( $frm_settings->load_style != 'none' );
2573 + $custom_style = ( $frm_settings->load_style !== 'none' );
2349 2574 }
2350 2575
2351 2576 return $custom_style;
2352 2577 }
2353 2578
2354 - public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
2355 - if ( is_array( $str ) ) {
2579 + /**
2580 + * @param mixed $original_string
2581 + * @param int|string $length
2582 + * @param int $minword
2583 + * @param string $continue
2584 + * @return string
2585 + */
2586 + public static function truncate( $original_string, $length, $minword = 3, $continue = '...' ) {
2587 + if ( ! is_string( $original_string ) && ! is_int( $original_string ) ) {
2356 2588 return '';
2357 2589 }
2358 2590
2359 2591 $length = (int) $length;
2360 - $str = wp_strip_all_tags( $str );
2592 + $str = wp_strip_all_tags( (string) $original_string );
2361 2593 $original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
2362 2594
2363 2595 if ( $length == 0 ) {
2364 2596 return '';
2365 - } elseif ( $length <= 10 ) {
2597 + }
2598 +
2599 + if ( $length <= 10 ) {
2366 2600 $sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
2367 -
2368 - return $sub . ( ( $length < $original_len ) ? $continue : '' );
2601 + return $sub . ( $length < $original_len ? $continue : '' );
2369 2602 }
2370 2603
2371 2604 $sub = '';
2372 2605 $len = 0;
@@ -2372,10 +2605,14 @@
2372 2605 $len = 0;
2373 2606
2374 2607 $words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
2375 2608
2609 + if ( ! is_array( $words ) ) {
2610 + return $original_string;
2611 + }
2612 +
2376 2613 foreach ( $words as $word ) {
2377 - $part = ( ( $sub != '' ) ? ' ' : '' ) . $word;
2614 + $part = ( $sub != '' ? ' ' : '' ) . $word;
2378 2615 $total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
2379 2616 if ( $total_len > $length && substr_count( $sub, ' ' ) ) {
2380 2617 break;
2381 2618 }
@@ -2389,11 +2626,37 @@
2389 2626
2390 2627 unset( $total_len, $word );
2391 2628 }
2392 2629
2393 - return $sub . ( ( $len < $original_len ) ? $continue : '' );
2630 + $sub = self::maybe_force_truncate_on_string_with_no_spaces( $sub, $length );
2631 +
2632 + return $sub . ( $len < $original_len ? $continue : '' );
2394 2633 }
2395 2634
2635 + /**
2636 + * If the string is still too long because there may not have been any spaces, force truncate.
2637 + *
2638 + * @since 6.5.4
2639 + *
2640 + * @param string $sub Current substring.
2641 + * @param int $length The length limit.
2642 + * @return string
2643 + */
2644 + private static function maybe_force_truncate_on_string_with_no_spaces( $sub, $length ) {
2645 + if ( strlen( $sub ) < $length + 50 ) {
2646 + // If the string isn't way over the limit, leave it.
2647 + return $sub;
2648 + }
2649 +
2650 + $first_space = strpos( $sub, ' ', $length );
2651 + if ( false !== $first_space ) {
2652 + // Ignore anything with spaces.
2653 + return $sub;
2654 + }
2655 +
2656 + return substr( $sub, 0, $length + 10 );
2657 + }
2658 +
2396 2659 public static function mb_function( $function_names, $args ) {
2397 2660 $mb_function_name = $function_names[0];
2398 2661 $function_name = $function_names[1];
2399 2662 if ( function_exists( $mb_function_name ) ) {
@@ -2450,12 +2713,12 @@
2450 2713 return date_i18n( $date_format, strtotime( $date ) );
2451 2714 }
2452 2715
2453 2716 /**
2454 - * Gets the time ago in words
2717 + * Gets the time ago in words.
2455 2718 *
2456 - * @param int $from in seconds
2457 - * @param int|string $to in seconds
2719 + * @param int $from In seconds.
2720 + * @param int|string $to In seconds.
2458 2721 *
2459 2722 * @return string $time_ago
2460 2723 */
2461 2724 public static function human_time_diff( $from, $to = '', $levels = 1 ) {
@@ -2470,9 +2733,9 @@
2470 2733 $diff_object = $now->diff( $ago );
2471 2734 $diff = get_object_vars( $diff_object );
2472 2735
2473 2736 // Add week amount and update day amount
2474 - $diff['w'] = floor( $diff['d'] / 7 );
2737 + $diff['w'] = floor( $diff['d'] / 7 );
2475 2738 $diff['d'] -= $diff['w'] * 7;
2476 2739
2477 2740 $time_strings = self::get_time_strings();
2478 2741
@@ -2479,9 +2742,9 @@
2479 2742 if ( ! is_numeric( $levels ) ) {
2480 2743 // Show time in specified unit.
2481 2744 $levels = self::get_unit( $levels );
2482 2745 if ( isset( $time_strings[ $levels ] ) ) {
2483 - $diff = array(
2746 + $diff = array(
2484 2747 $levels => self::time_format( $levels, $diff ),
2485 2748 );
2486 2749 $time_strings = array(
2487 2750 $levels => $time_strings[ $levels ],
@@ -2570,9 +2833,9 @@
2570 2833 }
2571 2834
2572 2835 /**
2573 2836 * Get the translatable time strings. The untranslated version is a failsafe
2574 - * in case langauges are changing for the unit set in the shortcode.
2837 + * in case languages are changing for the unit set in the shortcode.
2575 2838 *
2576 2839 * @since 2.0.20
2577 2840 * @return array
2578 2841 */
@@ -2618,23 +2881,28 @@
2618 2881
2619 2882 // Pagination Methods.
2620 2883
2621 2884 /**
2622 - * @param integer $current_p
2885 + * @param int $r_count
2886 + * @param int $current_p
2887 + * @param int $p_size
2888 + * @return int
2623 2889 */
2624 2890 public static function get_last_record_num( $r_count, $current_p, $p_size ) {
2625 - return ( ( $r_count < ( $current_p * $p_size ) ) ? $r_count : ( $current_p * $p_size ) );
2891 + return ( $r_count < $current_p * $p_size ? $r_count : $current_p * $p_size );
2626 2892 }
2627 2893
2628 2894 /**
2629 - * @param integer $current_p
2895 + * @param int $r_count
2896 + * @param int $current_p
2897 + * @param int $p_size
2898 + * @return int
2630 2899 */
2631 2900 public static function get_first_record_num( $r_count, $current_p, $p_size ) {
2632 2901 if ( $current_p == 1 ) {
2633 2902 return 1;
2634 - } else {
2635 - return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
2636 2903 }
2904 + return self::get_last_record_num( $r_count, $current_p - 1, $p_size ) + 1;
2637 2905 }
2638 2906
2639 2907 /**
2640 2908 * @return array
@@ -2657,9 +2925,9 @@
2657 2925 if ( ! isset( $l3 ) ) {
2658 2926 $l3 = $name;
2659 2927 }
2660 2928
2661 - $this_val = ( $p == $last ) ? $jv['value'] : array();
2929 + $this_val = $p == $last ? $jv['value'] : array();
2662 2930
2663 2931 switch ( $p ) {
2664 2932 case 0:
2665 2933 $l1 = $name;
@@ -2681,12 +2949,12 @@
2681 2949 self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
2682 2950 }
2683 2951
2684 2952 unset( $this_val, $n );
2685 - }
2953 + }//end foreach
2686 2954
2687 2955 unset( $last, $jv );
2688 - }
2956 + }//end foreach
2689 2957
2690 2958 return $vars;
2691 2959 }
2692 2960
@@ -2934,8 +3202,11 @@
2934 3202 }
2935 3203
2936 3204 /**
2937 3205 * @since 4.02.03
3206 + *
3207 + * @param array|string $value
3208 + * @return string
2938 3209 */
2939 3210 public static function maybe_json_encode( $value ) {
2940 3211 if ( is_array( $value ) ) {
2941 3212 $value = wp_json_encode( $value );
@@ -2943,12 +3214,14 @@
2943 3214 return $value;
2944 3215 }
2945 3216
2946 3217 /**
3218 + * Echo The javascript to open and highlight the Formidable menu
3219 + *
2947 3220 * @since 1.07.10
2948 3221 *
2949 - * @param string $post_type The name of the post type that may need to be highlighted
2950 - * echo The javascript to open and highlight the Formidable menu
3222 + * @param string $post_type The name of the post type that may need to be highlighted.
3223 + * @return void
2951 3224 */
2952 3225 public static function maybe_highlight_menu( $post_type ) {
2953 3226 global $post;
2954 3227
@@ -2967,8 +3240,11 @@
2967 3240 /**
2968 3241 * Load the JS file on non-Formidable pages in the admin area
2969 3242 *
2970 3243 * @since 2.0
3244 + *
3245 + * @param bool $load
3246 + * @return void
2971 3247 */
2972 3248 public static function load_admin_wide_js( $load = true ) {
2973 3249 $version = self::plugin_version();
2974 3250 wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
@@ -2982,8 +3258,9 @@
2982 3258 'canAccessApplicationDashboard' => current_user_can( is_callable( 'FrmProApplicationsHelper::get_required_templates_capability' ) ? FrmProApplicationsHelper::get_required_templates_capability() : 'frm_edit_forms' ),
2983 3259 'loading' => __( 'Loading&hellip;', 'formidable' ),
2984 3260 'nonce' => wp_create_nonce( 'frm_ajax' ),
2985 3261 'proIncludesSliderJs' => is_callable( 'FrmProFormsHelper::prepare_custom_currency' ),
3262 + 'inboxSlideIn' => FrmInbox::get_inbox_slide_in_value_for_js(),
2986 3263 );
2987 3264 wp_localize_script( 'formidable_admin_global', 'frmGlobal', $global_strings );
2988 3265
2989 3266 if ( $load ) {
@@ -2992,8 +3269,9 @@
2992 3269 }
2993 3270
2994 3271 /**
2995 3272 * @since 2.0.9
3273 + * @return void
2996 3274 */
2997 3275 public static function load_font_style() {
2998 3276 wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
2999 3277 }
@@ -2999,26 +3277,29 @@
2999 3277 }
3000 3278
3001 3279 /**
3002 3280 * @param string $location
3281 + * @return void
3003 3282 */
3004 3283 public static function localize_script( $location ) {
3005 3284 global $wp_scripts;
3006 3285
3007 3286 $script_strings = array(
3008 - 'ajax_url' => esc_url_raw( self::get_ajax_url() ),
3009 - 'images_url' => self::plugin_url() . '/images',
3010 - 'loading' => __( 'Loading&hellip;', 'formidable' ),
3011 - 'remove' => __( 'Remove', 'formidable' ),
3012 - 'offset' => apply_filters( 'frm_scroll_offset', 4 ),
3013 - 'nonce' => wp_create_nonce( 'frm_ajax' ),
3014 - 'id' => __( 'ID', 'formidable' ),
3015 - 'no_results' => __( 'No results match', 'formidable' ),
3016 - 'file_spam' => __( 'That file looks like Spam.', 'formidable' ),
3017 - 'calc_error' => __( 'There is an error in the calculation in the field with key', 'formidable' ),
3018 - 'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
3019 - 'focus_first_error' => self::should_focus_first_error(),
3020 - 'include_alert_role' => self::should_include_alert_role_on_field_errors(),
3287 + 'ajax_url' => esc_url_raw( self::get_ajax_url() ),
3288 + 'images_url' => self::plugin_url() . '/images',
3289 + 'loading' => __( 'Loading&hellip;', 'formidable' ),
3290 + 'remove' => __( 'Remove', 'formidable' ),
3291 + 'offset' => apply_filters( 'frm_scroll_offset', 4 ),
3292 + 'nonce' => wp_create_nonce( 'frm_ajax' ),
3293 + 'id' => __( 'ID', 'formidable' ),
3294 + 'no_results' => __( 'No results match', 'formidable' ),
3295 + 'file_spam' => __( 'That file looks like Spam.', 'formidable' ),
3296 + 'calc_error' => __( 'There is an error in the calculation in the field with key', 'formidable' ),
3297 + 'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
3298 + 'focus_first_error' => self::should_focus_first_error(),
3299 + 'include_alert_role' => self::should_include_alert_role_on_field_errors(),
3300 + // We need to keep this setting for a few versions because Pro checks for this.
3301 + 'include_resend_email' => false,
3021 3302 );
3022 3303
3023 3304 $data = $wp_scripts->get_data( 'formidable', 'data' );
3024 3305 if ( ! $data ) {
@@ -3025,9 +3306,8 @@
3025 3306 wp_localize_script( 'formidable', 'frm_js', $script_strings );
3026 3307 }
3027 3308
3028 3309 if ( $location === 'admin' ) {
3029 - $frm_settings = self::get_settings();
3030 3310 $admin_script_strings = array(
3031 3311 'desc' => __( '(Click to add description)', 'formidable' ),
3032 3312 'blank' => __( '(Blank)', 'formidable' ),
3033 3313 'no_label' => __( '(no label)', 'formidable' ),
@@ -3041,9 +3321,9 @@
3041 3321 'confirm' => __( 'Are you sure?', 'formidable' ),
3042 3322 'conf_delete' => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
3043 3323 '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' ),
3044 3324 'conf_no_repeat' => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
3045 - 'default_unique' => $frm_settings->unique_msg,
3325 + 'default_unique' => FrmFieldsHelper::default_unique_msg(),
3046 3326 'default_conf' => __( 'The entered values do not match', 'formidable' ),
3047 3327 'enter_email' => __( 'Enter Email', 'formidable' ),
3048 3328 'confirm_email' => __( 'Confirm Email', 'formidable' ),
3049 3329 'conditional_text' => __( 'Conditional content here', 'formidable' ),
@@ -3060,9 +3340,11 @@
3060 3340 'no_licenses' => __( 'No new licenses were found', 'formidable' ),
3061 3341 'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3062 3342 'view_shortcodes' => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
3063 3343 'text_shortcodes' => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
3064 - 'only_one_action' => __( 'This form action is limited to one per form. Please edit the existing form action.', 'formidable' ),
3344 + /* translators: %d is the number of allowed actions per form */
3345 + 'only_one_action' => sprintf( __( 'This form action is limited to %d per form.', 'formidable' ), 1 ),
3346 + 'edit_action_text' => __( 'Please edit the existing form action.', 'formidable' ),
3065 3347 'unsafe_params' => FrmFormsHelper::reserved_words(),
3066 3348 /* Translators: %s is the name of a Detail Page Slug that is a reserved word.*/
3067 3349 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ),
3068 3350 /* 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. */
@@ -3071,13 +3353,22 @@
3071 3353 'repeat_limit_min' => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
3072 3354 'checkbox_limit' => __( 'Please select a limit between 0 and 200.', 'formidable' ),
3073 3355 'install' => __( 'Install', 'formidable' ),
3074 3356 'active' => __( 'Active', 'formidable' ),
3357 + 'installed' => __( 'Installed', 'formidable' ),
3358 + 'not_installed' => __( 'Not Installed', 'formidable' ),
3075 3359 'select_a_field' => __( 'Select a Field', 'formidable' ),
3076 3360 'no_items_found' => __( 'No items found.', 'formidable' ),
3077 3361 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
3078 - 'saving' => '', // Deprecated in 6.0.
3079 - 'saved' => '', // Deprecated in 6.0.
3362 +
3363 + // Deprecated in 6.0.
3364 + 'saving' => '',
3365 +
3366 + // Deprecated in 6.0.
3367 + 'saved' => '',
3368 +
3369 + // translators: %1$s: HTML open tag, %2$s: HTML end tag.
3370 + 'holdShiftMsg' => esc_html__( 'You can hold %1$sShift%2$s on your keyboard to select multiple fields', 'formidable' ),
3080 3371 );
3081 3372 /**
3082 3373 * @param array $admin_script_strings
3083 3374 */
@@ -3086,9 +3377,9 @@
3086 3377 $data = $wp_scripts->get_data( 'formidable_admin', 'data' );
3087 3378 if ( ! $data ) {
3088 3379 wp_localize_script( 'formidable_admin', 'frm_admin_js', $admin_script_strings );
3089 3380 }
3090 - }
3381 + }//end if
3091 3382 }
3092 3383
3093 3384 /**
3094 3385 * @since 6.5
@@ -3132,9 +3423,10 @@
3132 3423 * Echo the message on the plugins listing page
3133 3424 *
3134 3425 * @since 1.07.10
3135 3426 *
3136 - * @param float $min_version The version the add-on requires
3427 + * @param float $min_version The version the add-on requires.
3428 + * @return void
3137 3429 */
3138 3430 public static function min_version_notice( $min_version ) {
3139 3431 $frm_version = self::plugin_version();
3140 3432
@@ -3168,9 +3460,8 @@
3168 3460 if ( ! $is_pro || self::meets_min_pro_version( $min_version ) ) {
3169 3461 return;
3170 3462 }
3171 3463
3172 - $pro_version = FrmProDb::$plug_version;
3173 3464 $expired = FrmAddonsController::is_license_expired();
3174 3465 ?>
3175 3466 <div class="frm-banner-alert frm_error_style frm_previous_install">
3176 3467 <?php
@@ -3188,8 +3479,11 @@
3188 3479 /**
3189 3480 * If Pro is installed, check the version number.
3190 3481 *
3191 3482 * @since 4.0.01
3483 + *
3484 + * @param string $min_version
3485 + * @return bool
3192 3486 */
3193 3487 public static function meets_min_pro_version( $min_version ) {
3194 3488 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
3195 3489 }
@@ -3194,24 +3488,19 @@
3194 3488 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
3195 3489 }
3196 3490
3197 3491 /**
3198 - * Show a message if the browser or PHP version is below the recommendations.
3492 + * Show a message if the PHP version is below the recommendations.
3199 3493 *
3200 3494 * @since 4.0.02
3495 + * @return void
3201 3496 */
3202 3497 private static function php_version_notice() {
3203 3498 $message = array();
3204 - if ( version_compare( phpversion(), '5.6', '<' ) ) {
3499 + if ( version_compare( phpversion(), '7.0', '<' ) ) {
3205 3500 $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' );
3206 3501 }
3207 3502
3208 - $browser = self::get_server_value( 'HTTP_USER_AGENT' );
3209 - $is_ie = strpos( $browser, 'MSIE' ) !== false;
3210 - if ( $is_ie ) {
3211 - $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' );
3212 - }
3213 -
3214 3503 foreach ( $message as $m ) {
3215 3504 ?>
3216 3505 <div class="frm-banner-alert frm_error_style frm_previous_install">
3217 3506 <?php echo esc_html( $m ); ?>
@@ -3341,16 +3630,10 @@
3341 3630 return $locales;
3342 3631 }
3343 3632
3344 3633 /**
3345 - * Output HTML containing reference text for accessibility
3346 - *
3347 - * @deprecated 5.1
3634 + * @return string
3348 3635 */
3349 - public static function multiselect_accessibility() {
3350 - _deprecated_function( __METHOD__, '5.1' );
3351 - }
3352 -
3353 3636 public static function get_menu_icon_class() {
3354 3637 if ( is_callable( 'FrmProAppHelper::get_settings' ) ) {
3355 3638 $settings = FrmProAppHelper::get_settings();
3356 3639 if ( is_object( $settings ) && ! empty( $settings->menu_icon ) ) {
@@ -3460,8 +3743,18 @@
3460 3743 return apply_filters( 'frm_images_dropdown_input_attrs', $input_attrs_str, $args );
3461 3744 }
3462 3745
3463 3746 /**
3747 + * @since 6.7.1
3748 + */
3749 + public static function get_images_dropdown_atts( $option, $args ) {
3750 + $image = self::get_images_dropdown_option_image( $option, $args );
3751 + $classes = self::get_images_dropdown_option_classes( $option, $args );
3752 + $custom_attrs = self::get_images_dropdown_option_html_attrs( $option, $args );
3753 + return compact( 'image', 'classes', 'custom_attrs' );
3754 + }
3755 +
3756 + /**
3464 3757 * Gets the image of each option in images_dropdown() method.
3465 3758 *
3466 3759 * @since 5.0.04
3467 3760 *
@@ -3472,9 +3765,9 @@
3472 3765 private static function get_images_dropdown_option_image( $option, $args ) {
3473 3766 $image = self::icon_by_class(
3474 3767 'frmfont ' . $option['svg'],
3475 3768 array(
3476 - 'echo' => false,
3769 + 'echo' => false,
3477 3770 )
3478 3771 );
3479 3772
3480 3773 $args['option'] = $option;
@@ -3612,15 +3905,15 @@
3612 3905 return $values;
3613 3906 }
3614 3907
3615 3908 /**
3616 - * Some back end fields allow privleged users to add scripts.
3909 + * Some back end fields allow privileged users to add scripts.
3617 3910 * A site that uses the DISALLOW_UNFILTERED_HTML always remove scripts on echo.
3618 3911 *
3619 3912 * @since 5.0.13
3620 3913 *
3621 3914 * @param string $value
3622 - * @param array|string $allowed 'all' for everything included as defaults
3915 + * @param array|string $allowed 'all' for everything included as defaults.
3623 3916 * @return string
3624 3917 */
3625 3918 public static function maybe_kses( $value, $allowed = 'all' ) {
3626 3919 if ( self::should_never_allow_unfiltered_html() ) {
@@ -3629,8 +3922,64 @@
3629 3922 return $value;
3630 3923 }
3631 3924
3632 3925 /**
3926 + * Check if an option attribute used in an [input] shortcode is safe.
3927 + *
3928 + * @since 6.11.2
3929 + *
3930 + * @param string $key
3931 + * @param string $context Either 'display' or 'update'. On update, we want to allow a few keys that are never displayed.
3932 + * @return bool
3933 + */
3934 + public static function input_key_is_safe( $key, $context = 'display' ) {
3935 + if ( 'update' === $context && in_array( $key, array( 'opt', 'label' ), true ) ) {
3936 + $safe = true;
3937 + } elseif ( 0 === strpos( $key, 'data-' ) ) {
3938 + // Allow all data attributes.
3939 + $safe = true;
3940 + } elseif ( 0 === strpos( $key, 'aria-' ) ) {
3941 + // Allow all aria attributes.
3942 + $safe = true;
3943 + } else {
3944 + $safe_keys = array(
3945 + 'class',
3946 + 'required',
3947 + 'title',
3948 + 'placeholder',
3949 + 'value',
3950 + 'readonly',
3951 + 'disabled',
3952 + 'size',
3953 + 'maxlength',
3954 + 'min',
3955 + 'max',
3956 + 'pattern',
3957 + 'step',
3958 + 'autofocus',
3959 + 'width',
3960 + 'height',
3961 + 'autocomplete',
3962 + 'tabindex',
3963 + 'role',
3964 + 'style',
3965 + );
3966 + $safe = in_array( $key, $safe_keys, true );
3967 + }//end if
3968 +
3969 + /**
3970 + * Filter the $safe value so additional keys can be allowed or disallowed.
3971 + *
3972 + * @since 6.11.2
3973 + *
3974 + * @param bool $safe True if the key is considered safe.
3975 + * @param string $key
3976 + * @param string $context Either 'display' or 'update'.
3977 + */
3978 + return (bool) apply_filters( 'frm_input_key_is_safe', $safe, $key, $context );
3979 + }
3980 +
3981 + /**
3633 3982 * @since 5.0.16
3634 3983 *
3635 3984 * @return bool
3636 3985 */
@@ -3655,20 +4004,9 @@
3655 4004
3656 4005 /**
3657 4006 * @since 5.0.17
3658 4007 *
3659 - * @param string $plugin
3660 - * @return string|false
3661 - */
3662 - private static function get_plan_required( $plugin ) {
3663 - $link = FrmAddonsController::install_link( $plugin );
3664 - return FrmFormsHelper::get_plan_required( $link );
3665 - }
3666 -
3667 - /**
3668 - * @since 5.0.17
3669 - *
3670 - * @param string
4008 + * @param string $feature
3671 4009 * @return bool
3672 4010 */
3673 4011 public static function show_new_feature( $feature ) {
3674 4012 $link = FrmAddonsController::install_link( $feature );
@@ -3741,9 +4079,9 @@
3741 4079 public static function show_pill_text( $text = null ) {
3742 4080 if ( null === $text ) {
3743 4081 $text = __( 'NEW', 'formidable' );
3744 4082 }
3745 - echo '<span class="frm-new-pill">' . esc_html( $text ) . '</span>';
4083 + echo '<span class="frm-meta-tag frm-new-pill">' . esc_html( $text ) . '</span>';
3746 4084 }
3747 4085
3748 4086 /**
3749 4087 * Count the number of decimals digits.
@@ -3750,9 +4088,9 @@
3750 4088 *
3751 4089 * @since 5.2.07
3752 4090 *
3753 4091 * @param mixed $num Number.
3754 - * @return int|false Returns `false` if the passed parameter is not number.
4092 + * @return false|int Returns `false` if the passed parameter is not number.
3755 4093 */
3756 4094 public static function count_decimals( $num ) {
3757 4095 if ( ! is_numeric( $num ) ) {
3758 4096 return false;
@@ -3783,9 +4121,9 @@
3783 4121 }
3784 4122
3785 4123 add_filter(
3786 4124 'option_gmt_offset',
3787 - function( $offset ) {
4125 + function ( $offset ) {
3788 4126 if ( ! is_string( $offset ) || is_numeric( $offset ) ) {
3789 4127 // Leave a valid value alone.
3790 4128 return $offset;
3791 4129 }
@@ -3867,65 +4205,8 @@
3867 4205 return true;
3868 4206 }
3869 4207
3870 4208 /**
3871 - * @since 4.08
3872 - * @deprecated 4.09.01
3873 - */
3874 - public static function expiring_message() {
3875 - _deprecated_function( __METHOD__, '4.09.01', 'FrmProAddonsController::expiring_message' );
3876 - if ( is_callable( 'FrmProAddonsController::expiring_message' ) ) {
3877 - FrmProAddonsController::expiring_message();
3878 - }
3879 - }
3880 -
3881 - /**
3882 - * Use the WP 4.7 wp_doing_ajax function
3883 - *
3884 - * @since 2.05.07
3885 - * @deprecated 4.04.04
3886 - */
3887 - public static function wp_doing_ajax() {
3888 - _deprecated_function( __METHOD__, '4.04.04', 'wp_doing_ajax' );
3889 - return wp_doing_ajax();
3890 - }
3891 -
3892 - /**
3893 - * @deprecated 4.0
3894 - */
3895 - public static function insert_opt_html( $args ) {
3896 - _deprecated_function( __METHOD__, '4.0', 'FrmFormsHelper::insert_opt_html' );
3897 - FrmFormsHelper::insert_opt_html( $args );
3898 - }
3899 -
3900 - /**
3901 - * @deprecated 3.01
3902 - * @codeCoverageIgnore
3903 - */
3904 - public static function sanitize_array( &$values ) {
3905 - FrmDeprecated::sanitize_array( $values );
3906 - }
3907 -
3908 - /**
3909 - * @since 2.0
3910 - * @deprecated 5.0.13
3911 - *
3912 - * @return string The base Google APIS url for the current version of jQuery UI
3913 - */
3914 - public static function jquery_ui_base_url() {
3915 - _deprecated_function( __FUNCTION__, '5.0.13', 'FrmProAppHelper::jquery_ui_base_url' );
3916 - return is_callable( 'FrmProAppHelper::jquery_ui_base_url' ) ? FrmProAppHelper::jquery_ui_base_url() : '';
3917 - }
3918 -
3919 - /**
3920 - * @since 4.07
3921 - * @deprecated 6.0
3922 - */
3923 - public static function renewal_message() {
3924 - _deprecated_function( __METHOD__, '6.0', 'FrmProAddonsController::renewal_message' );
3925 - }
3926 -
3927 - /**
3928 4209 * Display a dismissable warning message and save its dismissal state.
3929 4210 *
3930 4211 * @since 6.3
3931 4212 *
@@ -3937,9 +4218,9 @@
3937 4218 if ( ! $message || ! $option ) {
3938 4219 return;
3939 4220 }
3940 4221
3941 - $ajax_callback = function() use ( $option ) {
4222 + $ajax_callback = function () use ( $option ) {
3942 4223 self::dismiss_warning_message( $option );
3943 4224 };
3944 4225
3945 4226 // We're handling JS codes with `doJsonPost` and it adds 'frm_' to the beginning of the action.
@@ -3947,9 +4228,9 @@
3947 4228 add_action( 'wp_ajax_frm_' . $option, $ajax_callback );
3948 4229
3949 4230 add_filter(
3950 4231 'frm_message_list',
3951 - function( $show_messages ) use ( $message, $option ) {
4232 + function ( $show_messages ) use ( $message, $option ) {
3952 4233 if ( get_option( $option, false ) ) {
3953 4234 return $show_messages;
3954 4235 }
3955 4236
@@ -3956,9 +4237,9 @@
3956 4237 $dismiss_icon = self::icon_by_class(
3957 4238 'frmfont frm_close_icon',
3958 4239 array(
3959 4240 'aria-label' => _x( 'Dismiss', 'warning message: close icon label', 'formidable' ),
3960 - 'echo' => false,
4241 + 'echo' => false,
3961 4242 )
3962 4243 );
3963 4244
3964 4245 $show_messages[] = $message;
@@ -3985,6 +4266,100 @@
3985 4266 update_option( $option, true, 'no' );
3986 4267 }
3987 4268
3988 4269 wp_send_json_success();
4270 + }
4271 +
4272 + /**
4273 + * Lite license copy.
4274 + * Used in FrmDashboardController & FrmSettingsController
4275 + *
4276 + * @since 6.8
4277 + *
4278 + * @return string
4279 + */
4280 + public static function copy_for_lite_license() {
4281 + $message = __( 'You\'re using Formidable Forms Lite - no license needed. Enjoy!', 'formidable' ) . ' 🙂';
4282 +
4283 + if ( is_callable( 'FrmProAddonsController::get_readable_license_type' ) && ! class_exists( 'FrmProDashboardController' ) ) {
4284 + // Manage PRO versions without PRO dashboard functionality.
4285 + $license_type = FrmProAddonsController::get_readable_license_type();
4286 + if ( 'lite' !== strtolower( $license_type ) ) {
4287 + $message = 'Formidable Pro ' . $license_type;
4288 + }
4289 + }
4290 +
4291 + return apply_filters( 'frm_license_type_text', $message );
4292 + }
4293 +
4294 + /**
4295 + * Removes scripts that are unnecessarily loaded across the pages!
4296 + *
4297 + * @since 6.9
4298 + * @return void
4299 + */
4300 + public static function dequeue_extra_global_scripts() {
4301 + wp_dequeue_script( 'frm-surveys-admin' );
4302 + wp_dequeue_script( 'frm-quizzes-form-action' );
4303 + }
4304 +
4305 + /**
4306 + * Shows tooltip icon.
4307 + *
4308 + * @since 6.12
4309 + *
4310 + * @param string $tooltip_text Tooltip text.
4311 + * @param array $atts Tooltip wrapper HTML attributes.
4312 + *
4313 + * @return void
4314 + */
4315 + public static function tooltip_icon( $tooltip_text, $atts = array() ) {
4316 + $atts['title'] = $tooltip_text;
4317 + if ( isset( $atts['class'] ) ) {
4318 + $atts['class'] .= ' frm_help';
4319 + } else {
4320 + $atts['class'] = 'frm_help';
4321 + }
4322 + ?>
4323 + <span <?php self::array_to_html_params( $atts, true ); ?>>
4324 + <?php self::icon_by_class( 'frmfont frm_tooltip_icon' ); ?>
4325 + </span>
4326 + <?php
4327 + }
4328 +
4329 + /**
4330 + * Prints errors for settings in onboarding wizard or template settings.
4331 + *
4332 + * @since 6.15
4333 + *
4334 + * @param array $args Args.
4335 + *
4336 + * @return void
4337 + */
4338 + public static function print_setting_error( $args ) {
4339 + $args = wp_parse_args(
4340 + $args,
4341 + array(
4342 + 'id' => '',
4343 + 'errors' => array(),
4344 + 'class' => '',
4345 + )
4346 + );
4347 +
4348 + $args['class'] .= ' frm-validation-error frm-mt-xs frm_hidden';
4349 + ?>
4350 + <span id="<?php echo esc_attr( $args['id'] ); ?>" class="<?php echo esc_attr( $args['class'] ); ?>">
4351 + <?php
4352 + if ( is_array( $args['errors'] ) ) {
4353 + foreach ( $args['errors'] as $key => $msg ) {
4354 + ?>
4355 + <span frm-error="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $msg ); ?></span>
4356 + <?php
4357 + }
4358 + } else {
4359 + echo '<span>' . esc_html( $args['errors'] ) . '</span>';
4360 + }
4361 + ?>
4362 + </span>
4363 + <?php
3989 4364 }
3990 4365 }