PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.14.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.14.1
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/helpers/FrmAppHelper.php +625 -286 6.5.2 → 6.14.1 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.2';
36 + public static $plug_version = '6.14.1';
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,8 +184,11 @@
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 194 return FrmAddonsController::is_license_expired() ? 'Formidable' : $frm_settings->menu;
@@ -153,24 +195,28 @@
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
@@ -428,9 +507,10 @@
428 507 }
429 508
430 509 $key = self::get_server_value( $key );
431 510 foreach ( explode( ',', $key ) as $ip ) {
432 - $ip = trim( $ip ); // Just to be safe.
511 + // Just to be safe.
512 + $ip = trim( $ip );
433 513
434 514 if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
435 515 return sanitize_text_field( $ip );
436 516 }
@@ -521,15 +601,24 @@
521 601
522 602 return $value;
523 603 }
524 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 + */
525 614 public static function get_post_param( $param, $default = '', $sanitize = '', $serialized = false ) {
526 615 return self::get_simple_request(
527 616 array(
528 - 'type' => 'post',
529 - 'param' => $param,
530 - 'default' => $default,
531 - 'sanitize' => $sanitize,
617 + 'type' => 'post',
618 + 'param' => $param,
619 + 'default' => $default,
620 + 'sanitize' => $sanitize,
532 621 'serialized' => $serialized,
533 622 )
534 623 );
535 624 }
@@ -540,9 +629,9 @@
540 629 * @param string $param
541 630 * @param string $sanitize
542 631 * @param string $default
543 632 *
544 - * @return string|array
633 + * @return array|string
545 634 */
546 635 public static function simple_get( $param, $sanitize = 'sanitize_text_field', $default = '' ) {
547 636 return self::get_simple_request(
548 637 array(
@@ -560,16 +649,16 @@
560 649 * @since 2.0.6
561 650 *
562 651 * @param array $args
563 652 *
564 - * @return string|array
653 + * @return array|string
565 654 */
566 655 public static function get_simple_request( $args ) {
567 656 $defaults = array(
568 - 'param' => '',
569 - 'default' => '',
570 - 'type' => 'get',
571 - 'sanitize' => 'sanitize_text_field',
657 + 'param' => '',
658 + 'default' => '',
659 + 'type' => 'get',
660 + 'sanitize' => 'sanitize_text_field',
572 661 'serialized' => false,
573 662 );
574 663 $args = wp_parse_args( $args, $defaults );
575 664
@@ -586,13 +675,12 @@
586 675 if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
587 676 self::unserialize_or_decode( $value );
588 677 }
589 678 }
590 - } else {
591 - if ( isset( $_REQUEST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
679 + } elseif ( isset( $_REQUEST[ $args['param'] ] ) ) {
680 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
592 681 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
593 682 $value = wp_unslash( $_REQUEST[ $args['param'] ] );
594 - }
595 683 }
596 684
597 685 self::sanitize_value( $args['sanitize'], $value );
598 686
@@ -616,19 +704,35 @@
616 704
617 705 return $value;
618 706 }
619 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 + */
620 716 public static function sanitize_value( $sanitize, &$value ) {
621 - if ( ! empty( $sanitize ) ) {
622 - if ( is_array( $value ) ) {
623 - $temp_values = $value;
624 - foreach ( $temp_values as $k => $v ) {
625 - self::sanitize_value( $sanitize, $value[ $k ] );
626 - }
627 - } else {
628 - $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 ] );
629 730 }
731 + return;
630 732 }
733 +
734 + $value = call_user_func( $sanitize, $value );
631 735 }
632 736
633 737 public static function sanitize_request( $sanitize_method, &$values ) {
634 738 $temp_values = $values;
@@ -640,15 +744,52 @@
640 744 }
641 745
642 746 /**
643 747 * @since 4.0.04
748 + *
749 + * @param mixed $value
750 + * @return void
644 751 */
645 752 public static function sanitize_with_html( &$value ) {
646 - 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 + }
647 759 self::decode_specialchars( $value );
648 760 }
649 761
650 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 + /**
651 792 * Do wp_specialchars_decode to get back '&' that wp_kses_post might have turned to '&'
652 793 * this MUST be done, else we'll be back to the '& entity' problem.
653 794 *
654 795 * @since 4.0.04
@@ -682,10 +823,12 @@
682 823 $translation = array(
683 824 '"' => '"',
684 825 '"' => '"',
685 826 '"' => '"',
686 - '&lt; ' => '< ', // The space preserves the HTML.
687 - '&#060; ' => '< ', // The space preserves the HTML.
827 + // The space preserves the HTML.
828 + '&lt; ' => '< ',
829 + // The space preserves the HTML.
830 + '&#060; ' => '< ',
688 831 '&gt;' => '>',
689 832 '&#062;' => '>',
690 833 '&amp;' => '&',
691 834 '&#038;' => '&',
@@ -712,10 +855,10 @@
712 855 * Sanitize the value, and allow some HTML
713 856 *
714 857 * @since 2.0
715 858 *
716 - * @param string $value
717 - * @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.
718 861 *
719 862 * @return string
720 863 */
721 864 public static function kses( $value, $allowed = array() ) {
@@ -816,9 +959,9 @@
816 959 'id' => true,
817 960 );
818 961
819 962 return array(
820 - 'a' => array(
963 + 'a' => array(
821 964 'class' => true,
822 965 'href' => true,
823 966 'id' => true,
824 967 'rel' => true,
@@ -887,16 +1030,16 @@
887 1030 'cite' => true,
888 1031 'title' => true,
889 1032 ),
890 1033 'rect' => array(
891 - 'class' => true,
892 - 'fill' => true,
893 - 'height' => true,
894 - 'width' => true,
895 - 'x' => true,
896 - 'y' => true,
897 - 'rx' => true,
898 - '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,
899 1042 'stroke-opacity' => true,
900 1043 'stroke-width' => true,
901 1044 ),
902 1045 'section' => $allow_class,
@@ -931,9 +1074,9 @@
931 1074 'xlink:href' => true,
932 1075 ),
933 1076 'ul' => $allow_class,
934 1077 'label' => array(
935 - 'for' => true,
1078 + 'for' => true,
936 1079 'class' => true,
937 1080 'id' => true,
938 1081 ),
939 1082 'button' => array(
@@ -951,9 +1094,9 @@
951 1094 *
952 1095 * @since 2.0
953 1096 */
954 1097 public static function remove_get_action() {
955 - if ( ! isset( $_GET ) ) {
1098 + if ( empty( $_GET ) ) {
956 1099 return;
957 1100 }
958 1101
959 1102 $action_name = isset( $_GET['action'] ) ? 'action' : ( isset( $_GET['action2'] ) ? 'action2' : '' );
@@ -970,9 +1113,9 @@
970 1113 /**
971 1114 * Check the WP query for a parameter
972 1115 *
973 1116 * @since 2.0
974 - * @return string|array
1117 + * @return array|string
975 1118 */
976 1119 public static function get_query_var( $value, $param ) {
977 1120 if ( $value != '' ) {
978 1121 return $value;
@@ -989,10 +1132,12 @@
989 1132 /**
990 1133 * Try to show the SVG if possible. Otherwise, use the font icon.
991 1134 *
992 1135 * @since 4.0.02
1136 + *
993 1137 * @param string $class
994 1138 * @param array $atts
1139 + * @return string|null
995 1140 */
996 1141 public static function icon_by_class( $class, $atts = array() ) {
997 1142 $echo = ! isset( $atts['echo'] ) || $atts['echo'];
998 1143 if ( isset( $atts['echo'] ) ) {
@@ -1002,14 +1147,16 @@
1002 1147 $html_atts = self::array_to_html_params( $atts );
1003 1148
1004 1149 $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
1005 1150
1006 - // Replace icons that have been removed.
1151 + // Replace icons that have been removed or renamed.
1007 1152 $deprecated = array(
1008 - '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',
1009 1156 );
1010 1157 if ( isset( $deprecated[ $icon ] ) ) {
1011 - $icon = $deprecated[ $icon ];
1158 + $icon = $deprecated[ $icon ];
1012 1159 $class = str_replace( $icon, $deprecated[ $icon ], $class );
1013 1160 }
1014 1161
1015 1162 if ( $icon === $class ) {
@@ -1019,11 +1166,9 @@
1019 1166 if ( strpos( $icon, ' ' ) ) {
1020 1167 $icon = explode( ' ', $icon );
1021 1168 $icon = reset( $icon );
1022 1169 }
1023 - $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '>
1024 - <use xlink:href="#' . esc_attr( $icon ) . '" />
1025 - </svg>';
1170 + $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use xlink:href="#' . esc_attr( $icon ) . '" /></svg>';
1026 1171 }
1027 1172
1028 1173 if ( $echo ) {
1029 1174 echo self::kses_icon( $icon ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -1109,11 +1254,18 @@
1109 1254 /**
1110 1255 * Include svg images.
1111 1256 *
1112 1257 * @since 4.0.02
1258 + * @return void
1113 1259 */
1114 1260 public static function include_svg() {
1115 - 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;
1116 1268 }
1117 1269
1118 1270 /**
1119 1271 * Convert an associative array to HTML values.
@@ -1125,9 +1277,9 @@
1125 1277 * @param bool $echo
1126 1278 * @return string|void
1127 1279 */
1128 1280 public static function array_to_html_params( $atts, $echo = false ) {
1129 - $callback = function() use ( $atts ) {
1281 + $callback = function () use ( $atts ) {
1130 1282 if ( $atts ) {
1131 1283 foreach ( $atts as $key => $value ) {
1132 1284 echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
1133 1285 }
@@ -1142,9 +1294,9 @@
1142 1294 * @since 5.0.13
1143 1295 *
1144 1296 * @param Closure $echo_function
1145 1297 * @param bool $echo
1146 - * @return string|void
1298 + * @return string|null
1147 1299 */
1148 1300 public static function clip( $echo_function, $echo = false ) {
1149 1301 if ( ! $echo ) {
1150 1302 ob_start();
@@ -1162,12 +1314,15 @@
1162 1314 }
1163 1315
1164 1316 /**
1165 1317 * @since 3.0
1318 + *
1319 + * @param array $atts
1320 + * @return void
1166 1321 */
1167 1322 public static function get_admin_header( $atts ) {
1168 - $has_nav = ( isset( $atts['form'] ) && ! empty( $atts['form'] ) && ( ! isset( $atts['is_template'] ) || ! $atts['is_template'] ) );
1169 - if ( ! isset( $atts['close'] ) || empty( $atts['close'] ) ) {
1323 + $has_nav = ! empty( $atts['form'] ) && empty( $atts['is_template'] );
1324 + if ( empty( $atts['close'] ) ) {
1170 1325 $atts['close'] = admin_url( 'admin.php?page=formidable' );
1171 1326 }
1172 1327 if ( ! isset( $atts['import_link'] ) ) {
1173 1328 $atts['import_link'] = false;
@@ -1172,9 +1327,9 @@
1172 1327 if ( ! isset( $atts['import_link'] ) ) {
1173 1328 $atts['import_link'] = false;
1174 1329 }
1175 1330
1176 - include( self::plugin_path() . '/classes/views/shared/admin-header.php' );
1331 + include self::plugin_path() . '/classes/views/shared/admin-header.php';
1177 1332 }
1178 1333
1179 1334 /**
1180 1335 * @since 6.0
@@ -1210,10 +1365,16 @@
1210 1365 return;
1211 1366 }
1212 1367 ?>
1213 1368 <div class="frm-upgrade-bar">
1214 - <span>You're using Formidable Forms Lite. To unlock more features consider</span>
1215 - <a href="<?php echo esc_url( self::admin_upgrade_link( 'top-bar' ) ); ?>" target="_blank" rel="noopener">upgrading to Pro</a>.
1369 + <?php
1370 + printf(
1371 + /* translators: %1$s: Start link HTML, %2$s: End link HTML */
1372 + esc_html__( 'You\'re using Formidable Forms Lite. To unlock more features consider %1$supgrading to PRO%2$s.', 'formidable' ),
1373 + '<a href="' . esc_url( self::admin_upgrade_link( 'settings-license' ) ) . '">',
1374 + '</a>'
1375 + );
1376 + ?>
1216 1377 </div>
1217 1378 <?php
1218 1379 }
1219 1380
@@ -1230,8 +1391,10 @@
1230 1391 * Render a button for a new item (Form, Application, etc).
1231 1392 *
1232 1393 * @since 3.0
1233 1394 * @param array $atts {
1395 + * Details about the button.
1396 + *
1234 1397 * @type array $link_hook Custom link hook, calls do_action and exits early.
1235 1398 * @type string $new_link Href value, default #.
1236 1399 * @type string $class Custom class names, space separated.
1237 1400 * @type string $button_text Button text. Default "Add New".
@@ -1243,9 +1406,9 @@
1243 1406 do_action( $atts['link_hook']['hook'], $atts['link_hook']['param'] );
1244 1407 return;
1245 1408 }
1246 1409
1247 - if ( empty( $atts['new_link'] ) && empty( $atts['trigger_new_form_modal'] ) && empty( $atts['class'] ) ) {
1410 + if ( empty( $atts['new_link'] ) && empty( $atts['create_form'] ) && empty( $atts['class'] ) ) {
1248 1411 // Do not render a button if none of these attributes are set.
1249 1412 return;
1250 1413 }
1251 1414
@@ -1251,12 +1414,8 @@
1251 1414
1252 1415 $href = ! empty( $atts['new_link'] ) ? esc_url( $atts['new_link'] ) : '#';
1253 1416 $class = 'button button-primary frm-button-primary';
1254 1417
1255 - if ( ! empty( $atts['trigger_new_form_modal'] ) ) {
1256 - $class .= ' frm-trigger-new-form-modal';
1257 - }
1258 -
1259 1418 if ( ! empty( $atts['class'] ) ) {
1260 1419 $class .= ' ' . $atts['class'];
1261 1420 }
1262 1421
@@ -1273,10 +1432,11 @@
1273 1432 'placeholder' => '',
1274 1433 'tosearch' => '',
1275 1434 'text' => __( 'Search', 'formidable' ),
1276 1435 'input_id' => '',
1436 + 'value' => false,
1277 1437 );
1278 - $atts = array_merge( $defaults, $atts );
1438 + $atts = array_merge( $defaults, $atts );
1279 1439
1280 1440 if ( $atts['input_id'] === 'template' && empty( $atts['tosearch'] ) ) {
1281 1441 $atts['tosearch'] = 'frm-card';
1282 1442 }
@@ -1287,8 +1447,27 @@
1287 1447 }
1288 1448
1289 1449 $input_id = $atts['input_id'] . '-search-input';
1290 1450
1451 + $input_atts = array(
1452 + 'type' => 'search',
1453 + 'id' => $input_id,
1454 + 'name' => 's',
1455 + 'placeholder' => $atts['placeholder'],
1456 + 'class' => $class,
1457 + 'data-tosearch' => $atts['tosearch'],
1458 + );
1459 +
1460 + if ( is_string( $atts['value'] ) ) {
1461 + $input_atts['value'] = $atts['value'];
1462 + } elseif ( isset( $_REQUEST['s'] ) ) {
1463 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1464 + $input_atts['value'] = wp_unslash( $_REQUEST['s'] );
1465 + }
1466 +
1467 + if ( ! empty( $atts['tosearch'] ) ) {
1468 + $input_atts['autocomplete'] = 'off';
1469 + }
1291 1470 ?>
1292 1471 <p class="frm-search">
1293 1472 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1294 1473 <?php echo esc_html( $atts['text'] ); ?>:
@@ -1293,15 +1472,9 @@
1293 1472 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1294 1473 <?php echo esc_html( $atts['text'] ); ?>:
1295 1474 </label>
1296 1475 <span class="frmfont frm_search_icon"></span>
1297 - <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s"
1298 - value="<?php _admin_search_query(); ?>" placeholder="<?php echo esc_attr( $atts['placeholder'] ); ?>"
1299 - class="<?php echo esc_attr( $class ); ?>" data-tosearch="<?php echo esc_attr( $atts['tosearch'] ); ?>"
1300 - <?php if ( ! empty( $atts['tosearch'] ) ) { ?>
1301 - autocomplete="off"
1302 - <?php } ?>
1303 - />
1476 + <input <?php self::array_to_html_params( $input_atts, true ); ?> />
1304 1477 <?php
1305 1478 if ( empty( $atts['tosearch'] ) ) {
1306 1479 submit_button( $atts['text'], 'button-secondary', '', false, array( 'id' => 'search-submit' ) );
1307 1480 }
@@ -1311,8 +1484,9 @@
1311 1484 }
1312 1485
1313 1486 /**
1314 1487 * @param string $type
1488 + * @return void
1315 1489 */
1316 1490 public static function trigger_hook_load( $type, $object = null ) {
1317 1491 // Only load the form hooks once.
1318 1492 $hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
@@ -1356,9 +1530,9 @@
1356 1530 'new_file_path' => self::plugin_path() . '/js',
1357 1531 )
1358 1532 );
1359 1533 $new_file = new FrmCreateFile( $file_atts );
1360 - $files = array(
1534 + $files = array(
1361 1535 FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.min.js',
1362 1536 );
1363 1537
1364 1538 /**
@@ -1375,14 +1549,14 @@
1375 1549 * True when value is 1, true, 'true', 'yes'
1376 1550 *
1377 1551 * @since 1.07.10
1378 1552 *
1379 - * @param string $value The value to compare
1553 + * @param string $value The value to compare.
1380 1554 *
1381 - * @return boolean True or False
1555 + * @return bool
1382 1556 */
1383 1557 public static function is_true( $value ) {
1384 - return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
1558 + return true === $value || 1 == $value || 'true' === $value || 'yes' === $value;
1385 1559 }
1386 1560
1387 1561 /**
1388 1562 * Gets all post from a specific post type.
@@ -1448,9 +1622,9 @@
1448 1622
1449 1623 wp_enqueue_script( 'jquery-ui-autocomplete' );
1450 1624
1451 1625 $selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
1452 - $title = '';
1626 + $title = '';
1453 1627
1454 1628 if ( $selected ) {
1455 1629 $title = get_the_title( $selected );
1456 1630 }
@@ -1466,11 +1640,11 @@
1466 1640 <?php
1467 1641 }
1468 1642
1469 1643 /**
1470 - * @param array $args
1471 - * @param string $page_id Deprecated.
1472 - * @param boolean $truncate Deprecated.
1644 + * @param array $args
1645 + * @param string $page_id Deprecated.
1646 + * @param bool $truncate Deprecated.
1473 1647 */
1474 1648 public static function wp_pages_dropdown( $args = array(), $page_id = '', $truncate = false ) {
1475 1649 self::prep_page_dropdown_params( $page_id, $truncate, $args );
1476 1650
@@ -1514,13 +1688,13 @@
1514 1688 * @since 4.10.01 Added `post_type` and `autocomplete_placeholder` to the arguments array.
1515 1689 */
1516 1690 private static function preformat_selection_args( $args ) {
1517 1691 $defaults = array(
1518 - 'truncate' => false,
1519 - 'placeholder' => ' ',
1520 - 'field_name' => '',
1521 - 'page_id' => '',
1522 - 'post_type' => 'page',
1692 + 'truncate' => false,
1693 + 'placeholder' => ' ',
1694 + 'field_name' => '',
1695 + 'page_id' => '',
1696 + 'post_type' => 'page',
1523 1697 'autocomplete_placeholder' => __( 'Select a Page', 'formidable' ),
1524 1698 );
1525 1699
1526 1700 return array_merge( $defaults, $args );
@@ -1600,16 +1774,16 @@
1600 1774 return $link;
1601 1775 }
1602 1776
1603 1777 /**
1604 - * @param string $field_name
1605 - * @param string|array $capability
1606 - * @param string $multiple 'single' and 'multiple'
1778 + * @param string $field_name
1779 + * @param array|string $capability
1780 + * @param string $multiple 'single' and 'multiple'.
1607 1781 */
1608 1782 public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
1609 1783 ?>
1610 1784 <select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>"
1611 - <?php echo ( 'multiple' === $multiple ) ? 'multiple="multiple"' : ''; ?>
1785 + <?php echo 'multiple' === $multiple ? 'multiple="multiple"' : ''; ?>
1612 1786 class="frm_multiselect">
1613 1787 <?php self::roles_options( $capability ); ?>
1614 1788 </select>
1615 1789 <?php
@@ -1617,9 +1791,9 @@
1617 1791
1618 1792 /**
1619 1793 * @since 4.07
1620 1794 * @param array|string $selected
1621 - * @param string $current
1795 + * @param string $current
1622 1796 */
1623 1797 private static function selected( $selected, $current ) {
1624 1798 if ( is_callable( 'FrmProAppHelper::selected' ) ) {
1625 1799 FrmProAppHelper::selected( $selected, $current );
@@ -1628,9 +1802,9 @@
1628 1802 }
1629 1803 }
1630 1804
1631 1805 /**
1632 - * @param string|array $capability
1806 + * @param array|string $capability
1633 1807 */
1634 1808 public static function roles_options( $capability ) {
1635 1809 global $frm_vars;
1636 1810 if ( isset( $frm_vars['editable_roles'] ) ) {
@@ -1642,9 +1816,9 @@
1642 1816
1643 1817 foreach ( $editable_roles as $role => $details ) {
1644 1818 $name = translate_user_role( $details['name'] );
1645 1819 ?>
1646 - <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_attr( $name ); ?> </option>
1820 + <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_html( $name ); ?> </option>
1647 1821 <?php
1648 1822 unset( $role, $details );
1649 1823 }
1650 1824 }
@@ -1665,9 +1839,8 @@
1665 1839 $pro_cap = array(
1666 1840 'frm_create_entries' => __( 'Add Entries from Admin Area', 'formidable' ),
1667 1841 'frm_edit_entries' => __( 'Edit Entries from Admin Area', 'formidable' ),
1668 1842 'frm_view_reports' => __( 'View Reports', 'formidable' ),
1669 - 'frm_edit_displays' => __( 'Add/Edit Views', 'formidable' ),
1670 1843 );
1671 1844 /**
1672 1845 * @since 5.3.1
1673 1846 *
@@ -1674,8 +1847,14 @@
1674 1847 * @param array<string,string> $pro_cap
1675 1848 */
1676 1849 $pro_cap = apply_filters( 'frm_pro_capabilities', $pro_cap );
1677 1850
1851 + if ( ! array_key_exists( 'frm_edit_displays', $pro_cap ) && is_callable( 'FrmProAppHelper::views_is_installed' ) && FrmProAppHelper::views_is_installed() ) {
1852 + // For backward compatibility, add the Add/Edit Views permission if Pro is not up to date.
1853 + // This was added in 6.5.4. Remove this in the future.
1854 + $pro_cap['frm_edit_displays'] = __( 'Add/Edit Views', 'formidable' );
1855 + }
1856 +
1678 1857 if ( 'pro_only' === $type ) {
1679 1858 return $pro_cap;
1680 1859 }
1681 1860
@@ -1690,9 +1869,9 @@
1690 1869 * @return array<string,string>
1691 1870 */
1692 1871 private static function get_lite_capabilities() {
1693 1872 return array(
1694 - 'frm_view_forms' => __( 'View Forms', 'formidable' ),
1873 + 'frm_view_forms' => __( 'View Forms List', 'formidable' ),
1695 1874 'frm_edit_forms' => __( 'Add and Edit Forms', 'formidable' ),
1696 1875 'frm_delete_forms' => __( 'Delete Forms', 'formidable' ),
1697 1876 'frm_change_settings' => __( 'Access this Settings Page', 'formidable' ),
1698 1877 'frm_view_entries' => __( 'View Entries from Admin Area', 'formidable' ),
@@ -1733,9 +1912,9 @@
1733 1912 return current_user_can( $role );
1734 1913 }
1735 1914
1736 1915 /**
1737 - * @param string|array $needed_role
1916 + * @param array|string $needed_role
1738 1917 * @return bool
1739 1918 */
1740 1919 public static function user_has_permission( $needed_role ) {
1741 1920 if ( is_array( $needed_role ) ) {
@@ -1791,8 +1970,11 @@
1791 1970 /**
1792 1971 * Make sure admins have permission to see the menu items
1793 1972 *
1794 1973 * @since 2.0.6
1974 + *
1975 + * @param string $cap
1976 + * @return void
1795 1977 */
1796 1978 public static function force_capability( $cap = 'frm_change_settings' ) {
1797 1979 if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
1798 1980 $role = get_role( 'administrator' );
@@ -1803,9 +1985,9 @@
1803 1985 }
1804 1986 }
1805 1987
1806 1988 /**
1807 - * Check if the user has permision for action.
1989 + * Check if the user has permission for action.
1808 1990 * Return permission message and stop the action if no permission
1809 1991 *
1810 1992 * @since 2.0
1811 1993 *
@@ -1841,9 +2023,9 @@
1841 2023 if ( empty( $nonce_name ) ) {
1842 2024 return $error;
1843 2025 }
1844 2026
1845 - $nonce_value = ( $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
2027 + $nonce_value = $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
1846 2028 if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $nonce_value, $nonce ) ) ) {
1847 2029 $frm_settings = self::get_settings();
1848 2030 $error = $frm_settings->admin_permission;
1849 2031 }
@@ -1857,12 +2039,13 @@
1857 2039 }
1858 2040 }
1859 2041
1860 2042 public static function check_selected( $values, $current ) {
1861 - $values = self::recursive_function_map( $values, 'trim' );
1862 - $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1863 - $current = htmlspecialchars_decode( trim( $current ) );
2043 + $values = self::recursive_function_map( $values, 'trim' );
2044 + $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1864 2045
2046 + $current = is_null( $current ) ? '' : htmlspecialchars_decode( trim( $current ) );
2047 +
1865 2048 return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
1866 2049 }
1867 2050
1868 2051 public static function recursive_function_map( $value, $function ) {
@@ -1882,8 +2065,9 @@
1882 2065 }
1883 2066 }
1884 2067 }
1885 2068 } else {
2069 + $value = self::maybe_update_value_if_null( $value, $function );
1886 2070 $value = call_user_func( $function, $value );
1887 2071 }
1888 2072
1889 2073 return $value;
@@ -1888,8 +2072,24 @@
1888 2072
1889 2073 return $value;
1890 2074 }
1891 2075
2076 + /**
2077 + * Updates value to empty string if it is null and being passed to a string function.
2078 + *
2079 + * @since 6.8.4
2080 + * @param mixed $value
2081 + * @param string $function
2082 + * @return mixed
2083 + */
2084 + private static function maybe_update_value_if_null( $value, $function ) {
2085 + if ( null === $value && in_array( $function, array( 'trim', 'strlen' ), true ) ) {
2086 + $value = '';
2087 + }
2088 +
2089 + return $value;
2090 + }
2091 +
1892 2092 public static function is_assoc( $array ) {
1893 2093 return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
1894 2094 }
1895 2095
@@ -1900,14 +2100,12 @@
1900 2100 $return = array();
1901 2101 foreach ( $array as $key => $value ) {
1902 2102 if ( is_array( $value ) ) {
1903 2103 $return = array_merge( $return, self::array_flatten( $value, $keys ) );
2104 + } elseif ( $keys === 'keep' ) {
2105 + $return[ $key ] = $value;
1904 2106 } else {
1905 - if ( $keys === 'keep' ) {
1906 - $return[ $key ] = $value;
1907 - } else {
1908 - $return[] = $value;
1909 - }
2107 + $return[] = $value;
1910 2108 }
1911 2109 }
1912 2110
1913 2111 return $return;
@@ -1912,8 +2110,13 @@
1912 2110
1913 2111 return $return;
1914 2112 }
1915 2113
2114 + /**
2115 + * @param string $text
2116 + * @param bool $is_rich_text
2117 + * @return string
2118 + */
1916 2119 public static function esc_textarea( $text, $is_rich_text = false ) {
1917 2120 $safe_text = str_replace( '&quot;', '"', $text );
1918 2121 if ( ! $is_rich_text ) {
1919 2122 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
@@ -1919,9 +2122,13 @@
1919 2122 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
1920 2123 }
1921 2124 $safe_text = str_replace( '&amp; ', '& ', $safe_text );
1922 2125
1923 - return apply_filters( 'esc_textarea', $safe_text, $text );
2126 + /**
2127 + * @param string $safe_text
2128 + * @param string $text
2129 + */
2130 + return (string) apply_filters( 'esc_textarea', $safe_text, $text );
1924 2131 }
1925 2132
1926 2133 /**
1927 2134 * Add auto paragraphs to text areas
@@ -1972,12 +2179,12 @@
1972 2179 * @since 5.0.13 added $echo param.
1973 2180 *
1974 2181 * @param string $url
1975 2182 * @param bool $echo
1976 - * @return string|void
2183 + * @return string|null
1977 2184 */
1978 2185 public static function js_redirect( $url, $echo = false ) {
1979 - $callback = function() use ( $url ) {
2186 + $callback = function () use ( $url ) {
1980 2187 echo '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
1981 2188 };
1982 2189 return self::clip( $callback, $echo );
1983 2190 }
@@ -2005,8 +2212,13 @@
2005 2212
2006 2213 return $user_id;
2007 2214 }
2008 2215
2216 + /**
2217 + * @param string $filename
2218 + * @param array $atts
2219 + * @return false|string
2220 + */
2009 2221 public static function get_file_contents( $filename, $atts = array() ) {
2010 2222 if ( ! is_file( $filename ) ) {
2011 2223 return false;
2012 2224 }
@@ -2012,9 +2224,9 @@
2012 2224 }
2013 2225
2014 2226 extract( $atts ); // phpcs:ignore WordPress.PHP.DontExtract
2015 2227 ob_start();
2016 - include( $filename );
2228 + include $filename;
2017 2229 $contents = ob_get_contents();
2018 2230 ob_end_clean();
2019 2231
2020 2232 return $contents;
@@ -2069,9 +2281,9 @@
2069 2281 ++$suffix;
2070 2282 } while ( in_array( $key_check, $similar_keys, true ) );
2071 2283
2072 2284 $key = $key_check;
2073 - }
2285 + }//end if
2074 2286
2075 2287 return $key;
2076 2288 }
2077 2289
@@ -2115,9 +2327,11 @@
2115 2327 * @return string
2116 2328 */
2117 2329 private static function generate_new_key( $num_chars ) {
2118 2330 $max_slug_value = pow( 36, $num_chars );
2119 - $min_slug_value = 37; // we want to have at least 2 characters in the slug
2331 +
2332 + // We want to have at least 2 characters in the slug.
2333 + $min_slug_value = 37;
2120 2334 return base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
2121 2335 }
2122 2336
2123 2337 /**
@@ -2146,11 +2360,16 @@
2146 2360
2147 2361 /**
2148 2362 * Editing a Form or Entry
2149 2363 *
2150 - * @param string $table
2364 + * @param object $record
2365 + * @param string $table
2366 + * @param array|string $fields
2367 + * @param bool $default
2368 + * @param array $post_values
2369 + * @param array $args
2151 2370 *
2152 - * @return bool|array
2371 + * @return array|bool
2153 2372 */
2154 2373 public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
2155 2374 if ( ! $record ) {
2156 2375 return false;
@@ -2203,13 +2422,12 @@
2203 2422 $post_values = $args['post_values'];
2204 2423
2205 2424 if ( $args['default'] ) {
2206 2425 $meta_value = $field->default_value;
2207 - } else {
2208 - if ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
2209 - if ( ! isset( $field->field_options['custom_field'] ) ) {
2210 - $field->field_options['custom_field'] = '';
2211 - }
2426 + } elseif ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
2427 + if ( ! isset( $field->field_options['custom_field'] ) ) {
2428 + $field->field_options['custom_field'] = '';
2429 + }
2212 2430 $meta_value = FrmProEntryMetaHelper::get_post_value(
2213 2431 $record->post_id,
2214 2432 $field->field_options['post_field'],
2215 2433 $field->field_options['custom_field'],
@@ -2219,12 +2437,11 @@
2219 2437 'form_id' => $field->form_id,
2220 2438 'field' => $field,
2221 2439 )
2222 2440 );
2223 - } else {
2224 - $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2225 - }
2226 - }
2441 + } else {
2442 + $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2443 + }//end if
2227 2444
2228 2445 $field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
2229 2446 if ( isset( $post_values['item_meta'][ $field->id ] ) ) {
2230 2447 $new_value = $post_values['item_meta'][ $field->id ];
@@ -2272,12 +2489,15 @@
2272 2489 );
2273 2490 }
2274 2491
2275 2492 /**
2493 + * @param object $record
2276 2494 * @param string $table
2495 + * @param array $post_values
2496 + * @param array $values
2277 2497 */
2278 2498 private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
2279 - if ( $table == 'entries' ) {
2499 + if ( $table === 'entries' ) {
2280 2500 $form = $record->form_id;
2281 2501 FrmForm::maybe_get_form( $form );
2282 2502 } else {
2283 2503 $form = $record;
@@ -2313,9 +2533,9 @@
2313 2533 $form_defaults = FrmFormsHelper::get_default_opts();
2314 2534
2315 2535 foreach ( $form_defaults as $opt => $default ) {
2316 2536 if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
2317 - $values[ $opt ] = ( $post_values && isset( $post_values['options'][ $opt ] ) ) ? $post_values['options'][ $opt ] : $default;
2537 + $values[ $opt ] = $post_values && isset( $post_values['options'][ $opt ] ) ? $post_values['options'][ $opt ] : $default;
2318 2538 }
2319 2539
2320 2540 unset( $opt, $default );
2321 2541 }
@@ -2336,9 +2556,9 @@
2336 2556 * @since 2.2.10
2337 2557 *
2338 2558 * @param array $post_values
2339 2559 *
2340 - * @return boolean|int
2560 + * @return bool|int
2341 2561 */
2342 2562 public static function custom_style_value( $post_values ) {
2343 2563 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2344 2564 $custom_style = absint( $post_values['options']['custom_style'] );
@@ -2343,29 +2563,37 @@
2343 2563 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2344 2564 $custom_style = absint( $post_values['options']['custom_style'] );
2345 2565 } else {
2346 2566 $frm_settings = self::get_settings();
2347 - $custom_style = ( $frm_settings->load_style != 'none' );
2567 + $custom_style = ( $frm_settings->load_style !== 'none' );
2348 2568 }
2349 2569
2350 2570 return $custom_style;
2351 2571 }
2352 2572
2353 - public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
2354 - if ( is_array( $str ) ) {
2573 + /**
2574 + * @param mixed $original_string
2575 + * @param int|string $length
2576 + * @param int $minword
2577 + * @param string $continue
2578 + * @return string
2579 + */
2580 + public static function truncate( $original_string, $length, $minword = 3, $continue = '...' ) {
2581 + if ( ! is_string( $original_string ) && ! is_int( $original_string ) ) {
2355 2582 return '';
2356 2583 }
2357 2584
2358 2585 $length = (int) $length;
2359 - $str = wp_strip_all_tags( $str );
2586 + $str = wp_strip_all_tags( (string) $original_string );
2360 2587 $original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
2361 2588
2362 2589 if ( $length == 0 ) {
2363 2590 return '';
2364 - } elseif ( $length <= 10 ) {
2591 + }
2592 +
2593 + if ( $length <= 10 ) {
2365 2594 $sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
2366 -
2367 - return $sub . ( ( $length < $original_len ) ? $continue : '' );
2595 + return $sub . ( $length < $original_len ? $continue : '' );
2368 2596 }
2369 2597
2370 2598 $sub = '';
2371 2599 $len = 0;
@@ -2371,10 +2599,14 @@
2371 2599 $len = 0;
2372 2600
2373 2601 $words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
2374 2602
2603 + if ( ! is_array( $words ) ) {
2604 + return $original_string;
2605 + }
2606 +
2375 2607 foreach ( $words as $word ) {
2376 - $part = ( ( $sub != '' ) ? ' ' : '' ) . $word;
2608 + $part = ( $sub != '' ? ' ' : '' ) . $word;
2377 2609 $total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
2378 2610 if ( $total_len > $length && substr_count( $sub, ' ' ) ) {
2379 2611 break;
2380 2612 }
@@ -2388,11 +2620,37 @@
2388 2620
2389 2621 unset( $total_len, $word );
2390 2622 }
2391 2623
2392 - return $sub . ( ( $len < $original_len ) ? $continue : '' );
2624 + $sub = self::maybe_force_truncate_on_string_with_no_spaces( $sub, $length );
2625 +
2626 + return $sub . ( $len < $original_len ? $continue : '' );
2393 2627 }
2394 2628
2629 + /**
2630 + * If the string is still too long because there may not have been any spaces, force truncate.
2631 + *
2632 + * @since 6.5.4
2633 + *
2634 + * @param string $sub Current substring.
2635 + * @param int $length The length limit.
2636 + * @return string
2637 + */
2638 + private static function maybe_force_truncate_on_string_with_no_spaces( $sub, $length ) {
2639 + if ( strlen( $sub ) < $length + 50 ) {
2640 + // If the string isn't way over the limit, leave it.
2641 + return $sub;
2642 + }
2643 +
2644 + $first_space = strpos( $sub, ' ', $length );
2645 + if ( false !== $first_space ) {
2646 + // Ignore anything with spaces.
2647 + return $sub;
2648 + }
2649 +
2650 + return substr( $sub, 0, $length + 10 );
2651 + }
2652 +
2395 2653 public static function mb_function( $function_names, $args ) {
2396 2654 $mb_function_name = $function_names[0];
2397 2655 $function_name = $function_names[1];
2398 2656 if ( function_exists( $mb_function_name ) ) {
@@ -2449,12 +2707,12 @@
2449 2707 return date_i18n( $date_format, strtotime( $date ) );
2450 2708 }
2451 2709
2452 2710 /**
2453 - * Gets the time ago in words
2711 + * Gets the time ago in words.
2454 2712 *
2455 - * @param int $from in seconds
2456 - * @param int|string $to in seconds
2713 + * @param int $from In seconds.
2714 + * @param int|string $to In seconds.
2457 2715 *
2458 2716 * @return string $time_ago
2459 2717 */
2460 2718 public static function human_time_diff( $from, $to = '', $levels = 1 ) {
@@ -2469,9 +2727,9 @@
2469 2727 $diff_object = $now->diff( $ago );
2470 2728 $diff = get_object_vars( $diff_object );
2471 2729
2472 2730 // Add week amount and update day amount
2473 - $diff['w'] = floor( $diff['d'] / 7 );
2731 + $diff['w'] = floor( $diff['d'] / 7 );
2474 2732 $diff['d'] -= $diff['w'] * 7;
2475 2733
2476 2734 $time_strings = self::get_time_strings();
2477 2735
@@ -2478,9 +2736,9 @@
2478 2736 if ( ! is_numeric( $levels ) ) {
2479 2737 // Show time in specified unit.
2480 2738 $levels = self::get_unit( $levels );
2481 2739 if ( isset( $time_strings[ $levels ] ) ) {
2482 - $diff = array(
2740 + $diff = array(
2483 2741 $levels => self::time_format( $levels, $diff ),
2484 2742 );
2485 2743 $time_strings = array(
2486 2744 $levels => $time_strings[ $levels ],
@@ -2569,9 +2827,9 @@
2569 2827 }
2570 2828
2571 2829 /**
2572 2830 * Get the translatable time strings. The untranslated version is a failsafe
2573 - * in case langauges are changing for the unit set in the shortcode.
2831 + * in case languages are changing for the unit set in the shortcode.
2574 2832 *
2575 2833 * @since 2.0.20
2576 2834 * @return array
2577 2835 */
@@ -2617,23 +2875,28 @@
2617 2875
2618 2876 // Pagination Methods.
2619 2877
2620 2878 /**
2621 - * @param integer $current_p
2879 + * @param int $r_count
2880 + * @param int $current_p
2881 + * @param int $p_size
2882 + * @return int
2622 2883 */
2623 2884 public static function get_last_record_num( $r_count, $current_p, $p_size ) {
2624 - return ( ( $r_count < ( $current_p * $p_size ) ) ? $r_count : ( $current_p * $p_size ) );
2885 + return ( $r_count < $current_p * $p_size ? $r_count : $current_p * $p_size );
2625 2886 }
2626 2887
2627 2888 /**
2628 - * @param integer $current_p
2889 + * @param int $r_count
2890 + * @param int $current_p
2891 + * @param int $p_size
2892 + * @return int
2629 2893 */
2630 2894 public static function get_first_record_num( $r_count, $current_p, $p_size ) {
2631 2895 if ( $current_p == 1 ) {
2632 2896 return 1;
2633 - } else {
2634 - return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
2635 2897 }
2898 + return self::get_last_record_num( $r_count, $current_p - 1, $p_size ) + 1;
2636 2899 }
2637 2900
2638 2901 /**
2639 2902 * @return array
@@ -2656,9 +2919,9 @@
2656 2919 if ( ! isset( $l3 ) ) {
2657 2920 $l3 = $name;
2658 2921 }
2659 2922
2660 - $this_val = ( $p == $last ) ? $jv['value'] : array();
2923 + $this_val = $p == $last ? $jv['value'] : array();
2661 2924
2662 2925 switch ( $p ) {
2663 2926 case 0:
2664 2927 $l1 = $name;
@@ -2680,12 +2943,12 @@
2680 2943 self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
2681 2944 }
2682 2945
2683 2946 unset( $this_val, $n );
2684 - }
2947 + }//end foreach
2685 2948
2686 2949 unset( $last, $jv );
2687 - }
2950 + }//end foreach
2688 2951
2689 2952 return $vars;
2690 2953 }
2691 2954
@@ -2933,8 +3196,11 @@
2933 3196 }
2934 3197
2935 3198 /**
2936 3199 * @since 4.02.03
3200 + *
3201 + * @param array|string $value
3202 + * @return string
2937 3203 */
2938 3204 public static function maybe_json_encode( $value ) {
2939 3205 if ( is_array( $value ) ) {
2940 3206 $value = wp_json_encode( $value );
@@ -2942,12 +3208,14 @@
2942 3208 return $value;
2943 3209 }
2944 3210
2945 3211 /**
3212 + * Echo The javascript to open and highlight the Formidable menu
3213 + *
2946 3214 * @since 1.07.10
2947 3215 *
2948 - * @param string $post_type The name of the post type that may need to be highlighted
2949 - * echo The javascript to open and highlight the Formidable menu
3216 + * @param string $post_type The name of the post type that may need to be highlighted.
3217 + * @return void
2950 3218 */
2951 3219 public static function maybe_highlight_menu( $post_type ) {
2952 3220 global $post;
2953 3221
@@ -2966,8 +3234,11 @@
2966 3234 /**
2967 3235 * Load the JS file on non-Formidable pages in the admin area
2968 3236 *
2969 3237 * @since 2.0
3238 + *
3239 + * @param bool $load
3240 + * @return void
2970 3241 */
2971 3242 public static function load_admin_wide_js( $load = true ) {
2972 3243 $version = self::plugin_version();
2973 3244 wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
@@ -2981,8 +3252,9 @@
2981 3252 'canAccessApplicationDashboard' => current_user_can( is_callable( 'FrmProApplicationsHelper::get_required_templates_capability' ) ? FrmProApplicationsHelper::get_required_templates_capability() : 'frm_edit_forms' ),
2982 3253 'loading' => __( 'Loading&hellip;', 'formidable' ),
2983 3254 'nonce' => wp_create_nonce( 'frm_ajax' ),
2984 3255 'proIncludesSliderJs' => is_callable( 'FrmProFormsHelper::prepare_custom_currency' ),
3256 + 'inboxSlideIn' => FrmInbox::get_inbox_slide_in_value_for_js(),
2985 3257 );
2986 3258 wp_localize_script( 'formidable_admin_global', 'frmGlobal', $global_strings );
2987 3259
2988 3260 if ( $load ) {
@@ -2991,8 +3263,9 @@
2991 3263 }
2992 3264
2993 3265 /**
2994 3266 * @since 2.0.9
3267 + * @return void
2995 3268 */
2996 3269 public static function load_font_style() {
2997 3270 wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
2998 3271 }
@@ -2998,26 +3271,29 @@
2998 3271 }
2999 3272
3000 3273 /**
3001 3274 * @param string $location
3275 + * @return void
3002 3276 */
3003 3277 public static function localize_script( $location ) {
3004 3278 global $wp_scripts;
3005 3279
3006 3280 $script_strings = array(
3007 - 'ajax_url' => esc_url_raw( self::get_ajax_url() ),
3008 - 'images_url' => self::plugin_url() . '/images',
3009 - 'loading' => __( 'Loading&hellip;', 'formidable' ),
3010 - 'remove' => __( 'Remove', 'formidable' ),
3011 - 'offset' => apply_filters( 'frm_scroll_offset', 4 ),
3012 - 'nonce' => wp_create_nonce( 'frm_ajax' ),
3013 - 'id' => __( 'ID', 'formidable' ),
3014 - 'no_results' => __( 'No results match', 'formidable' ),
3015 - 'file_spam' => __( 'That file looks like Spam.', 'formidable' ),
3016 - 'calc_error' => __( 'There is an error in the calculation in the field with key', 'formidable' ),
3017 - 'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
3018 - 'focus_first_error' => self::should_focus_first_error(),
3019 - 'include_alert_role' => self::should_include_alert_role_on_field_errors(),
3281 + 'ajax_url' => esc_url_raw( self::get_ajax_url() ),
3282 + 'images_url' => self::plugin_url() . '/images',
3283 + 'loading' => __( 'Loading&hellip;', 'formidable' ),
3284 + 'remove' => __( 'Remove', 'formidable' ),
3285 + 'offset' => apply_filters( 'frm_scroll_offset', 4 ),
3286 + 'nonce' => wp_create_nonce( 'frm_ajax' ),
3287 + 'id' => __( 'ID', 'formidable' ),
3288 + 'no_results' => __( 'No results match', 'formidable' ),
3289 + 'file_spam' => __( 'That file looks like Spam.', 'formidable' ),
3290 + 'calc_error' => __( 'There is an error in the calculation in the field with key', 'formidable' ),
3291 + 'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
3292 + 'focus_first_error' => self::should_focus_first_error(),
3293 + 'include_alert_role' => self::should_include_alert_role_on_field_errors(),
3294 + // We need to keep this setting for a few versions because Pro checks for this.
3295 + 'include_resend_email' => false,
3020 3296 );
3021 3297
3022 3298 $data = $wp_scripts->get_data( 'formidable', 'data' );
3023 3299 if ( ! $data ) {
@@ -3024,9 +3300,8 @@
3024 3300 wp_localize_script( 'formidable', 'frm_js', $script_strings );
3025 3301 }
3026 3302
3027 3303 if ( $location === 'admin' ) {
3028 - $frm_settings = self::get_settings();
3029 3304 $admin_script_strings = array(
3030 3305 'desc' => __( '(Click to add description)', 'formidable' ),
3031 3306 'blank' => __( '(Blank)', 'formidable' ),
3032 3307 'no_label' => __( '(no label)', 'formidable' ),
@@ -3040,9 +3315,9 @@
3040 3315 'confirm' => __( 'Are you sure?', 'formidable' ),
3041 3316 'conf_delete' => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
3042 3317 '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' ),
3043 3318 'conf_no_repeat' => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
3044 - 'default_unique' => $frm_settings->unique_msg,
3319 + 'default_unique' => FrmFieldsHelper::default_unique_msg(),
3045 3320 'default_conf' => __( 'The entered values do not match', 'formidable' ),
3046 3321 'enter_email' => __( 'Enter Email', 'formidable' ),
3047 3322 'confirm_email' => __( 'Confirm Email', 'formidable' ),
3048 3323 'conditional_text' => __( 'Conditional content here', 'formidable' ),
@@ -3059,9 +3334,11 @@
3059 3334 'no_licenses' => __( 'No new licenses were found', 'formidable' ),
3060 3335 'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3061 3336 'view_shortcodes' => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
3062 3337 'text_shortcodes' => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
3063 - 'only_one_action' => __( 'This form action is limited to one per form. Please edit the existing form action.', 'formidable' ),
3338 + /* translators: %d is the number of allowed actions per form */
3339 + 'only_one_action' => sprintf( __( 'This form action is limited to %d per form.', 'formidable' ), 1 ),
3340 + 'edit_action_text' => __( 'Please edit the existing form action.', 'formidable' ),
3064 3341 'unsafe_params' => FrmFormsHelper::reserved_words(),
3065 3342 /* Translators: %s is the name of a Detail Page Slug that is a reserved word.*/
3066 3343 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ),
3067 3344 /* 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. */
@@ -3070,13 +3347,22 @@
3070 3347 'repeat_limit_min' => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
3071 3348 'checkbox_limit' => __( 'Please select a limit between 0 and 200.', 'formidable' ),
3072 3349 'install' => __( 'Install', 'formidable' ),
3073 3350 'active' => __( 'Active', 'formidable' ),
3351 + 'installed' => __( 'Installed', 'formidable' ),
3352 + 'not_installed' => __( 'Not Installed', 'formidable' ),
3074 3353 'select_a_field' => __( 'Select a Field', 'formidable' ),
3075 3354 'no_items_found' => __( 'No items found.', 'formidable' ),
3076 3355 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
3077 - 'saving' => '', // Deprecated in 6.0.
3078 - 'saved' => '', // Deprecated in 6.0.
3356 +
3357 + // Deprecated in 6.0.
3358 + 'saving' => '',
3359 +
3360 + // Deprecated in 6.0.
3361 + 'saved' => '',
3362 +
3363 + // translators: %1$s: HTML open tag, %2$s: HTML end tag.
3364 + 'holdShiftMsg' => esc_html__( 'You can hold %1$sShift%2$s on your keyboard to select multiple fields', 'formidable' ),
3079 3365 );
3080 3366 /**
3081 3367 * @param array $admin_script_strings
3082 3368 */
@@ -3085,9 +3371,9 @@
3085 3371 $data = $wp_scripts->get_data( 'formidable_admin', 'data' );
3086 3372 if ( ! $data ) {
3087 3373 wp_localize_script( 'formidable_admin', 'frm_admin_js', $admin_script_strings );
3088 3374 }
3089 - }
3375 + }//end if
3090 3376 }
3091 3377
3092 3378 /**
3093 3379 * @since 6.5
@@ -3131,9 +3417,10 @@
3131 3417 * Echo the message on the plugins listing page
3132 3418 *
3133 3419 * @since 1.07.10
3134 3420 *
3135 - * @param float $min_version The version the add-on requires
3421 + * @param float $min_version The version the add-on requires.
3422 + * @return void
3136 3423 */
3137 3424 public static function min_version_notice( $min_version ) {
3138 3425 $frm_version = self::plugin_version();
3139 3426
@@ -3167,9 +3454,8 @@
3167 3454 if ( ! $is_pro || self::meets_min_pro_version( $min_version ) ) {
3168 3455 return;
3169 3456 }
3170 3457
3171 - $pro_version = FrmProDb::$plug_version;
3172 3458 $expired = FrmAddonsController::is_license_expired();
3173 3459 ?>
3174 3460 <div class="frm-banner-alert frm_error_style frm_previous_install">
3175 3461 <?php
@@ -3187,8 +3473,11 @@
3187 3473 /**
3188 3474 * If Pro is installed, check the version number.
3189 3475 *
3190 3476 * @since 4.0.01
3477 + *
3478 + * @param string $min_version
3479 + * @return bool
3191 3480 */
3192 3481 public static function meets_min_pro_version( $min_version ) {
3193 3482 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
3194 3483 }
@@ -3196,12 +3485,13 @@
3196 3485 /**
3197 3486 * Show a message if the browser or PHP version is below the recommendations.
3198 3487 *
3199 3488 * @since 4.0.02
3489 + * @return void
3200 3490 */
3201 3491 private static function php_version_notice() {
3202 3492 $message = array();
3203 - if ( version_compare( phpversion(), '5.6', '<' ) ) {
3493 + if ( version_compare( phpversion(), '7.0', '<' ) ) {
3204 3494 $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' );
3205 3495 }
3206 3496
3207 3497 $browser = self::get_server_value( 'HTTP_USER_AGENT' );
@@ -3340,16 +3630,10 @@
3340 3630 return $locales;
3341 3631 }
3342 3632
3343 3633 /**
3344 - * Output HTML containing reference text for accessibility
3345 - *
3346 - * @deprecated 5.1
3634 + * @return string
3347 3635 */
3348 - public static function multiselect_accessibility() {
3349 - _deprecated_function( __METHOD__, '5.1' );
3350 - }
3351 -
3352 3636 public static function get_menu_icon_class() {
3353 3637 if ( is_callable( 'FrmProAppHelper::get_settings' ) ) {
3354 3638 $settings = FrmProAppHelper::get_settings();
3355 3639 if ( is_object( $settings ) && ! empty( $settings->menu_icon ) ) {
@@ -3459,8 +3743,18 @@
3459 3743 return apply_filters( 'frm_images_dropdown_input_attrs', $input_attrs_str, $args );
3460 3744 }
3461 3745
3462 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 + /**
3463 3757 * Gets the image of each option in images_dropdown() method.
3464 3758 *
3465 3759 * @since 5.0.04
3466 3760 *
@@ -3471,9 +3765,9 @@
3471 3765 private static function get_images_dropdown_option_image( $option, $args ) {
3472 3766 $image = self::icon_by_class(
3473 3767 'frmfont ' . $option['svg'],
3474 3768 array(
3475 - 'echo' => false,
3769 + 'echo' => false,
3476 3770 )
3477 3771 );
3478 3772
3479 3773 $args['option'] = $option;
@@ -3611,15 +3905,15 @@
3611 3905 return $values;
3612 3906 }
3613 3907
3614 3908 /**
3615 - * Some back end fields allow privleged users to add scripts.
3909 + * Some back end fields allow privileged users to add scripts.
3616 3910 * A site that uses the DISALLOW_UNFILTERED_HTML always remove scripts on echo.
3617 3911 *
3618 3912 * @since 5.0.13
3619 3913 *
3620 3914 * @param string $value
3621 - * @param array|string $allowed 'all' for everything included as defaults
3915 + * @param array|string $allowed 'all' for everything included as defaults.
3622 3916 * @return string
3623 3917 */
3624 3918 public static function maybe_kses( $value, $allowed = 'all' ) {
3625 3919 if ( self::should_never_allow_unfiltered_html() ) {
@@ -3628,8 +3922,64 @@
3628 3922 return $value;
3629 3923 }
3630 3924
3631 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 + /**
3632 3982 * @since 5.0.16
3633 3983 *
3634 3984 * @return bool
3635 3985 */
@@ -3654,20 +4004,9 @@
3654 4004
3655 4005 /**
3656 4006 * @since 5.0.17
3657 4007 *
3658 - * @param string $plugin
3659 - * @return string|false
3660 - */
3661 - private static function get_plan_required( $plugin ) {
3662 - $link = FrmAddonsController::install_link( $plugin );
3663 - return FrmFormsHelper::get_plan_required( $link );
3664 - }
3665 -
3666 - /**
3667 - * @since 5.0.17
3668 - *
3669 - * @param string
4008 + * @param string $feature
3670 4009 * @return bool
3671 4010 */
3672 4011 public static function show_new_feature( $feature ) {
3673 4012 $link = FrmAddonsController::install_link( $feature );
@@ -3740,9 +4079,9 @@
3740 4079 public static function show_pill_text( $text = null ) {
3741 4080 if ( null === $text ) {
3742 4081 $text = __( 'NEW', 'formidable' );
3743 4082 }
3744 - echo '<span class="frm-new-pill">' . esc_html( $text ) . '</span>';
4083 + echo '<span class="frm-meta-tag frm-new-pill">' . esc_html( $text ) . '</span>';
3745 4084 }
3746 4085
3747 4086 /**
3748 4087 * Count the number of decimals digits.
@@ -3749,9 +4088,9 @@
3749 4088 *
3750 4089 * @since 5.2.07
3751 4090 *
3752 4091 * @param mixed $num Number.
3753 - * @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.
3754 4093 */
3755 4094 public static function count_decimals( $num ) {
3756 4095 if ( ! is_numeric( $num ) ) {
3757 4096 return false;
@@ -3782,9 +4121,9 @@
3782 4121 }
3783 4122
3784 4123 add_filter(
3785 4124 'option_gmt_offset',
3786 - function( $offset ) {
4125 + function ( $offset ) {
3787 4126 if ( ! is_string( $offset ) || is_numeric( $offset ) ) {
3788 4127 // Leave a valid value alone.
3789 4128 return $offset;
3790 4129 }
@@ -3866,65 +4205,8 @@
3866 4205 return true;
3867 4206 }
3868 4207
3869 4208 /**
3870 - * @since 4.08
3871 - * @deprecated 4.09.01
3872 - */
3873 - public static function expiring_message() {
3874 - _deprecated_function( __METHOD__, '4.09.01', 'FrmProAddonsController::expiring_message' );
3875 - if ( is_callable( 'FrmProAddonsController::expiring_message' ) ) {
3876 - FrmProAddonsController::expiring_message();
3877 - }
3878 - }
3879 -
3880 - /**
3881 - * Use the WP 4.7 wp_doing_ajax function
3882 - *
3883 - * @since 2.05.07
3884 - * @deprecated 4.04.04
3885 - */
3886 - public static function wp_doing_ajax() {
3887 - _deprecated_function( __METHOD__, '4.04.04', 'wp_doing_ajax' );
3888 - return wp_doing_ajax();
3889 - }
3890 -
3891 - /**
3892 - * @deprecated 4.0
3893 - */
3894 - public static function insert_opt_html( $args ) {
3895 - _deprecated_function( __METHOD__, '4.0', 'FrmFormsHelper::insert_opt_html' );
3896 - FrmFormsHelper::insert_opt_html( $args );
3897 - }
3898 -
3899 - /**
3900 - * @deprecated 3.01
3901 - * @codeCoverageIgnore
3902 - */
3903 - public static function sanitize_array( &$values ) {
3904 - FrmDeprecated::sanitize_array( $values );
3905 - }
3906 -
3907 - /**
3908 - * @since 2.0
3909 - * @deprecated 5.0.13
3910 - *
3911 - * @return string The base Google APIS url for the current version of jQuery UI
3912 - */
3913 - public static function jquery_ui_base_url() {
3914 - _deprecated_function( __FUNCTION__, '5.0.13', 'FrmProAppHelper::jquery_ui_base_url' );
3915 - return is_callable( 'FrmProAppHelper::jquery_ui_base_url' ) ? FrmProAppHelper::jquery_ui_base_url() : '';
3916 - }
3917 -
3918 - /**
3919 - * @since 4.07
3920 - * @deprecated 6.0
3921 - */
3922 - public static function renewal_message() {
3923 - _deprecated_function( __METHOD__, '6.0', 'FrmProAddonsController::renewal_message' );
3924 - }
3925 -
3926 - /**
3927 4209 * Display a dismissable warning message and save its dismissal state.
3928 4210 *
3929 4211 * @since 6.3
3930 4212 *
@@ -3936,9 +4218,9 @@
3936 4218 if ( ! $message || ! $option ) {
3937 4219 return;
3938 4220 }
3939 4221
3940 - $ajax_callback = function() use ( $option ) {
4222 + $ajax_callback = function () use ( $option ) {
3941 4223 self::dismiss_warning_message( $option );
3942 4224 };
3943 4225
3944 4226 // We're handling JS codes with `doJsonPost` and it adds 'frm_' to the beginning of the action.
@@ -3946,9 +4228,9 @@
3946 4228 add_action( 'wp_ajax_frm_' . $option, $ajax_callback );
3947 4229
3948 4230 add_filter(
3949 4231 'frm_message_list',
3950 - function( $show_messages ) use ( $message, $option ) {
4232 + function ( $show_messages ) use ( $message, $option ) {
3951 4233 if ( get_option( $option, false ) ) {
3952 4234 return $show_messages;
3953 4235 }
3954 4236
@@ -3955,9 +4237,9 @@
3955 4237 $dismiss_icon = self::icon_by_class(
3956 4238 'frmfont frm_close_icon',
3957 4239 array(
3958 4240 'aria-label' => _x( 'Dismiss', 'warning message: close icon label', 'formidable' ),
3959 - 'echo' => false,
4241 + 'echo' => false,
3960 4242 )
3961 4243 );
3962 4244
3963 4245 $show_messages[] = $message;
@@ -3984,6 +4266,63 @@
3984 4266 update_option( $option, true, 'no' );
3985 4267 }
3986 4268
3987 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
3988 4327 }
3989 4328 }