PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.12
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.12
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 +627 -289 6.56.12 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.12';
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,16 @@
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 + 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 + ?>
1217 1377 </div>
1218 1378 <?php
1219 1379 }
1220 1380
@@ -1231,8 +1391,10 @@
1231 1391 * Render a button for a new item (Form, Application, etc).
1232 1392 *
1233 1393 * @since 3.0
1234 1394 * @param array $atts {
1395 + * Details about the button.
1396 + *
1235 1397 * @type array $link_hook Custom link hook, calls do_action and exits early.
1236 1398 * @type string $new_link Href value, default #.
1237 1399 * @type string $class Custom class names, space separated.
1238 1400 * @type string $button_text Button text. Default "Add New".
@@ -1244,9 +1406,9 @@
1244 1406 do_action( $atts['link_hook']['hook'], $atts['link_hook']['param'] );
1245 1407 return;
1246 1408 }
1247 1409
1248 - 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'] ) ) {
1249 1411 // Do not render a button if none of these attributes are set.
1250 1412 return;
1251 1413 }
1252 1414
@@ -1252,12 +1414,8 @@
1252 1414
1253 1415 $href = ! empty( $atts['new_link'] ) ? esc_url( $atts['new_link'] ) : '#';
1254 1416 $class = 'button button-primary frm-button-primary';
1255 1417
1256 - if ( ! empty( $atts['trigger_new_form_modal'] ) ) {
1257 - $class .= ' frm-trigger-new-form-modal';
1258 - }
1259 -
1260 1418 if ( ! empty( $atts['class'] ) ) {
1261 1419 $class .= ' ' . $atts['class'];
1262 1420 }
1263 1421
@@ -1274,10 +1432,11 @@
1274 1432 'placeholder' => '',
1275 1433 'tosearch' => '',
1276 1434 'text' => __( 'Search', 'formidable' ),
1277 1435 'input_id' => '',
1436 + 'value' => false,
1278 1437 );
1279 - $atts = array_merge( $defaults, $atts );
1438 + $atts = array_merge( $defaults, $atts );
1280 1439
1281 1440 if ( $atts['input_id'] === 'template' && empty( $atts['tosearch'] ) ) {
1282 1441 $atts['tosearch'] = 'frm-card';
1283 1442 }
@@ -1288,8 +1447,27 @@
1288 1447 }
1289 1448
1290 1449 $input_id = $atts['input_id'] . '-search-input';
1291 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 + }
1292 1470 ?>
1293 1471 <p class="frm-search">
1294 1472 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1295 1473 <?php echo esc_html( $atts['text'] ); ?>:
@@ -1294,15 +1472,9 @@
1294 1472 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1295 1473 <?php echo esc_html( $atts['text'] ); ?>:
1296 1474 </label>
1297 1475 <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 - />
1476 + <input <?php self::array_to_html_params( $input_atts, true ); ?> />
1305 1477 <?php
1306 1478 if ( empty( $atts['tosearch'] ) ) {
1307 1479 submit_button( $atts['text'], 'button-secondary', '', false, array( 'id' => 'search-submit' ) );
1308 1480 }
@@ -1312,8 +1484,9 @@
1312 1484 }
1313 1485
1314 1486 /**
1315 1487 * @param string $type
1488 + * @return void
1316 1489 */
1317 1490 public static function trigger_hook_load( $type, $object = null ) {
1318 1491 // Only load the form hooks once.
1319 1492 $hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
@@ -1357,9 +1530,9 @@
1357 1530 'new_file_path' => self::plugin_path() . '/js',
1358 1531 )
1359 1532 );
1360 1533 $new_file = new FrmCreateFile( $file_atts );
1361 - $files = array(
1534 + $files = array(
1362 1535 FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.min.js',
1363 1536 );
1364 1537
1365 1538 /**
@@ -1376,14 +1549,14 @@
1376 1549 * True when value is 1, true, 'true', 'yes'
1377 1550 *
1378 1551 * @since 1.07.10
1379 1552 *
1380 - * @param string $value The value to compare
1553 + * @param string $value The value to compare.
1381 1554 *
1382 - * @return boolean True or False
1555 + * @return bool
1383 1556 */
1384 1557 public static function is_true( $value ) {
1385 - return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
1558 + return true === $value || 1 == $value || 'true' === $value || 'yes' === $value;
1386 1559 }
1387 1560
1388 1561 /**
1389 1562 * Gets all post from a specific post type.
@@ -1449,9 +1622,9 @@
1449 1622
1450 1623 wp_enqueue_script( 'jquery-ui-autocomplete' );
1451 1624
1452 1625 $selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
1453 - $title = '';
1626 + $title = '';
1454 1627
1455 1628 if ( $selected ) {
1456 1629 $title = get_the_title( $selected );
1457 1630 }
@@ -1467,11 +1640,11 @@
1467 1640 <?php
1468 1641 }
1469 1642
1470 1643 /**
1471 - * @param array $args
1472 - * @param string $page_id Deprecated.
1473 - * @param boolean $truncate Deprecated.
1644 + * @param array $args
1645 + * @param string $page_id Deprecated.
1646 + * @param bool $truncate Deprecated.
1474 1647 */
1475 1648 public static function wp_pages_dropdown( $args = array(), $page_id = '', $truncate = false ) {
1476 1649 self::prep_page_dropdown_params( $page_id, $truncate, $args );
1477 1650
@@ -1515,13 +1688,13 @@
1515 1688 * @since 4.10.01 Added `post_type` and `autocomplete_placeholder` to the arguments array.
1516 1689 */
1517 1690 private static function preformat_selection_args( $args ) {
1518 1691 $defaults = array(
1519 - 'truncate' => false,
1520 - 'placeholder' => ' ',
1521 - 'field_name' => '',
1522 - 'page_id' => '',
1523 - 'post_type' => 'page',
1692 + 'truncate' => false,
1693 + 'placeholder' => ' ',
1694 + 'field_name' => '',
1695 + 'page_id' => '',
1696 + 'post_type' => 'page',
1524 1697 'autocomplete_placeholder' => __( 'Select a Page', 'formidable' ),
1525 1698 );
1526 1699
1527 1700 return array_merge( $defaults, $args );
@@ -1601,16 +1774,16 @@
1601 1774 return $link;
1602 1775 }
1603 1776
1604 1777 /**
1605 - * @param string $field_name
1606 - * @param string|array $capability
1607 - * @param string $multiple 'single' and 'multiple'
1778 + * @param string $field_name
1779 + * @param array|string $capability
1780 + * @param string $multiple 'single' and 'multiple'.
1608 1781 */
1609 1782 public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
1610 1783 ?>
1611 1784 <select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>"
1612 - <?php echo ( 'multiple' === $multiple ) ? 'multiple="multiple"' : ''; ?>
1785 + <?php echo 'multiple' === $multiple ? 'multiple="multiple"' : ''; ?>
1613 1786 class="frm_multiselect">
1614 1787 <?php self::roles_options( $capability ); ?>
1615 1788 </select>
1616 1789 <?php
@@ -1618,9 +1791,9 @@
1618 1791
1619 1792 /**
1620 1793 * @since 4.07
1621 1794 * @param array|string $selected
1622 - * @param string $current
1795 + * @param string $current
1623 1796 */
1624 1797 private static function selected( $selected, $current ) {
1625 1798 if ( is_callable( 'FrmProAppHelper::selected' ) ) {
1626 1799 FrmProAppHelper::selected( $selected, $current );
@@ -1629,9 +1802,9 @@
1629 1802 }
1630 1803 }
1631 1804
1632 1805 /**
1633 - * @param string|array $capability
1806 + * @param array|string $capability
1634 1807 */
1635 1808 public static function roles_options( $capability ) {
1636 1809 global $frm_vars;
1637 1810 if ( isset( $frm_vars['editable_roles'] ) ) {
@@ -1643,9 +1816,9 @@
1643 1816
1644 1817 foreach ( $editable_roles as $role => $details ) {
1645 1818 $name = translate_user_role( $details['name'] );
1646 1819 ?>
1647 - <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>
1648 1821 <?php
1649 1822 unset( $role, $details );
1650 1823 }
1651 1824 }
@@ -1666,9 +1839,8 @@
1666 1839 $pro_cap = array(
1667 1840 'frm_create_entries' => __( 'Add Entries from Admin Area', 'formidable' ),
1668 1841 'frm_edit_entries' => __( 'Edit Entries from Admin Area', 'formidable' ),
1669 1842 'frm_view_reports' => __( 'View Reports', 'formidable' ),
1670 - 'frm_edit_displays' => __( 'Add/Edit Views', 'formidable' ),
1671 1843 );
1672 1844 /**
1673 1845 * @since 5.3.1
1674 1846 *
@@ -1675,8 +1847,14 @@
1675 1847 * @param array<string,string> $pro_cap
1676 1848 */
1677 1849 $pro_cap = apply_filters( 'frm_pro_capabilities', $pro_cap );
1678 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 +
1679 1857 if ( 'pro_only' === $type ) {
1680 1858 return $pro_cap;
1681 1859 }
1682 1860
@@ -1691,9 +1869,9 @@
1691 1869 * @return array<string,string>
1692 1870 */
1693 1871 private static function get_lite_capabilities() {
1694 1872 return array(
1695 - 'frm_view_forms' => __( 'View Forms', 'formidable' ),
1873 + 'frm_view_forms' => __( 'View Forms List', 'formidable' ),
1696 1874 'frm_edit_forms' => __( 'Add and Edit Forms', 'formidable' ),
1697 1875 'frm_delete_forms' => __( 'Delete Forms', 'formidable' ),
1698 1876 'frm_change_settings' => __( 'Access this Settings Page', 'formidable' ),
1699 1877 'frm_view_entries' => __( 'View Entries from Admin Area', 'formidable' ),
@@ -1734,9 +1912,9 @@
1734 1912 return current_user_can( $role );
1735 1913 }
1736 1914
1737 1915 /**
1738 - * @param string|array $needed_role
1916 + * @param array|string $needed_role
1739 1917 * @return bool
1740 1918 */
1741 1919 public static function user_has_permission( $needed_role ) {
1742 1920 if ( is_array( $needed_role ) ) {
@@ -1792,8 +1970,11 @@
1792 1970 /**
1793 1971 * Make sure admins have permission to see the menu items
1794 1972 *
1795 1973 * @since 2.0.6
1974 + *
1975 + * @param string $cap
1976 + * @return void
1796 1977 */
1797 1978 public static function force_capability( $cap = 'frm_change_settings' ) {
1798 1979 if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
1799 1980 $role = get_role( 'administrator' );
@@ -1804,9 +1985,9 @@
1804 1985 }
1805 1986 }
1806 1987
1807 1988 /**
1808 - * Check if the user has permision for action.
1989 + * Check if the user has permission for action.
1809 1990 * Return permission message and stop the action if no permission
1810 1991 *
1811 1992 * @since 2.0
1812 1993 *
@@ -1842,9 +2023,9 @@
1842 2023 if ( empty( $nonce_name ) ) {
1843 2024 return $error;
1844 2025 }
1845 2026
1846 - $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 ] ) ) : '';
1847 2028 if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $nonce_value, $nonce ) ) ) {
1848 2029 $frm_settings = self::get_settings();
1849 2030 $error = $frm_settings->admin_permission;
1850 2031 }
@@ -1858,12 +2039,13 @@
1858 2039 }
1859 2040 }
1860 2041
1861 2042 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 ) );
2043 + $values = self::recursive_function_map( $values, 'trim' );
2044 + $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1865 2045
2046 + $current = is_null( $current ) ? '' : htmlspecialchars_decode( trim( $current ) );
2047 +
1866 2048 return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
1867 2049 }
1868 2050
1869 2051 public static function recursive_function_map( $value, $function ) {
@@ -1883,8 +2065,9 @@
1883 2065 }
1884 2066 }
1885 2067 }
1886 2068 } else {
2069 + $value = self::maybe_update_value_if_null( $value, $function );
1887 2070 $value = call_user_func( $function, $value );
1888 2071 }
1889 2072
1890 2073 return $value;
@@ -1889,8 +2072,24 @@
1889 2072
1890 2073 return $value;
1891 2074 }
1892 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 +
1893 2092 public static function is_assoc( $array ) {
1894 2093 return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
1895 2094 }
1896 2095
@@ -1901,14 +2100,12 @@
1901 2100 $return = array();
1902 2101 foreach ( $array as $key => $value ) {
1903 2102 if ( is_array( $value ) ) {
1904 2103 $return = array_merge( $return, self::array_flatten( $value, $keys ) );
2104 + } elseif ( $keys === 'keep' ) {
2105 + $return[ $key ] = $value;
1905 2106 } else {
1906 - if ( $keys === 'keep' ) {
1907 - $return[ $key ] = $value;
1908 - } else {
1909 - $return[] = $value;
1910 - }
2107 + $return[] = $value;
1911 2108 }
1912 2109 }
1913 2110
1914 2111 return $return;
@@ -1913,8 +2110,13 @@
1913 2110
1914 2111 return $return;
1915 2112 }
1916 2113
2114 + /**
2115 + * @param string $text
2116 + * @param bool $is_rich_text
2117 + * @return string
2118 + */
1917 2119 public static function esc_textarea( $text, $is_rich_text = false ) {
1918 2120 $safe_text = str_replace( '&quot;', '"', $text );
1919 2121 if ( ! $is_rich_text ) {
1920 2122 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
@@ -1920,9 +2122,13 @@
1920 2122 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
1921 2123 }
1922 2124 $safe_text = str_replace( '&amp; ', '& ', $safe_text );
1923 2125
1924 - 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 );
1925 2131 }
1926 2132
1927 2133 /**
1928 2134 * Add auto paragraphs to text areas
@@ -1973,12 +2179,12 @@
1973 2179 * @since 5.0.13 added $echo param.
1974 2180 *
1975 2181 * @param string $url
1976 2182 * @param bool $echo
1977 - * @return string|void
2183 + * @return string|null
1978 2184 */
1979 2185 public static function js_redirect( $url, $echo = false ) {
1980 - $callback = function() use ( $url ) {
2186 + $callback = function () use ( $url ) {
1981 2187 echo '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
1982 2188 };
1983 2189 return self::clip( $callback, $echo );
1984 2190 }
@@ -2006,8 +2212,13 @@
2006 2212
2007 2213 return $user_id;
2008 2214 }
2009 2215
2216 + /**
2217 + * @param string $filename
2218 + * @param array $atts
2219 + * @return false|string
2220 + */
2010 2221 public static function get_file_contents( $filename, $atts = array() ) {
2011 2222 if ( ! is_file( $filename ) ) {
2012 2223 return false;
2013 2224 }
@@ -2013,9 +2224,9 @@
2013 2224 }
2014 2225
2015 2226 extract( $atts ); // phpcs:ignore WordPress.PHP.DontExtract
2016 2227 ob_start();
2017 - include( $filename );
2228 + include $filename;
2018 2229 $contents = ob_get_contents();
2019 2230 ob_end_clean();
2020 2231
2021 2232 return $contents;
@@ -2070,9 +2281,9 @@
2070 2281 ++$suffix;
2071 2282 } while ( in_array( $key_check, $similar_keys, true ) );
2072 2283
2073 2284 $key = $key_check;
2074 - }
2285 + }//end if
2075 2286
2076 2287 return $key;
2077 2288 }
2078 2289
@@ -2116,9 +2327,11 @@
2116 2327 * @return string
2117 2328 */
2118 2329 private static function generate_new_key( $num_chars ) {
2119 2330 $max_slug_value = pow( 36, $num_chars );
2120 - $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;
2121 2334 return base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
2122 2335 }
2123 2336
2124 2337 /**
@@ -2147,11 +2360,16 @@
2147 2360
2148 2361 /**
2149 2362 * Editing a Form or Entry
2150 2363 *
2151 - * @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
2152 2370 *
2153 - * @return bool|array
2371 + * @return array|bool
2154 2372 */
2155 2373 public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
2156 2374 if ( ! $record ) {
2157 2375 return false;
@@ -2204,13 +2422,12 @@
2204 2422 $post_values = $args['post_values'];
2205 2423
2206 2424 if ( $args['default'] ) {
2207 2425 $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 - }
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 + }
2213 2430 $meta_value = FrmProEntryMetaHelper::get_post_value(
2214 2431 $record->post_id,
2215 2432 $field->field_options['post_field'],
2216 2433 $field->field_options['custom_field'],
@@ -2220,12 +2437,11 @@
2220 2437 'form_id' => $field->form_id,
2221 2438 'field' => $field,
2222 2439 )
2223 2440 );
2224 - } else {
2225 - $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2226 - }
2227 - }
2441 + } else {
2442 + $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2443 + }//end if
2228 2444
2229 2445 $field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
2230 2446 if ( isset( $post_values['item_meta'][ $field->id ] ) ) {
2231 2447 $new_value = $post_values['item_meta'][ $field->id ];
@@ -2273,12 +2489,15 @@
2273 2489 );
2274 2490 }
2275 2491
2276 2492 /**
2493 + * @param object $record
2277 2494 * @param string $table
2495 + * @param array $post_values
2496 + * @param array $values
2278 2497 */
2279 2498 private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
2280 - if ( $table == 'entries' ) {
2499 + if ( $table === 'entries' ) {
2281 2500 $form = $record->form_id;
2282 2501 FrmForm::maybe_get_form( $form );
2283 2502 } else {
2284 2503 $form = $record;
@@ -2314,9 +2533,9 @@
2314 2533 $form_defaults = FrmFormsHelper::get_default_opts();
2315 2534
2316 2535 foreach ( $form_defaults as $opt => $default ) {
2317 2536 if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
2318 - $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;
2319 2538 }
2320 2539
2321 2540 unset( $opt, $default );
2322 2541 }
@@ -2337,9 +2556,9 @@
2337 2556 * @since 2.2.10
2338 2557 *
2339 2558 * @param array $post_values
2340 2559 *
2341 - * @return boolean|int
2560 + * @return bool|int
2342 2561 */
2343 2562 public static function custom_style_value( $post_values ) {
2344 2563 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2345 2564 $custom_style = absint( $post_values['options']['custom_style'] );
@@ -2344,29 +2563,37 @@
2344 2563 if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2345 2564 $custom_style = absint( $post_values['options']['custom_style'] );
2346 2565 } else {
2347 2566 $frm_settings = self::get_settings();
2348 - $custom_style = ( $frm_settings->load_style != 'none' );
2567 + $custom_style = ( $frm_settings->load_style !== 'none' );
2349 2568 }
2350 2569
2351 2570 return $custom_style;
2352 2571 }
2353 2572
2354 - public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
2355 - 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 ) ) {
2356 2582 return '';
2357 2583 }
2358 2584
2359 2585 $length = (int) $length;
2360 - $str = wp_strip_all_tags( $str );
2586 + $str = wp_strip_all_tags( (string) $original_string );
2361 2587 $original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
2362 2588
2363 2589 if ( $length == 0 ) {
2364 2590 return '';
2365 - } elseif ( $length <= 10 ) {
2591 + }
2592 +
2593 + if ( $length <= 10 ) {
2366 2594 $sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
2367 -
2368 - return $sub . ( ( $length < $original_len ) ? $continue : '' );
2595 + return $sub . ( $length < $original_len ? $continue : '' );
2369 2596 }
2370 2597
2371 2598 $sub = '';
2372 2599 $len = 0;
@@ -2372,10 +2599,14 @@
2372 2599 $len = 0;
2373 2600
2374 2601 $words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
2375 2602
2603 + if ( ! is_array( $words ) ) {
2604 + return $original_string;
2605 + }
2606 +
2376 2607 foreach ( $words as $word ) {
2377 - $part = ( ( $sub != '' ) ? ' ' : '' ) . $word;
2608 + $part = ( $sub != '' ? ' ' : '' ) . $word;
2378 2609 $total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
2379 2610 if ( $total_len > $length && substr_count( $sub, ' ' ) ) {
2380 2611 break;
2381 2612 }
@@ -2389,11 +2620,37 @@
2389 2620
2390 2621 unset( $total_len, $word );
2391 2622 }
2392 2623
2393 - 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 : '' );
2394 2627 }
2395 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 +
2396 2653 public static function mb_function( $function_names, $args ) {
2397 2654 $mb_function_name = $function_names[0];
2398 2655 $function_name = $function_names[1];
2399 2656 if ( function_exists( $mb_function_name ) ) {
@@ -2450,12 +2707,12 @@
2450 2707 return date_i18n( $date_format, strtotime( $date ) );
2451 2708 }
2452 2709
2453 2710 /**
2454 - * Gets the time ago in words
2711 + * Gets the time ago in words.
2455 2712 *
2456 - * @param int $from in seconds
2457 - * @param int|string $to in seconds
2713 + * @param int $from In seconds.
2714 + * @param int|string $to In seconds.
2458 2715 *
2459 2716 * @return string $time_ago
2460 2717 */
2461 2718 public static function human_time_diff( $from, $to = '', $levels = 1 ) {
@@ -2470,9 +2727,9 @@
2470 2727 $diff_object = $now->diff( $ago );
2471 2728 $diff = get_object_vars( $diff_object );
2472 2729
2473 2730 // Add week amount and update day amount
2474 - $diff['w'] = floor( $diff['d'] / 7 );
2731 + $diff['w'] = floor( $diff['d'] / 7 );
2475 2732 $diff['d'] -= $diff['w'] * 7;
2476 2733
2477 2734 $time_strings = self::get_time_strings();
2478 2735
@@ -2479,9 +2736,9 @@
2479 2736 if ( ! is_numeric( $levels ) ) {
2480 2737 // Show time in specified unit.
2481 2738 $levels = self::get_unit( $levels );
2482 2739 if ( isset( $time_strings[ $levels ] ) ) {
2483 - $diff = array(
2740 + $diff = array(
2484 2741 $levels => self::time_format( $levels, $diff ),
2485 2742 );
2486 2743 $time_strings = array(
2487 2744 $levels => $time_strings[ $levels ],
@@ -2570,9 +2827,9 @@
2570 2827 }
2571 2828
2572 2829 /**
2573 2830 * Get the translatable time strings. The untranslated version is a failsafe
2574 - * 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.
2575 2832 *
2576 2833 * @since 2.0.20
2577 2834 * @return array
2578 2835 */
@@ -2618,23 +2875,28 @@
2618 2875
2619 2876 // Pagination Methods.
2620 2877
2621 2878 /**
2622 - * @param integer $current_p
2879 + * @param int $r_count
2880 + * @param int $current_p
2881 + * @param int $p_size
2882 + * @return int
2623 2883 */
2624 2884 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 ) );
2885 + return ( $r_count < $current_p * $p_size ? $r_count : $current_p * $p_size );
2626 2886 }
2627 2887
2628 2888 /**
2629 - * @param integer $current_p
2889 + * @param int $r_count
2890 + * @param int $current_p
2891 + * @param int $p_size
2892 + * @return int
2630 2893 */
2631 2894 public static function get_first_record_num( $r_count, $current_p, $p_size ) {
2632 2895 if ( $current_p == 1 ) {
2633 2896 return 1;
2634 - } else {
2635 - return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
2636 2897 }
2898 + return self::get_last_record_num( $r_count, $current_p - 1, $p_size ) + 1;
2637 2899 }
2638 2900
2639 2901 /**
2640 2902 * @return array
@@ -2657,9 +2919,9 @@
2657 2919 if ( ! isset( $l3 ) ) {
2658 2920 $l3 = $name;
2659 2921 }
2660 2922
2661 - $this_val = ( $p == $last ) ? $jv['value'] : array();
2923 + $this_val = $p == $last ? $jv['value'] : array();
2662 2924
2663 2925 switch ( $p ) {
2664 2926 case 0:
2665 2927 $l1 = $name;
@@ -2681,12 +2943,12 @@
2681 2943 self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
2682 2944 }
2683 2945
2684 2946 unset( $this_val, $n );
2685 - }
2947 + }//end foreach
2686 2948
2687 2949 unset( $last, $jv );
2688 - }
2950 + }//end foreach
2689 2951
2690 2952 return $vars;
2691 2953 }
2692 2954
@@ -2934,8 +3196,11 @@
2934 3196 }
2935 3197
2936 3198 /**
2937 3199 * @since 4.02.03
3200 + *
3201 + * @param array|string $value
3202 + * @return string
2938 3203 */
2939 3204 public static function maybe_json_encode( $value ) {
2940 3205 if ( is_array( $value ) ) {
2941 3206 $value = wp_json_encode( $value );
@@ -2943,12 +3208,14 @@
2943 3208 return $value;
2944 3209 }
2945 3210
2946 3211 /**
3212 + * Echo The javascript to open and highlight the Formidable menu
3213 + *
2947 3214 * @since 1.07.10
2948 3215 *
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
3216 + * @param string $post_type The name of the post type that may need to be highlighted.
3217 + * @return void
2951 3218 */
2952 3219 public static function maybe_highlight_menu( $post_type ) {
2953 3220 global $post;
2954 3221
@@ -2967,8 +3234,11 @@
2967 3234 /**
2968 3235 * Load the JS file on non-Formidable pages in the admin area
2969 3236 *
2970 3237 * @since 2.0
3238 + *
3239 + * @param bool $load
3240 + * @return void
2971 3241 */
2972 3242 public static function load_admin_wide_js( $load = true ) {
2973 3243 $version = self::plugin_version();
2974 3244 wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
@@ -2982,8 +3252,9 @@
2982 3252 'canAccessApplicationDashboard' => current_user_can( is_callable( 'FrmProApplicationsHelper::get_required_templates_capability' ) ? FrmProApplicationsHelper::get_required_templates_capability() : 'frm_edit_forms' ),
2983 3253 'loading' => __( 'Loading&hellip;', 'formidable' ),
2984 3254 'nonce' => wp_create_nonce( 'frm_ajax' ),
2985 3255 'proIncludesSliderJs' => is_callable( 'FrmProFormsHelper::prepare_custom_currency' ),
3256 + 'inboxSlideIn' => FrmInbox::get_inbox_slide_in_value_for_js(),
2986 3257 );
2987 3258 wp_localize_script( 'formidable_admin_global', 'frmGlobal', $global_strings );
2988 3259
2989 3260 if ( $load ) {
@@ -2992,8 +3263,9 @@
2992 3263 }
2993 3264
2994 3265 /**
2995 3266 * @since 2.0.9
3267 + * @return void
2996 3268 */
2997 3269 public static function load_font_style() {
2998 3270 wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
2999 3271 }
@@ -2999,26 +3271,29 @@
2999 3271 }
3000 3272
3001 3273 /**
3002 3274 * @param string $location
3275 + * @return void
3003 3276 */
3004 3277 public static function localize_script( $location ) {
3005 3278 global $wp_scripts;
3006 3279
3007 3280 $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(),
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,
3021 3296 );
3022 3297
3023 3298 $data = $wp_scripts->get_data( 'formidable', 'data' );
3024 3299 if ( ! $data ) {
@@ -3025,9 +3300,8 @@
3025 3300 wp_localize_script( 'formidable', 'frm_js', $script_strings );
3026 3301 }
3027 3302
3028 3303 if ( $location === 'admin' ) {
3029 - $frm_settings = self::get_settings();
3030 3304 $admin_script_strings = array(
3031 3305 'desc' => __( '(Click to add description)', 'formidable' ),
3032 3306 'blank' => __( '(Blank)', 'formidable' ),
3033 3307 'no_label' => __( '(no label)', 'formidable' ),
@@ -3041,9 +3315,9 @@
3041 3315 'confirm' => __( 'Are you sure?', 'formidable' ),
3042 3316 'conf_delete' => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
3043 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' ),
3044 3318 '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,
3319 + 'default_unique' => FrmFieldsHelper::default_unique_msg(),
3046 3320 'default_conf' => __( 'The entered values do not match', 'formidable' ),
3047 3321 'enter_email' => __( 'Enter Email', 'formidable' ),
3048 3322 'confirm_email' => __( 'Confirm Email', 'formidable' ),
3049 3323 'conditional_text' => __( 'Conditional content here', 'formidable' ),
@@ -3060,9 +3334,11 @@
3060 3334 'no_licenses' => __( 'No new licenses were found', 'formidable' ),
3061 3335 'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3062 3336 'view_shortcodes' => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
3063 3337 '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' ),
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' ),
3065 3341 'unsafe_params' => FrmFormsHelper::reserved_words(),
3066 3342 /* Translators: %s is the name of a Detail Page Slug that is a reserved word.*/
3067 3343 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ),
3068 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. */
@@ -3071,13 +3347,22 @@
3071 3347 'repeat_limit_min' => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
3072 3348 'checkbox_limit' => __( 'Please select a limit between 0 and 200.', 'formidable' ),
3073 3349 'install' => __( 'Install', 'formidable' ),
3074 3350 'active' => __( 'Active', 'formidable' ),
3351 + 'installed' => __( 'Installed', 'formidable' ),
3352 + 'not_installed' => __( 'Not Installed', 'formidable' ),
3075 3353 'select_a_field' => __( 'Select a Field', 'formidable' ),
3076 3354 'no_items_found' => __( 'No items found.', 'formidable' ),
3077 3355 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
3078 - 'saving' => '', // Deprecated in 6.0.
3079 - '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' ),
3080 3365 );
3081 3366 /**
3082 3367 * @param array $admin_script_strings
3083 3368 */
@@ -3086,9 +3371,9 @@
3086 3371 $data = $wp_scripts->get_data( 'formidable_admin', 'data' );
3087 3372 if ( ! $data ) {
3088 3373 wp_localize_script( 'formidable_admin', 'frm_admin_js', $admin_script_strings );
3089 3374 }
3090 - }
3375 + }//end if
3091 3376 }
3092 3377
3093 3378 /**
3094 3379 * @since 6.5
@@ -3132,9 +3417,10 @@
3132 3417 * Echo the message on the plugins listing page
3133 3418 *
3134 3419 * @since 1.07.10
3135 3420 *
3136 - * @param float $min_version The version the add-on requires
3421 + * @param float $min_version The version the add-on requires.
3422 + * @return void
3137 3423 */
3138 3424 public static function min_version_notice( $min_version ) {
3139 3425 $frm_version = self::plugin_version();
3140 3426
@@ -3168,9 +3454,8 @@
3168 3454 if ( ! $is_pro || self::meets_min_pro_version( $min_version ) ) {
3169 3455 return;
3170 3456 }
3171 3457
3172 - $pro_version = FrmProDb::$plug_version;
3173 3458 $expired = FrmAddonsController::is_license_expired();
3174 3459 ?>
3175 3460 <div class="frm-banner-alert frm_error_style frm_previous_install">
3176 3461 <?php
@@ -3188,8 +3473,11 @@
3188 3473 /**
3189 3474 * If Pro is installed, check the version number.
3190 3475 *
3191 3476 * @since 4.0.01
3477 + *
3478 + * @param string $min_version
3479 + * @return bool
3192 3480 */
3193 3481 public static function meets_min_pro_version( $min_version ) {
3194 3482 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
3195 3483 }
@@ -3197,12 +3485,13 @@
3197 3485 /**
3198 3486 * Show a message if the browser or PHP version is below the recommendations.
3199 3487 *
3200 3488 * @since 4.0.02
3489 + * @return void
3201 3490 */
3202 3491 private static function php_version_notice() {
3203 3492 $message = array();
3204 - if ( version_compare( phpversion(), '5.6', '<' ) ) {
3493 + if ( version_compare( phpversion(), '7.0', '<' ) ) {
3205 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' );
3206 3495 }
3207 3496
3208 3497 $browser = self::get_server_value( 'HTTP_USER_AGENT' );
@@ -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,63 @@
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
3989 4327 }
3990 4328 }