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 +473 -1200 6.296.12 View file →
@@ -3,19 +3,23 @@
3 3 die( 'You are not allowed to call this page directly.' );
4 4 }
5 5
6 6 class FrmAppHelper {
7 -
8 7 /**
9 8 * Version of the database we are moving to.
10 9 *
11 10 * @var int
12 11 */
13 - public static $db_version = 104;
12 + public static $db_version = 101;
14 13
15 14 /**
16 - * Used by the API add-on.
15 + * Deprecated.
17 16 *
17 + * @var int
18 + */
19 + public static $pro_db_version = 37;
20 +
21 + /**
18 22 * @var float
19 23 */
20 24 public static $font_version = 7;
21 25
@@ -28,9 +32,9 @@
28 32 * @since 2.0
29 33 *
30 34 * @var string
31 35 */
32 - public static $plug_version = '6.29';
36 + public static $plug_version = '6.12';
33 37
34 38 /**
35 39 * @var bool
36 40 */
@@ -55,9 +59,9 @@
55 59 /**
56 60 * @return string
57 61 */
58 62 public static function plugin_path() {
59 - return dirname( __DIR__, 2 );
63 + return dirname( dirname( __DIR__ ) );
60 64 }
61 65
62 66 /**
63 67 * @return string
@@ -85,9 +89,8 @@
85 89 * Get the name of this site
86 90 * Used for [sitename] shortcode
87 91 *
88 92 * @since 2.0
89 - *
90 93 * @return string
91 94 */
92 95 public static function site_name() {
93 96 return get_option( 'blogname' );
@@ -94,15 +97,13 @@
94 97 }
95 98
96 99 /**
97 100 * @param string $url
98 - *
99 101 * @return string
100 102 */
101 103 public static function make_affiliate_url( $url ) {
102 104 $affiliate_id = self::get_affiliate();
103 -
104 - if ( $affiliate_id ) {
105 + if ( ! empty( $affiliate_id ) ) {
105 106 $url = str_replace( array( 'http://', 'https://' ), '', $url );
106 107 $url = 'http://www.shareasale.com/r.cfm?u=' . absint( $affiliate_id ) . '&b=841990&m=64739&afftrack=plugin&urllink=' . urlencode( $url );
107 108 }
108 109
@@ -117,167 +118,65 @@
117 118 }
118 119
119 120 /**
120 121 * @since 3.04.02
121 - *
122 - * @param array|string $args If a string is passed, it is used for the utm_campaign attribute.
122 + * @param array|string $args
123 123 * @param string $page
124 124 */
125 125 public static function admin_upgrade_link( $args, $page = '' ) {
126 - if ( $page ) {
126 + if ( empty( $page ) ) {
127 + $page = 'https://formidableforms.com/lite-upgrade/';
128 + } else {
127 129 $page = str_replace( 'https://formidableforms.com/', '', $page );
128 130 $page = 'https://formidableforms.com/' . $page;
131 + }
132 +
133 + $anchor = '';
134 + if ( is_array( $args ) ) {
135 + $medium = $args['medium'];
136 + if ( isset( $args['content'] ) ) {
137 + $content = $args['content'];
138 + }
139 + if ( isset( $args['anchor'] ) ) {
140 + $anchor = '#' . $args['anchor'];
141 + }
129 142 } else {
130 - $page = 'https://formidableforms.com/lite-upgrade/';
143 + $medium = $args;
131 144 }
132 145
133 - $args = is_array( $args ) ? self::adjust_legacy_utm_args( $args ) : array( 'campaign' => $args );
134 -
135 146 $query_args = array(
136 - 'utm_source' => 'plugin',
137 - 'utm_medium' => self::get_utm_medium(),
147 + 'utm_source' => 'WordPress',
148 + 'utm_medium' => $medium,
149 + 'utm_campaign' => 'liteplugin',
138 150 );
139 - $query_args = self::maybe_add_utm_license( $query_args );
140 151
141 - if ( isset( $args['campaign'] ) ) {
142 - $query_args['utm_campaign'] = $args['campaign'];
152 + if ( isset( $content ) ) {
153 + $query_args['utm_content'] = $content;
143 154 }
144 155
145 - if ( isset( $args['content'] ) ) {
146 - $query_args['utm_content'] = $args['content'];
147 - }
148 -
149 - if ( isset( $args['param'] ) ) {
156 + if ( is_array( $args ) && isset( $args['param'] ) ) {
150 157 $query_args['f'] = $args['param'];
151 158 }
152 159
153 - if ( ! empty( $args['plan'] ) ) {
160 + if ( is_array( $args ) && ! empty( $args['plan'] ) ) {
154 161 $query_args['plan'] = $args['plan'];
155 162 }
156 163
157 - $link = add_query_arg( $query_args, $page );
158 -
159 - if ( isset( $args['anchor'] ) ) {
160 - $link .= '#' . $args['anchor'];
161 - }
162 -
164 + $link = add_query_arg( $query_args, $page ) . $anchor;
163 165 return self::make_affiliate_url( $link );
164 166 }
165 167
166 168 /**
167 - * If medium is "pro", add an additional utm_license param with their active license type.
168 - *
169 - * @since 6.25.1
170 - *
171 - * @param array $query_args
172 - * @param string $link
173 - *
174 - * @return array
175 - */
176 - private static function maybe_add_utm_license( $query_args, $link = '' ) {
177 - $medium = $query_args['utm_medium'] ?? self::pull_medium_from_link( $link );
178 -
179 - if ( 'pro' === $medium && is_callable( 'FrmProAddonsController::get_readable_license_type' ) ) {
180 - $query_args['utm_license'] = strtolower( FrmProAddonsController::get_readable_license_type() );
181 - }
182 -
183 - return $query_args;
184 - }
185 -
186 - /**
187 - * @since 6.26
188 - *
189 - * @param string $link
190 - *
191 - * @return string
192 - */
193 - private static function pull_medium_from_link( $link ) {
194 - if ( ! $link ) {
195 - return '';
196 - }
197 -
198 - $parsed = parse_url( $link );
199 -
200 - if ( ! is_array( $parsed ) || ! isset( $parsed['query'] ) ) {
201 - return '';
202 - }
203 -
204 - $query_args = wp_parse_args( $parsed['query'] );
205 -
206 - return ! empty( $query_args['utm_medium'] ) ? $query_args['utm_medium'] : '';
207 - }
208 -
209 - /**
210 - * @since 6.25.1
211 - *
212 - * @return string
213 - */
214 - private static function get_utm_medium() {
215 - return self::pro_is_connected() ? 'pro' : 'lite';
216 - }
217 -
218 - /**
219 - * Change campaign from "liteplugin" to what we're currently using for medium.
220 - *
221 - * @since 6.25.1
222 - *
223 - * @param array $args
224 - *
225 - * @return array
226 - */
227 - private static function adjust_legacy_utm_args( $args ) {
228 - if ( isset( $args['medium'] ) ) {
229 - $args['campaign'] = $args['medium'];
230 - unset( $args['medium'] );
231 - }
232 -
233 - return $args;
234 - }
235 -
236 - /**
237 - * @since 6.21
238 - *
239 - * @param string $cta_link
240 - * @param array $utm
241 - */
242 - public static function maybe_add_missing_utm( $cta_link, $utm ) {
243 - $utm = self::adjust_legacy_utm_args( $utm );
244 - $query_args = array();
245 -
246 - if ( ! str_contains( $cta_link, 'utm_source' ) ) {
247 - $query_args['utm_source'] = 'plugin';
248 - }
249 -
250 - if ( ! str_contains( $cta_link, 'utm_medium' ) ) {
251 - $query_args['utm_medium'] = self::get_utm_medium();
252 - }
253 -
254 - if ( ! str_contains( $cta_link, 'utm_campaign' ) && isset( $utm['campaign'] ) ) {
255 - $query_args['utm_campaign'] = $utm['campaign'];
256 - }
257 -
258 - if ( ! str_contains( $cta_link, 'utm_content' ) && isset( $utm['content'] ) ) {
259 - $query_args['utm_content'] = $utm['content'];
260 - }
261 -
262 - $query_args = self::maybe_add_utm_license( $query_args, $cta_link );
263 -
264 - return $query_args ? add_query_arg( $query_args, $cta_link ) : $cta_link;
265 - }
266 -
267 - /**
268 169 * Get the Formidable settings
269 170 *
270 171 * @since 2.0
271 172 *
272 173 * @param array $args - May include the form id when values need translation.
273 - *
274 - * @return FrmSettings
174 + * @return FrmSettings $frm_settings
275 175 */
276 176 public static function get_settings( $args = array() ) {
277 177 global $frm_settings;
278 -
279 - if ( ! $frm_settings ) {
178 + if ( empty( $frm_settings ) ) {
280 179 $frm_settings = new FrmSettings( $args );
281 180 } elseif ( isset( $args['current_form'] ) ) {
282 181 // If the global has already been set, allow strings to be filtered.
283 182 $frm_settings->maybe_filter_for_form( $args );
@@ -289,13 +188,11 @@
289 188 /**
290 189 * @return string
291 190 */
292 191 public static function get_menu_name() {
293 - if ( ! self::pro_is_installed() || FrmAddonsController::is_license_expired() ) {
294 - return 'Formidable';
295 - }
192 + $frm_settings = self::get_settings();
296 193
297 - return self::get_settings()->menu;
194 + return FrmAddonsController::is_license_expired() ? 'Formidable' : $frm_settings->menu;
298 195 }
299 196
300 197 /**
301 198 * Determine if the current branding is set to 'formidable'.
@@ -310,9 +207,9 @@
310 207 return true;
311 208 }
312 209
313 210 $menu_icon = self::get_menu_icon_class();
314 - return str_contains( $menu_icon, 'frm_logo_icon' );
211 + return strpos( $menu_icon, 'frm_logo_icon' ) !== false;
315 212 }
316 213
317 214 /**
318 215 * @since 3.05
@@ -317,9 +214,8 @@
317 214 /**
318 215 * @since 3.05
319 216 *
320 217 * @param array $atts
321 - *
322 218 * @return string
323 219 */
324 220 public static function svg_logo( $atts = array() ) {
325 221 $defaults = array(
@@ -329,14 +225,12 @@
329 225 'orange' => '#f05a24',
330 226 );
331 227 $atts = array_merge( $defaults, $atts );
332 228
333 - // phpcs:disable SlevomatCodingStandard.Files.LineLength.LineTooLong
334 229 return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 599.68 601.37" width="' . esc_attr( $atts['width'] ) . '" height="' . esc_attr( $atts['height'] ) . '">
335 230 <path fill="' . esc_attr( $atts['orange'] ) . '" d="M289.6 384h140v76h-140z"/>
336 231 <path fill="' . esc_attr( $atts['fill'] ) . '" d="M400.2 147h-200c-17 0-30.6 12.2-30.6 29.3V218h260v-71zM397.9 264H169.6v196h75V340H398a32.2 32.2 0 0 0 30.1-21.4 24.3 24.3 0 0 0 1.7-8.7V264zM299.8 601.4A300.3 300.3 0 0 1 0 300.7a299.8 299.8 0 1 1 511.9 212.6 297.4 297.4 0 0 1-212 88zm0-563A262 262 0 0 0 38.3 300.7a261.6 261.6 0 1 0 446.5-185.5 259.5 259.5 0 0 0-185-76.8z"/>
337 232 </svg>';
338 - // phpcs:enable SlevomatCodingStandard.Files.LineLength.LineTooLong
339 233 }
340 234
341 235 /**
342 236 * @since 4.0
@@ -341,13 +235,12 @@
341 235 /**
342 236 * @since 4.0
343 237 *
344 238 * @param array $atts
345 - *
346 239 * @return void
347 240 */
348 241 public static function show_logo( $atts = array() ) {
349 - self::kses_echo( self::svg_logo( $atts ), 'all' );
242 + echo self::kses( self::svg_logo( $atts ), 'all' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
350 243 }
351 244
352 245 /**
353 246 * @since 4.03.02
@@ -362,11 +255,10 @@
362 255 )
363 256 );
364 257
365 258 $new_icon = apply_filters( 'frm_icon', $icon, true );
366 -
367 259 if ( $new_icon !== $icon ) {
368 - if ( str_starts_with( $new_icon, '<svg' ) ) {
260 + if ( strpos( $new_icon, '<svg' ) === 0 ) {
369 261 $icon = str_replace( 'viewBox="0 0 20', 'width="30" height="35" style="color:#929699" viewBox="0 0 20', $new_icon );
370 262 } else {
371 263 // Show nothing if it isn't an SVG.
372 264 $icon = '<div style="height:39px"></div>';
@@ -371,9 +263,9 @@
371 263 // Show nothing if it isn't an SVG.
372 264 $icon = '<div style="height:39px"></div>';
373 265 }
374 266 }
375 - self::kses_echo( $icon, 'all' );
267 + echo self::kses( $icon, 'all' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
376 268 }
377 269
378 270 /**
379 271 * @since 2.02.04
@@ -414,23 +306,14 @@
414 306 }
415 307
416 308 /**
417 309 * @since 4.06
418 - * @since 6.16.2 Added $check_for_settings parameter
419 310 *
420 - * @param bool $check_for_settings
421 - *
422 311 * @return bool
423 312 */
424 - public static function is_form_builder_page( $check_for_settings = true ) {
425 - $action = self::simple_get( 'frm_action', 'sanitize_title' );
426 - $check_actions = array( 'edit', 'duplicate' );
427 -
428 - if ( $check_for_settings ) {
429 - $check_actions[] = 'settings';
430 - }
431 -
432 - return self::is_admin_page( 'formidable' ) && in_array( $action, $check_actions, true );
313 + public static function is_form_builder_page() {
314 + $action = self::simple_get( 'frm_action', 'sanitize_title' );
315 + return self::is_admin_page( 'formidable' ) && ( $action === 'edit' || $action === 'settings' || $action === 'duplicate' );
433 316 }
434 317
435 318 /**
436 319 * @return bool
@@ -435,57 +318,18 @@
435 318 /**
436 319 * @return bool
437 320 */
438 321 public static function is_formidable_admin() {
439 - $page = self::simple_get( 'page', 'sanitize_title' );
440 -
441 - if ( ! $page ) {
442 - return self::is_view_builder_page();
322 + $page = self::simple_get( 'page', 'sanitize_title' );
323 + $is_formidable = strpos( $page, 'formidable' ) !== false;
324 + if ( empty( $page ) ) {
325 + $is_formidable = self::is_view_builder_page();
443 326 }
444 327
445 - return str_contains( $page, 'formidable' );
328 + return $is_formidable;
446 329 }
447 330
448 331 /**
449 - * Checks if is a list page.
450 - *
451 - * @since 6.19
452 - *
453 - * @param string $page The name of the page to check.
454 - *
455 - * @return bool
456 - */
457 - public static function is_admin_list_page( $page = 'formidable' ) {
458 - if ( 'formidable' === $page ) {
459 - return self::on_form_listing_page();
460 - }
461 -
462 - if ( ! self::is_admin_page( $page ) ) {
463 - return false;
464 - }
465 -
466 - if ( 'formidable-entries' === $page ) {
467 - $action = self::simple_get( 'frm_action' );
468 -
469 - if ( ! $action || in_array( $action, self::get_entries_listing_page_form_actions(), true ) ) {
470 - return true;
471 - }
472 - }
473 -
474 - // Check edit or settings page.
475 - return ! self::simple_get( 'frm_action' );
476 - }
477 -
478 - /**
479 - * @since 6.20
480 - *
481 - * @return array<string>
482 - */
483 - private static function get_entries_listing_page_form_actions() {
484 - return array( 'list', 'destroy' );
485 - }
486 -
487 - /**
488 332 * Check for certain page in Formidable settings
489 333 *
490 334 * @since 2.0
491 335 *
@@ -495,13 +339,11 @@
495 339 */
496 340 public static function is_admin_page( $page = 'formidable' ) {
497 341 global $pagenow;
498 342 $get_page = self::simple_get( 'page', 'sanitize_title' );
499 -
500 343 if ( $pagenow ) {
501 - // Allow this to be true during ajax load i.e. ajax form builder loading
344 + // allow this to be true during ajax load i.e. ajax form builder loading
502 345 $is_page = ( $pagenow === 'admin.php' || $pagenow === 'admin-ajax.php' ) && $get_page === $page;
503 -
504 346 if ( $is_page ) {
505 347 return true;
506 348 }
507 349 }
@@ -519,15 +361,15 @@
519 361 */
520 362 public static function is_view_builder_page() {
521 363 global $pagenow;
522 364
523 - if ( ! in_array( $pagenow, array( 'post.php', 'post-new.php', 'edit.php' ), true ) ) {
365 + if ( $pagenow !== 'post.php' && $pagenow !== 'post-new.php' && $pagenow !== 'edit.php' ) {
524 366 return false;
525 367 }
526 368
527 369 $post_type = self::simple_get( 'post_type', 'sanitize_title' );
528 370
529 - if ( ! $post_type ) {
371 + if ( empty( $post_type ) ) {
530 372 $post_id = self::simple_get( 'post', 'absint' );
531 373 $post = get_post( $post_id );
532 374 $post_type = $post ? $post->post_type : '';
533 375 }
@@ -545,9 +387,9 @@
545 387 public static function is_preview_page() {
546 388 global $pagenow;
547 389 $action = self::simple_get( 'action', 'sanitize_title' );
548 390
549 - return $pagenow === 'admin-ajax.php' && $action === 'frm_forms_preview';
391 + return $pagenow && $pagenow === 'admin-ajax.php' && $action === 'frm_forms_preview';
550 392 }
551 393
552 394 /**
553 395 * Check for ajax except the form preview page
@@ -568,9 +410,8 @@
568 410 }
569 411
570 412 /**
571 413 * @since 2.0.8
572 - *
573 414 * @return bool
574 415 */
575 416 public static function prevent_caching() {
576 417 global $frm_vars;
@@ -588,9 +429,8 @@
588 429 $is_admin = is_admin() && ! wp_doing_ajax();
589 430
590 431 /**
591 432 * @since 6.0
592 - *
593 433 * @param bool $is_admin
594 434 */
595 435 return apply_filters( 'frm_is_admin', $is_admin );
596 436 }
@@ -605,15 +445,14 @@
605 445 *
606 446 * @return bool
607 447 */
608 448 public static function is_empty_value( $value, $empty = '' ) {
609 - return $value === array() || $value === $empty;
449 + return ( is_array( $value ) && empty( $value ) ) || $value === $empty;
610 450 }
611 451
612 452 /**
613 453 * @param mixed $value
614 454 * @param string $empty
615 - *
616 455 * @return bool
617 456 */
618 457 public static function is_not_empty_value( $value, $empty = '' ) {
619 458 return ! self::is_empty_value( $value, $empty );
@@ -667,9 +506,8 @@
667 506 continue;
668 507 }
669 508
670 509 $key = self::get_server_value( $key );
671 -
672 510 foreach ( explode( ',', $key ) as $ip ) {
673 511 // Just to be safe.
674 512 $ip = trim( $ip );
675 513
@@ -725,26 +563,16 @@
725 563 */
726 564 return apply_filters( 'frm_use_custom_header_ip', $should_use_custom_header_ip );
727 565 }
728 566
729 - /**
730 - * @param string $param
731 - * @param mixed $default
732 - * @param string $src
733 - * @param callable|string $sanitize
734 - *
735 - * @return mixed
736 - */
737 567 public static function get_param( $param, $default = '', $src = 'get', $sanitize = '' ) {
738 - if ( str_contains( $param, '[' ) ) {
568 + if ( strpos( $param, '[' ) ) {
739 569 $params = explode( '[', $param );
740 570 $param = $params[0];
741 571 }
742 572
743 573 if ( $src === 'get' ) {
744 - // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
745 - $value = isset( $_POST[ $param ] ) ? wp_unslash( $_POST[ $param ] ) : ( isset( $_GET[ $param ] ) ? wp_unslash( $_GET[ $param ] ) : $default );
746 -
574 + $value = isset( $_POST[ $param ] ) ? wp_unslash( $_POST[ $param ] ) : ( isset( $_GET[ $param ] ) ? wp_unslash( $_GET[ $param ] ) : $default ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
747 575 if ( ! isset( $_POST[ $param ] ) && isset( $_GET[ $param ] ) && ! is_array( $value ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
748 576 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
749 577 $value = htmlspecialchars_decode( wp_unslash( $_GET[ $param ] ) );
750 578 }
@@ -759,19 +587,17 @@
759 587 )
760 588 );
761 589 }
762 590
763 - if ( ! isset( $params ) || ! is_array( $value ) || ! $value ) {
764 - return $value;
765 - }
591 + if ( isset( $params ) && is_array( $value ) && ! empty( $value ) ) {
592 + foreach ( $params as $k => $p ) {
593 + if ( ! $k || ! is_array( $value ) ) {
594 + continue;
595 + }
766 596
767 - foreach ( $params as $k => $p ) {
768 - if ( ! $k || ! is_array( $value ) ) {
769 - continue;
597 + $p = trim( $p, ']' );
598 + $value = isset( $value[ $p ] ) ? $value[ $p ] : $default;
770 599 }
771 -
772 - $p = trim( $p, ']' );
773 - $value = $value[ $p ] ?? $default;
774 600 }
775 601
776 602 return $value;
777 603 }
@@ -782,9 +608,8 @@
782 608 * @param string $param The key we are trying to access data from in $_POST.
783 609 * @param mixed $default The default if nothing is being sent.
784 610 * @param callable|string $sanitize Make sure to pass a sanitize method here. This function will NOT sanitize by default.
785 611 * @param bool $serialized
786 - *
787 612 * @return mixed
788 613 */
789 614 public static function get_post_param( $param, $default = '', $sanitize = '', $serialized = false ) {
790 615 return self::get_simple_request(
@@ -804,9 +629,9 @@
804 629 * @param string $param
805 630 * @param string $sanitize
806 631 * @param string $default
807 632 *
808 - * @return array|int|string
633 + * @return array|string
809 634 */
810 635 public static function simple_get( $param, $sanitize = 'sanitize_text_field', $default = '' ) {
811 636 return self::get_simple_request(
812 637 array(
@@ -835,10 +660,10 @@
835 660 'sanitize' => 'sanitize_text_field',
836 661 'serialized' => false,
837 662 );
838 663 $args = wp_parse_args( $args, $defaults );
839 - $value = $args['default'];
840 664
665 + $value = $args['default'];
841 666 if ( $args['type'] === 'get' ) {
842 667 if ( $_GET && isset( $_GET[ $args['param'] ] ) ) {
843 668 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
844 669 $value = wp_unslash( $_GET[ $args['param'] ] );
@@ -846,16 +671,16 @@
846 671 } elseif ( $args['type'] === 'post' ) {
847 672 if ( isset( $_POST[ $args['param'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
848 673 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
849 674 $value = wp_unslash( $_POST[ $args['param'] ] );
850 -
851 675 if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
852 676 self::unserialize_or_decode( $value );
853 677 }
854 678 }
855 679 } elseif ( isset( $_REQUEST[ $args['param'] ] ) ) {
856 - // phpcs:ignore phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
857 - $value = wp_unslash( $_REQUEST[ $args['param'] ] );
680 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
681 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
682 + $value = wp_unslash( $_REQUEST[ $args['param'] ] );
858 683 }
859 684
860 685 self::sanitize_value( $args['sanitize'], $value );
861 686
@@ -868,13 +693,17 @@
868 693 * @since 2.0.8
869 694 *
870 695 * @param string $value
871 696 *
872 - * @return string Value.
697 + * @return string $value
873 698 */
874 699 public static function preserve_backslashes( $value ) {
875 700 // If backslashes have already been added, don't add them again
876 - return str_contains( $value, '\\\\' ) ? $value : addslashes( $value );
701 + if ( strpos( $value, '\\\\' ) === false ) {
702 + $value = addslashes( $value );
703 + }
704 +
705 + return $value;
877 706 }
878 707
879 708 /**
880 709 * Sanitize a value in-place.
@@ -881,9 +710,8 @@
881 710 * If $value is an array, the sanitize function will get called for each item.
882 711 *
883 712 * @param callable $sanitize
884 713 * @param mixed $value
885 - *
886 714 * @return void
887 715 */
888 716 public static function sanitize_value( $sanitize, &$value ) {
889 717 if ( ! $sanitize ) {
@@ -896,13 +724,11 @@
896 724 }
897 725
898 726 if ( is_array( $value ) ) {
899 727 $temp_values = $value;
900 -
901 728 foreach ( $temp_values as $k => $v ) {
902 729 self::sanitize_value( $sanitize, $value[ $k ] );
903 730 }
904 -
905 731 return;
906 732 }
907 733
908 734 $value = call_user_func( $sanitize, $value );
@@ -907,17 +733,10 @@
907 733
908 734 $value = call_user_func( $sanitize, $value );
909 735 }
910 736
911 - /**
912 - * @param array $sanitize_method
913 - * @param array $values
914 - *
915 - * @return void
916 - */
917 737 public static function sanitize_request( $sanitize_method, &$values ) {
918 738 $temp_values = $values;
919 -
920 739 foreach ( $temp_values as $k => $val ) {
921 740 if ( isset( $sanitize_method[ $k ] ) ) {
922 741 $values[ $k ] = call_user_func( $sanitize_method[ $k ], $val );
923 742 }
@@ -927,9 +746,8 @@
927 746 /**
928 747 * @since 4.0.04
929 748 *
930 749 * @param mixed $value
931 - *
932 750 * @return void
933 751 */
934 752 public static function sanitize_with_html( &$value ) {
935 753 if ( current_user_can( 'frm_edit_entries' ) || current_user_can( 'administrator' ) ) {
@@ -948,12 +766,8 @@
948 766 *
949 767 * @param string $value
950 768 */
951 769 public static function strip_most_html( $value ) {
952 - if ( '' === $value ) {
953 - return $value;
954 - }
955 -
956 770 $allowed_html = array(
957 771 'b' => array(),
958 772 'br' => array(),
959 773 'strong' => array(),
@@ -978,15 +792,12 @@
978 792 * Do wp_specialchars_decode to get back '&' that wp_kses_post might have turned to '&amp;'
979 793 * this MUST be done, else we'll be back to the '& entity' problem.
980 794 *
981 795 * @since 4.0.04
982 - *
983 - * @param mixed $value Value to decode, passed by reference.
984 796 */
985 797 public static function decode_specialchars( &$value ) {
986 798 if ( is_array( $value ) ) {
987 799 $temp_values = $value;
988 -
989 800 foreach ( $temp_values as $k => $v ) {
990 801 self::decode_specialchars( $value[ $k ] );
991 802 }
992 803 } else {
@@ -1000,13 +811,13 @@
1000 811 * Adapted from wp_specialchars_decode().
1001 812 *
1002 813 * @since 4.03.01
1003 814 *
1004 - * @param string $string The string to prep, passed by reference.
815 + * @param string $string The string to prep.
1005 816 */
1006 817 private static function decode_amp( &$string ) {
1007 818 // Don't bother if there are no entities - saves a lot of processing
1008 - if ( ! $string || ! str_contains( $string, '&' ) ) {
819 + if ( empty( $string ) || strpos( $string, '&' ) === false ) {
1009 820 return;
1010 821 }
1011 822
1012 823 $translation = array(
@@ -1044,53 +855,38 @@
1044 855 * Sanitize the value, and allow some HTML
1045 856 *
1046 857 * @since 2.0
1047 858 *
1048 - * @param string $value The value to sanitize.
1049 - * @param array|string $allowed Allowed HTML tags and attributes, or 'all' for defaults.
859 + * @param string $value
860 + * @param array|string $allowed 'all' for everything included as defaults.
1050 861 *
1051 862 * @return string
1052 863 */
1053 864 public static function kses( $value, $allowed = array() ) {
1054 865 $allowed_html = self::allowed_html( $allowed );
866 +
1055 867 return wp_kses( $value, $allowed_html );
1056 868 }
1057 869
1058 870 /**
1059 - * Sanitizes and echoes a given value.
1060 - *
1061 - * @since 6.18
1062 - *
1063 - * @param string $value The value to sanitize and output.
1064 - * @param array|string $allowed Allowed HTML tags and attributes.
1065 - *
1066 - * @return void
1067 - */
1068 - public static function kses_echo( $value, $allowed = array() ) {
1069 - echo self::kses( $value, $allowed ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1070 - }
1071 -
1072 - /**
1073 871 * The regular kses function strips [button_action] from submit button HTML.
1074 872 *
1075 873 * @since 5.0.13
1076 874 *
1077 875 * @param string $html
1078 - *
1079 876 * @return string
1080 877 */
1081 878 public static function kses_submit_button( $html ) {
1082 - $included_button_action = str_contains( $html, '[button_action]' );
1083 - $included_back_hook = str_contains( $html, '[back_hook]' );
1084 - $included_draft_hook = str_contains( $html, '[draft_hook]' );
879 + $included_button_action = false !== strpos( $html, '[button_action]' );
880 + $included_back_hook = false !== strpos( $html, '[back_hook]' );
881 + $included_draft_hook = false !== strpos( $html, '[draft_hook]' );
1085 882 add_filter( 'safe_style_css', 'FrmAppHelper::allow_visibility_style' );
1086 883 add_filter( 'frm_striphtml_allowed_tags', 'FrmAppHelper::add_allowed_submit_button_tags' );
1087 884 $html = self::kses( $html, 'all' );
1088 885 remove_filter( 'safe_style_css', 'FrmAppHelper::allow_visibility_style' );
1089 886 remove_filter( 'frm_striphtml_allowed_tags', 'FrmAppHelper::add_allowed_submit_button_tags' );
1090 -
1091 887 if ( $included_button_action ) {
1092 - if ( str_contains( $html, '<input type="submit"' ) ) {
888 + if ( false !== strpos( $html, '<input type="submit"' ) ) {
1093 889 $pattern = '/(<input type="submit")([^>]*)(\/>)/';
1094 890 $html = preg_replace( $pattern, '$1$2[button_action] $3', $html, 1 );
1095 891 } else {
1096 892 $pattern = '/(<button)(.*)(class=")(.*)(frm_button_submit)(.*)(")(.*)([^>]+)(>)/';
@@ -1096,17 +892,14 @@
1096 892 $pattern = '/(<button)(.*)(class=")(.*)(frm_button_submit)(.*)(")(.*)([^>]+)(>)/';
1097 893 $html = preg_replace( $pattern, '$1$2$3$4$5$6$7 [button_action]$8$9$10', $html, 1 );
1098 894 }
1099 895 }
1100 -
1101 896 if ( $included_back_hook ) {
1102 897 $html = str_replace( 'class="frm_prev_page"', 'class="frm_prev_page" [back_hook]', $html );
1103 898 }
1104 -
1105 899 if ( $included_draft_hook ) {
1106 - return str_replace( 'class="frm_save_draft"', 'class="frm_save_draft" [draft_hook]', $html );
900 + $html = str_replace( 'class="frm_save_draft"', 'class="frm_save_draft" [draft_hook]', $html );
1107 901 }
1108 -
1109 902 return $html;
1110 903 }
1111 904
1112 905 /**
@@ -1112,9 +905,8 @@
1112 905 /**
1113 906 * @since 5.0.13
1114 907 *
1115 908 * @param array $allowed_attr
1116 - *
1117 909 * @return array
1118 910 */
1119 911 public static function allow_visibility_style( $allowed_attr ) {
1120 912 $allowed_attr[] = 'visibility';
@@ -1124,9 +916,8 @@
1124 916 /**
1125 917 * @since 5.0.13
1126 918 *
1127 919 * @param array $allowed_html
1128 - *
1129 920 * @return array
1130 921 */
1131 922 public static function add_allowed_submit_button_tags( $allowed_html ) {
1132 923 $allowed_html['input'] = array(
@@ -1143,22 +934,17 @@
1143 934 }
1144 935
1145 936 /**
1146 937 * @since 2.05.03
1147 - *
1148 - * @param array|string $allowed
1149 - *
1150 - * @return array
1151 938 */
1152 939 private static function allowed_html( $allowed ) {
1153 940 $html = self::safe_html();
1154 941 $allowed_html = array();
1155 -
1156 942 if ( $allowed === 'all' ) {
1157 943 $allowed_html = $html;
1158 - } elseif ( $allowed ) {
944 + } elseif ( ! empty( $allowed ) ) {
1159 945 foreach ( (array) $allowed as $a ) {
1160 - $allowed_html[ $a ] = $html[ $a ] ?? array();
946 + $allowed_html[ $a ] = isset( $html[ $a ] ) ? $html[ $a ] : array();
1161 947 }
1162 948 }
1163 949
1164 950 return apply_filters( 'frm_striphtml_allowed_tags', $allowed_html );
@@ -1165,10 +951,8 @@
1165 951 }
1166 952
1167 953 /**
1168 954 * @since 2.05.03
1169 - *
1170 - * @return array
1171 955 */
1172 956 private static function safe_html() {
1173 957 $allow_class = array(
1174 958 'class' => true,
@@ -1301,13 +1085,8 @@
1301 1085 ),
1302 1086 'legend' => array(
1303 1087 'class' => true,
1304 1088 ),
1305 - 'option' => array(
1306 - 'class' => true,
1307 - 'value' => true,
1308 - 'selected' => true,
1309 - ),
1310 1089 );
1311 1090 }
1312 1091
1313 1092 /**
@@ -1320,16 +1099,14 @@
1320 1099 return;
1321 1100 }
1322 1101
1323 1102 $action_name = isset( $_GET['action'] ) ? 'action' : ( isset( $_GET['action2'] ) ? 'action2' : '' );
1324 -
1325 - if ( ! $action_name ) {
1103 + if ( empty( $action_name ) ) {
1326 1104 return;
1327 1105 }
1328 1106
1329 1107 $new_action = self::get_param( $action_name, '', 'get', 'sanitize_text_field' );
1330 -
1331 - if ( $new_action ) {
1108 + if ( ! empty( $new_action ) ) {
1332 1109 $_SERVER['REQUEST_URI'] = str_replace( '&action=' . $new_action, '', self::get_server_value( 'REQUEST_URI' ) );
1333 1110 }
1334 1111 }
1335 1112
@@ -1336,23 +1113,21 @@
1336 1113 /**
1337 1114 * Check the WP query for a parameter
1338 1115 *
1339 1116 * @since 2.0
1340 - *
1341 - * @param array|string $value
1342 - * @param string $param
1343 - *
1344 1117 * @return array|string
1345 1118 */
1346 1119 public static function get_query_var( $value, $param ) {
1347 - // phpcs:ignore Universal.Operators.StrictComparisons
1348 1120 if ( $value != '' ) {
1349 1121 return $value;
1350 1122 }
1351 1123
1352 1124 global $wp_query;
1125 + if ( isset( $wp_query->query_vars[ $param ] ) ) {
1126 + $value = $wp_query->query_vars[ $param ];
1127 + }
1353 1128
1354 - return $wp_query->query_vars[ $param ] ?? $value;
1129 + return $value;
1355 1130 }
1356 1131
1357 1132 /**
1358 1133 * Try to show the SVG if possible. Otherwise, use the font icon.
@@ -1360,21 +1135,20 @@
1360 1135 * @since 4.0.02
1361 1136 *
1362 1137 * @param string $class
1363 1138 * @param array $atts
1364 - *
1365 1139 * @return string|null
1366 1140 */
1367 1141 public static function icon_by_class( $class, $atts = array() ) {
1368 1142 $echo = ! isset( $atts['echo'] ) || $atts['echo'];
1369 -
1370 1143 if ( isset( $atts['echo'] ) ) {
1371 1144 unset( $atts['echo'] );
1372 1145 }
1373 1146
1374 1147 $html_atts = self::array_to_html_params( $atts );
1375 - $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
1376 1148
1149 + $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
1150 +
1377 1151 // Replace icons that have been removed or renamed.
1378 1152 $deprecated = array(
1379 1153 'frm_clone_solid_icon' => 'frm_clone_icon',
1380 1154 'frm_keyalt_icon' => 'frm_key_icon',
@@ -1379,9 +1153,8 @@
1379 1153 'frm_clone_solid_icon' => 'frm_clone_icon',
1380 1154 'frm_keyalt_icon' => 'frm_key_icon',
1381 1155 'frm_keyalt_solid_icon' => 'frm_key_solid_icon',
1382 1156 );
1383 -
1384 1157 if ( isset( $deprecated[ $icon ] ) ) {
1385 1158 $icon = $deprecated[ $icon ];
1386 1159 $class = str_replace( $icon, $deprecated[ $icon ], $class );
1387 1160 }
@@ -1388,24 +1161,21 @@
1388 1161
1389 1162 if ( $icon === $class ) {
1390 1163 $icon = '<i class="' . esc_attr( $class ) . '"' . $html_atts . '></i>';
1391 1164 } else {
1392 - $class = str_contains( $icon, ' ' ) ? ' ' . $icon : '';
1393 -
1394 - if ( str_contains( $icon, ' ' ) ) {
1165 + $class = strpos( $icon, ' ' ) === false ? '' : ' ' . $icon;
1166 + if ( strpos( $icon, ' ' ) ) {
1395 1167 $icon = explode( ' ', $icon );
1396 1168 $icon = reset( $icon );
1397 1169 }
1398 -
1399 - $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use href="#' . esc_attr( $icon ) . '" /></svg>';
1170 + $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use xlink:href="#' . esc_attr( $icon ) . '" /></svg>';
1400 1171 }
1401 1172
1402 1173 if ( $echo ) {
1403 1174 echo self::kses_icon( $icon ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1404 - return null;
1175 + } else {
1176 + return $icon;
1405 1177 }
1406 -
1407 - return $icon;
1408 1178 }
1409 1179
1410 1180 /**
1411 1181 * Run kses for icons. It needs to add a few filters first in order to preserve some custom style values.
@@ -1412,9 +1182,8 @@
1412 1182 *
1413 1183 * @since 5.0.13
1414 1184 *
1415 1185 * @param string $icon
1416 - *
1417 1186 * @return string
1418 1187 */
1419 1188 public static function kses_icon( $icon ) {
1420 1189 add_filter( 'safe_style_css', 'FrmAppHelper::allow_vars_in_styles' );
@@ -1430,15 +1199,13 @@
1430 1199 /**
1431 1200 * @since 5.0.13.1
1432 1201 *
1433 1202 * @param array $allowed_html
1434 - *
1435 1203 * @return array
1436 1204 */
1437 1205 public static function add_allowed_icon_tags( $allowed_html ) {
1438 1206 $allowed_html['svg']['data-open'] = true;
1439 1207 $allowed_html['svg']['title'] = true;
1440 - $allowed_html['svg']['tabindex'] = true;
1441 1208 return $allowed_html;
1442 1209 }
1443 1210
1444 1211 /**
@@ -1444,9 +1211,8 @@
1444 1211 /**
1445 1212 * @since 5.0.13
1446 1213 *
1447 1214 * @param array $allowed_attr
1448 - *
1449 1215 * @return array
1450 1216 */
1451 1217 public static function allow_vars_in_styles( $allowed_attr ) {
1452 1218 $allowed_attr[] = '--primary-700';
@@ -1459,9 +1225,9 @@
1459 1225 * @param bool $allow_css
1460 1226 * @param string $css_string
1461 1227 */
1462 1228 public static function allow_style( $allow_css, $css_string ) {
1463 - if ( ! $allow_css && str_starts_with( $css_string, '--primary-700:' ) ) {
1229 + if ( ! $allow_css && 0 === strpos( $css_string, '--primary-700:' ) ) {
1464 1230 $split = explode( ':', $css_string, 2 );
1465 1231 $allow_css = 2 === count( $split ) && self::is_a_valid_color( $split[1] );
1466 1232 }
1467 1233 return $allow_css;
@@ -1470,22 +1236,19 @@
1470 1236 /**
1471 1237 * @since 5.0.13
1472 1238 *
1473 1239 * @param string $value
1474 - *
1475 1240 * @return bool
1476 1241 */
1477 1242 private static function is_a_valid_color( $value ) {
1478 1243 $match = 0;
1479 -
1480 - if ( str_starts_with( $value, 'rgba(' ) ) {
1244 + if ( 0 === strpos( $value, 'rgba(' ) ) {
1481 1245 $match = preg_match( '/^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*(?:\.\d+)?)\)$/', $value );
1482 - } elseif ( str_starts_with( $value, 'rgb(' ) ) {
1246 + } elseif ( 0 === strpos( $value, 'rgb(' ) ) {
1483 1247 $match = preg_match( '/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/', $value );
1484 - } elseif ( str_starts_with( $value, '#' ) ) {
1248 + } elseif ( 0 === strpos( $value, '#' ) ) {
1485 1249 $match = preg_match( '/^#([a-f0-9]{6}|[a-f0-9]{3})\b$/', $value );
1486 1250 }
1487 -
1488 1251 return (bool) $match;
1489 1252 }
1490 1253
1491 1254 /**
@@ -1491,9 +1254,8 @@
1491 1254 /**
1492 1255 * Include svg images.
1493 1256 *
1494 1257 * @since 4.0.02
1495 - *
1496 1258 * @return void
1497 1259 */
1498 1260 public static function include_svg() {
1499 1261 if ( self::$included_svg ) {
@@ -1512,20 +1274,17 @@
1512 1274 * @since 5.0.13 added $echo parameter.
1513 1275 *
1514 1276 * @param array $atts
1515 1277 * @param bool $echo
1516 - *
1517 1278 * @return string|void
1518 1279 */
1519 1280 public static function array_to_html_params( $atts, $echo = false ) {
1520 1281 $callback = function () use ( $atts ) {
1521 - if ( ! $atts ) {
1522 - return;
1282 + if ( $atts ) {
1283 + foreach ( $atts as $key => $value ) {
1284 + echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
1285 + }
1523 1286 }
1524 -
1525 - foreach ( $atts as $key => $value ) {
1526 - echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
1527 - }
1528 1287 };
1529 1288 return self::clip( $callback, $echo );
1530 1289 }
1531 1290
@@ -1535,9 +1294,8 @@
1535 1294 * @since 5.0.13
1536 1295 *
1537 1296 * @param Closure $echo_function
1538 1297 * @param bool $echo
1539 - *
1540 1298 * @return string|null
1541 1299 */
1542 1300 public static function clip( $echo_function, $echo = false ) {
1543 1301 if ( ! $echo ) {
@@ -1547,9 +1305,13 @@
1547 1305 if ( is_callable( $echo_function ) ) {
1548 1306 $echo_function();
1549 1307 }
1550 1308
1551 - return $echo ? null : ob_get_clean();
1309 + if ( ! $echo ) {
1310 + $return = ob_get_contents();
1311 + ob_end_clean();
1312 + return $return;
1313 + }
1552 1314 }
1553 1315
1554 1316 /**
1555 1317 * @since 3.0
@@ -1554,18 +1316,15 @@
1554 1316 /**
1555 1317 * @since 3.0
1556 1318 *
1557 1319 * @param array $atts
1558 - *
1559 1320 * @return void
1560 1321 */
1561 1322 public static function get_admin_header( $atts ) {
1562 1323 $has_nav = ! empty( $atts['form'] ) && empty( $atts['is_template'] );
1563 -
1564 1324 if ( empty( $atts['close'] ) ) {
1565 1325 $atts['close'] = admin_url( 'admin.php?page=formidable' );
1566 1326 }
1567 -
1568 1327 if ( ! isset( $atts['import_link'] ) ) {
1569 1328 $atts['import_link'] = false;
1570 1329 }
1571 1330
@@ -1575,19 +1334,16 @@
1575 1334 /**
1576 1335 * @since 6.0
1577 1336 *
1578 1337 * @param string $type
1579 - *
1580 1338 * @return void
1581 1339 */
1582 1340 public static function import_link( $type = 'secondary' ) {
1583 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
1584 1341 ?>
1585 1342 <a href="<?php echo esc_url( admin_url( 'admin.php?page=formidable-import' ) ); ?>" class="button frm-button-<?php echo esc_attr( $type ); ?> frm_animate_bg">
1586 1343 <?php esc_html_e( 'Import', 'formidable' ); ?>
1587 1344 </a>
1588 1345 <?php
1589 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
1590 1346 }
1591 1347
1592 1348 /**
1593 1349 * Print applicable admin banner.
@@ -1594,9 +1350,8 @@
1594 1350 *
1595 1351 * @since 5.4.2
1596 1352 *
1597 1353 * @param bool $should_show_lite_upgrade
1598 - *
1599 1354 * @return void
1600 1355 */
1601 1356 public static function print_admin_banner( $should_show_lite_upgrade ) {
1602 1357 if ( ! current_user_can( 'administrator' ) ) {
@@ -1603,44 +1358,25 @@
1603 1358 FrmInbox::maybe_show_banner();
1604 1359 return;
1605 1360 }
1606 1361
1607 - if ( FrmSalesApi::maybe_show_banner() || self::maybe_show_license_warning() || FrmInbox::maybe_show_banner() || ! $should_show_lite_upgrade || self::pro_is_installed() ) {
1362 + if ( self::maybe_show_license_warning() || FrmInbox::maybe_show_banner() || ! $should_show_lite_upgrade || self::pro_is_installed() ) {
1608 1363 // Print license warning or inbox banner and exit if either prints.
1609 1364 // And exit before printing the upgrade bar if it shouldn't be shown.
1610 1365 return;
1611 1366 }
1612 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
1613 1367 ?>
1614 1368 <div class="frm-upgrade-bar">
1615 - <div class="frm-upgrade-bar-inner">
1616 1369 <?php
1617 - $cta_text = FrmSalesApi::get_best_sale_value( 'lite_banner_cta_text' );
1618 -
1619 - if ( ! $cta_text ) {
1620 - $cta_text = __( 'upgrading to PRO', 'formidable' );
1621 - }
1622 -
1623 - $upgrade_link = FrmSalesApi::get_best_sale_value( 'lite_banner_cta_link' );
1624 - $utm = array(
1625 - 'campaign' => 'settings-license',
1626 - 'content' => 'lite-banner',
1627 - );
1628 -
1629 - $upgrade_link = $upgrade_link ? self::maybe_add_missing_utm( $upgrade_link, $utm ) : self::admin_upgrade_link( $utm );
1630 -
1631 1370 printf(
1632 - /* translators: %1$s: Start link HTML, %2$s: CTA text ("upgrading to PRO" by default), %3$s: End link HTML */
1633 - esc_html__( 'You\'re using Formidable Forms Lite. To unlock more features consider %1$s%2$s%3$s.', 'formidable' ),
1634 - '<a href="' . esc_url( $upgrade_link ) . '">',
1635 - esc_html( $cta_text ),
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' ) ) . '">',
1636 1374 '</a>'
1637 1375 );
1638 1376 ?>
1639 - </div>
1640 1377 </div>
1641 1378 <?php
1642 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
1643 1379 }
1644 1380
1645 1381 /**
1646 1382 * @since 5.4.2
@@ -1654,9 +1390,8 @@
1654 1390 /**
1655 1391 * Render a button for a new item (Form, Application, etc).
1656 1392 *
1657 1393 * @since 3.0
1658 - *
1659 1394 * @param array $atts {
1660 1395 * Details about the button.
1661 1396 *
1662 1397 * @type array $link_hook Custom link hook, calls do_action and exits early.
@@ -1663,9 +1398,8 @@
1663 1398 * @type string $new_link Href value, default #.
1664 1399 * @type string $class Custom class names, space separated.
1665 1400 * @type string $button_text Button text. Default "Add New".
1666 1401 * }
1667 - *
1668 1402 * @return void
1669 1403 */
1670 1404 public static function add_new_item_link( $atts ) {
1671 1405 if ( isset( $atts['link_hook'] ) ) {
@@ -1691,12 +1425,8 @@
1691 1425 }
1692 1426
1693 1427 /**
1694 1428 * @since 3.06
1695 - *
1696 - * @param array $atts
1697 - *
1698 - * @return void
1699 1429 */
1700 1430 public static function show_search_box( $atts ) {
1701 1431 $defaults = array(
1702 1432 'placeholder' => '',
@@ -1703,9 +1433,8 @@
1703 1433 'tosearch' => '',
1704 1434 'text' => __( 'Search', 'formidable' ),
1705 1435 'input_id' => '',
1706 1436 'value' => false,
1707 - 'class' => '',
1708 1437 );
1709 1438 $atts = array_merge( $defaults, $atts );
1710 1439
1711 1440 if ( $atts['input_id'] === 'template' && empty( $atts['tosearch'] ) ) {
@@ -1712,9 +1441,8 @@
1712 1441 $atts['tosearch'] = 'frm-card';
1713 1442 }
1714 1443
1715 1444 $class = 'frm-search-input';
1716 -
1717 1445 if ( ! empty( $atts['tosearch'] ) ) {
1718 1446 $class .= ' frm-auto-search';
1719 1447 }
1720 1448
@@ -1738,15 +1466,14 @@
1738 1466
1739 1467 if ( ! empty( $atts['tosearch'] ) ) {
1740 1468 $input_atts['autocomplete'] = 'off';
1741 1469 }
1742 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
1743 1470 ?>
1744 - <p class="frm-search <?php echo esc_attr( $atts['class'] ); ?>">
1471 + <p class="frm-search">
1745 1472 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
1746 1473 <?php echo esc_html( $atts['text'] ); ?>:
1747 1474 </label>
1748 - <?php self::icon_by_class( 'frmfont frm_search_icon frm_svg20' ); ?>
1475 + <span class="frmfont frm_search_icon"></span>
1749 1476 <input <?php self::array_to_html_params( $input_atts, true ); ?> />
1750 1477 <?php
1751 1478 if ( empty( $atts['tosearch'] ) ) {
1752 1479 submit_button( $atts['text'], 'button-secondary', '', false, array( 'id' => 'search-submit' ) );
@@ -1753,21 +1480,17 @@
1753 1480 }
1754 1481 ?>
1755 1482 </p>
1756 1483 <?php
1757 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
1758 1484 }
1759 1485
1760 1486 /**
1761 - * @param string $type Hook type slug.
1762 - * @param object|null $object Optional related object.
1763 - *
1487 + * @param string $type
1764 1488 * @return void
1765 1489 */
1766 1490 public static function trigger_hook_load( $type, $object = null ) {
1767 1491 // Only load the form hooks once.
1768 1492 $hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
1769 -
1770 1493 if ( ! $hooks_loaded ) {
1771 1494 do_action( 'frm_load_' . $type . '_hooks' );
1772 1495 }
1773 1496 }
@@ -1826,14 +1549,14 @@
1826 1549 * True when value is 1, true, 'true', 'yes'
1827 1550 *
1828 1551 * @since 1.07.10
1829 1552 *
1830 - * @param bool|int|string $value The value to compare.
1553 + * @param string $value The value to compare.
1831 1554 *
1832 1555 * @return bool
1833 1556 */
1834 1557 public static function is_true( $value ) {
1835 - return true === $value || '1' === (string) $value || 'true' === $value || 'yes' === $value;
1558 + return true === $value || 1 == $value || 'true' === $value || 'yes' === $value;
1836 1559 }
1837 1560
1838 1561 /**
1839 1562 * Gets all post from a specific post type.
@@ -1841,9 +1564,8 @@
1841 1564 *
1842 1565 * @since 4.10.01 Add `$post_type` argument.
1843 1566 *
1844 1567 * @param string $post_type Post type to query. Default is `page`.
1845 - *
1846 1568 * @return WP_Post[]
1847 1569 */
1848 1570 public static function get_pages( $post_type = 'page' ) {
1849 1571 $query = array(
@@ -1862,9 +1584,8 @@
1862 1584 *
1863 1585 * @since 5.0.09
1864 1586 *
1865 1587 * @param string $post_type Post type to query. Default is `page`.
1866 - *
1867 1588 * @return array
1868 1589 */
1869 1590 public static function get_post_ids_and_titles( $post_type = 'page' ) {
1870 1591 return FrmDb::get_results(
@@ -1889,12 +1610,13 @@
1889 1610 *
1890 1611 * @param array $args Selection arguments.
1891 1612 */
1892 1613 public static function maybe_autocomplete_pages_options( $args ) {
1893 - $args = self::preformat_selection_args( $args );
1614 + $args = self::preformat_selection_args( $args );
1615 +
1894 1616 $pages_count = wp_count_posts( $args['post_type'] );
1895 1617
1896 - if ( ! isset( $pages_count->publish ) || $pages_count->publish <= 50 ) {
1618 + if ( $pages_count->publish <= 50 ) {
1897 1619 self::wp_pages_dropdown( $args );
1898 1620 return;
1899 1621 }
1900 1622
@@ -1918,109 +1640,8 @@
1918 1640 <?php
1919 1641 }
1920 1642
1921 1643 /**
1922 - * Maybe show an HTML select or autocomplete input based on the number of options.
1923 - *
1924 - * @since 6.21
1925 - *
1926 - * @param array $args Args. See the method for details.
1927 - */
1928 - public static function maybe_autocomplete_options( $args ) {
1929 - $defaults = array(
1930 - 'truncate' => false,
1931 - 'placeholder' => ' ',
1932 - 'name' => '',
1933 - 'id' => '',
1934 - 'selected' => '',
1935 - 'source' => array(),
1936 - 'dropdown_limit' => 50,
1937 - 'autocomplete_placeholder' => __( 'Select an option', 'formidable' ),
1938 - 'value_key' => 'value',
1939 - 'label_key' => 'label',
1940 - );
1941 -
1942 - $args = wp_parse_args( $args, $defaults );
1943 - $html_attrs = array();
1944 -
1945 - if ( ! empty( $args['name'] ) ) {
1946 - $html_attrs['name'] = $args['name'];
1947 - }
1948 -
1949 - if ( ! empty( $args['id'] ) ) {
1950 - $html_attrs['id'] = $args['id'];
1951 - }
1952 -
1953 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
1954 - if ( count( $args['source'] ) <= $args['dropdown_limit'] ) {
1955 - ?>
1956 - <select <?php self::array_to_html_params( $html_attrs, true ); ?>>
1957 - <option value=""><?php echo esc_html( $args['placeholder'] ); ?></option>
1958 - <?php
1959 - foreach ( $args['source'] as $key => $source ) :
1960 - $value_label = self::get_dropdown_value_and_label_from_option( $source, $key, $args );
1961 -
1962 - if ( ! empty( $args['truncate'] ) ) {
1963 - $value_label['label'] = self::truncate( $value_label['label'], $args['truncate'] );
1964 - }
1965 - ?>
1966 - <option value="<?php echo esc_attr( $value_label['value'] ); ?>" <?php selected( $value_label['value'], $args['selected'] ); ?>><?php echo esc_html( $value_label['label'] ); ?></option><?php // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong ?>
1967 - <?php endforeach; ?>
1968 - </select>
1969 - <?php
1970 - return;
1971 - }
1972 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
1973 -
1974 - $options = array();
1975 - $autocomplete_value = '';
1976 -
1977 - foreach ( $args['source'] as $key => $source ) {
1978 - $value_label = self::get_dropdown_value_and_label_from_option( $source, $key, $args );
1979 -
1980 - if ( $value_label['value'] === $args['selected'] ) {
1981 - $autocomplete_value = $value_label['label'];
1982 - }
1983 -
1984 - $options[] = $value_label;
1985 - }
1986 -
1987 - $html_attrs['type'] = 'hidden';
1988 - $html_attrs['class'] = 'frm_autocomplete_value_input';
1989 - $html_attrs['value'] = $args['selected'];
1990 - ?>
1991 - <input type="text" class="frm-custom-search"
1992 - data-source="<?php echo esc_attr( wp_json_encode( $options ) ); ?>"
1993 - placeholder="<?php echo esc_attr( $args['autocomplete_placeholder'] ); ?>"
1994 - value="<?php echo esc_attr( $autocomplete_value ); ?>" />
1995 - <input <?php self::array_to_html_params( $html_attrs, true ); ?> />
1996 - <?php
1997 - }
1998 -
1999 - /**
2000 - * Gets dropdown value and label from autodropdown option.
2001 - *
2002 - * @since 6.21
2003 - *
2004 - * @param array|string $option Autocomplete option.
2005 - * @param string $key Array key of the option.
2006 - * @param array $args See {@see FrmAppHelper::maybe_autocomplete_options()}.
2007 - *
2008 - * @return array
2009 - */
2010 - private static function get_dropdown_value_and_label_from_option( $option, $key, $args ) {
2011 - if ( is_array( $option ) ) {
2012 - $value = $option[ $args['value_key'] ] ?? '';
2013 - $label = $option[ $args['label_key'] ] ?? '';
2014 - } else {
2015 - $value = $key;
2016 - $label = $option;
2017 - }
2018 -
2019 - return compact( 'value', 'label' );
2020 - }
2021 -
2022 - /**
2023 1644 * @param array $args
2024 1645 * @param string $page_id Deprecated.
2025 1646 * @param bool $truncate Deprecated.
2026 1647 */
@@ -2028,9 +1649,9 @@
2028 1649 self::prep_page_dropdown_params( $page_id, $truncate, $args );
2029 1650
2030 1651 $pages = self::get_post_ids_and_titles( $args['post_type'] );
2031 1652 $selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
2032 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
1653 +
2033 1654 ?>
2034 1655 <select name="<?php echo esc_attr( $args['field_name'] ); ?>" id="<?php echo esc_attr( $args['field_name'] ); ?>" class="frm-pages-dropdown">
2035 1656 <option value=""><?php echo esc_html( $args['placeholder'] ); ?></option>
2036 1657 <?php foreach ( $pages as $page ) { ?>
@@ -2039,9 +1660,8 @@
2039 1660 </option>
2040 1661 <?php } ?>
2041 1662 </select>
2042 1663 <?php
2043 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
2044 1664 }
2045 1665
2046 1666 /**
2047 1667 * Fill in missing parameters passed to wp_pages_dropdown().
@@ -2047,14 +1667,8 @@
2047 1667 * Fill in missing parameters passed to wp_pages_dropdown().
2048 1668 * This is for reverse compatibility with switching 3 params to 1.
2049 1669 *
2050 1670 * @since 4.03.06
2051 - *
2052 - * @param string $page_id Deprecated.
2053 - * @param bool $truncate Deprecated.
2054 - * @param mixed $args
2055 - *
2056 - * @return void
2057 1671 */
2058 1672 private static function prep_page_dropdown_params( $page_id, $truncate, &$args ) {
2059 1673 if ( ! is_array( $args ) ) {
2060 1674 $args = array(
@@ -2071,12 +1685,8 @@
2071 1685 * Filter to format args for page dropdown or autocomplete
2072 1686 *
2073 1687 * @since 4.03.06
2074 1688 * @since 4.10.01 Added `post_type` and `autocomplete_placeholder` to the arguments array.
2075 - *
2076 - * @param array $args
2077 - *
2078 - * @return array
2079 1689 */
2080 1690 private static function preformat_selection_args( $args ) {
2081 1691 $defaults = array(
2082 1692 'truncate' => false,
@@ -2089,18 +1699,13 @@
2089 1699
2090 1700 return array_merge( $defaults, $args );
2091 1701 }
2092 1702
2093 - /**
2094 - * @param int $post_id
2095 - *
2096 - * @return string
2097 - */
2098 1703 public static function post_edit_link( $post_id ) {
2099 1704 $post = get_post( $post_id );
2100 -
2101 1705 if ( $post ) {
2102 1706 $post_url = admin_url( 'post.php?post=' . $post_id . '&action=edit' );
1707 +
2103 1708 return '<a href="' . esc_url( $post_url ) . '">' . self::truncate( $post->post_title, 50 ) . '</a>';
2104 1709 }
2105 1710
2106 1711 return '';
@@ -2113,9 +1718,11 @@
2113 1718 *
2114 1719 * @return bool
2115 1720 */
2116 1721 public static function is_full_screen() {
2117 - return self::is_form_builder_page() || self::is_style_editor_page() || self::is_full_screen_view_builder_page();
1722 + return self::is_form_builder_page() ||
1723 + self::is_style_editor_page() ||
1724 + self::is_full_screen_view_builder_page();
2118 1725 }
2119 1726
2120 1727 /**
2121 1728 * Check if user is on the style editor or its alternative URL.
@@ -2125,9 +1732,8 @@
2125 1732 * @since 5.5.3
2126 1733 * @since 6.0 Added the $view parameter. Previously there was only a 'edit' view.
2127 1734 *
2128 1735 * @param string $view Supports 'edit', 'list', and ''. If '', both 'edit' and 'list' will match.
2129 - *
2130 1736 * @return bool
2131 1737 */
2132 1738 public static function is_style_editor_page( $view = '' ) {
2133 1739 if ( ! self::is_admin_page( 'formidable-styles' ) && ! self::is_admin_page( 'formidable-styles2' ) ) {
@@ -2159,14 +1765,22 @@
2159 1765 return self::is_admin_page( 'formidable-views-editor' );
2160 1766 }
2161 1767
2162 1768 /**
1769 + * @since 4.0
1770 + * @deprecated 5.5.3
1771 + */
1772 + public static function maybe_full_screen_link( $link ) {
1773 + _deprecated_function( __METHOD__, '5.5.3' );
1774 + return $link;
1775 + }
1776 +
1777 + /**
2163 1778 * @param string $field_name
2164 1779 * @param array|string $capability
2165 1780 * @param string $multiple 'single' and 'multiple'.
2166 1781 */
2167 1782 public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
2168 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
2169 1783 ?>
2170 1784 <select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>"
2171 1785 <?php echo 'multiple' === $multiple ? 'multiple="multiple"' : ''; ?>
2172 1786 class="frm_multiselect">
@@ -2172,14 +1786,12 @@
2172 1786 class="frm_multiselect">
2173 1787 <?php self::roles_options( $capability ); ?>
2174 1788 </select>
2175 1789 <?php
2176 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
2177 1790 }
2178 1791
2179 1792 /**
2180 1793 * @since 4.07
2181 - *
2182 1794 * @param array|string $selected
2183 1795 * @param string $current
2184 1796 */
2185 1797 private static function selected( $selected, $current ) {
@@ -2194,9 +1806,8 @@
2194 1806 * @param array|string $capability
2195 1807 */
2196 1808 public static function roles_options( $capability ) {
2197 1809 global $frm_vars;
2198 -
2199 1810 if ( isset( $frm_vars['editable_roles'] ) ) {
2200 1811 $editable_roles = $frm_vars['editable_roles'];
2201 1812 } else {
2202 1813 $editable_roles = get_editable_roles();
@@ -2205,9 +1816,9 @@
2205 1816
2206 1817 foreach ( $editable_roles as $role => $details ) {
2207 1818 $name = translate_user_role( $details['name'] );
2208 1819 ?>
2209 - <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_html( $name ); ?></option>
1820 + <option value="<?php echo esc_attr( $role ); ?>" <?php self::selected( $capability, $role ); ?>><?php echo esc_html( $name ); ?> </option>
2210 1821 <?php
2211 1822 unset( $role, $details );
2212 1823 }
2213 1824 }
@@ -2217,9 +1828,8 @@
2217 1828 *
2218 1829 * @since 5.0 Parameter `$type` supports `pro_only` value.
2219 1830 *
2220 1831 * @param string $type Supports `auto`, `pro`, or `pro_only`.
2221 - *
2222 1832 * @return array
2223 1833 */
2224 1834 public static function frm_capabilities( $type = 'auto' ) {
2225 1835 if ( ! self::pro_is_installed() && ! in_array( $type, array( 'pro', 'pro_only' ), true ) ) {
@@ -2237,8 +1847,14 @@
2237 1847 * @param array<string,string> $pro_cap
2238 1848 */
2239 1849 $pro_cap = apply_filters( 'frm_pro_capabilities', $pro_cap );
2240 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 +
2241 1857 if ( 'pro_only' === $type ) {
2242 1858 return $pro_cap;
2243 1859 }
2244 1860
@@ -2284,18 +1900,21 @@
2284 1900 if ( $role === 'loggedin' || ! $role ) {
2285 1901 return is_user_logged_in();
2286 1902 }
2287 1903
2288 - if ( (int) $role === 1 ) {
1904 + if ( $role == 1 ) {
2289 1905 $role = 'administrator';
2290 1906 }
2291 1907
2292 - return is_user_logged_in() ? current_user_can( $role ) : false;
1908 + if ( ! is_user_logged_in() ) {
1909 + return false;
1910 + }
1911 +
1912 + return current_user_can( $role );
2293 1913 }
2294 1914
2295 1915 /**
2296 1916 * @param array|string $needed_role
2297 - *
2298 1917 * @return bool
2299 1918 */
2300 1919 public static function user_has_permission( $needed_role ) {
2301 1920 if ( is_array( $needed_role ) ) {
@@ -2309,20 +1928,18 @@
2309 1928 }
2310 1929
2311 1930 $can = self::current_user_can( $needed_role );
2312 1931
2313 - if ( $can || in_array( $needed_role, array( '-1', 'loggedout' ), true ) ) {
1932 + if ( $can || in_array( $needed_role, array( '-1', 'loggedout' ) ) ) {
2314 1933 return $can;
2315 1934 }
2316 1935
2317 1936 $roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
2318 -
2319 1937 foreach ( $roles as $role ) {
2320 1938 if ( current_user_can( $role ) ) {
2321 1939 return true;
2322 1940 }
2323 -
2324 - if ( $role === $needed_role ) {
1941 + if ( $role == $needed_role ) {
2325 1942 break;
2326 1943 }
2327 1944 }
2328 1945
@@ -2343,9 +1960,8 @@
2343 1960
2344 1961 $user_id = get_current_user_id();
2345 1962 $user = new WP_User( $user_id );
2346 1963 $frm_roles = self::frm_capabilities();
2347 -
2348 1964 foreach ( $frm_roles as $frm_role => $frm_role_description ) {
2349 1965 $user->add_cap( $frm_role );
2350 1966 unset( $frm_role, $frm_role_description );
2351 1967 }
@@ -2356,22 +1972,18 @@
2356 1972 *
2357 1973 * @since 2.0.6
2358 1974 *
2359 1975 * @param string $cap
2360 - *
2361 1976 * @return void
2362 1977 */
2363 1978 public static function force_capability( $cap = 'frm_change_settings' ) {
2364 - if ( ! current_user_can( 'administrator' ) || current_user_can( $cap ) ) {
2365 - return;
1979 + if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
1980 + $role = get_role( 'administrator' );
1981 + $frm_roles = self::frm_capabilities();
1982 + foreach ( $frm_roles as $frm_role => $frm_role_description ) {
1983 + $role->add_cap( $frm_role );
1984 + }
2366 1985 }
2367 -
2368 - $role = get_role( 'administrator' );
2369 - $frm_roles = self::frm_capabilities();
2370 -
2371 - foreach ( $frm_roles as $frm_role => $frm_role_description ) {
2372 - $role->add_cap( $frm_role );
2373 - }
2374 1986 }
2375 1987
2376 1988 /**
2377 1989 * Check if the user has permission for action.
@@ -2379,22 +1991,17 @@
2379 1991 *
2380 1992 * @since 2.0
2381 1993 *
2382 1994 * @param string $permission
2383 - * @param string $show_message
2384 1995 */
2385 1996 public static function permission_check( $permission, $show_message = 'show' ) {
2386 1997 $permission_error = self::permission_nonce_error( $permission );
2387 -
2388 - if ( $permission_error === false ) {
2389 - return;
1998 + if ( $permission_error !== false ) {
1999 + if ( 'hide' == $show_message ) {
2000 + $permission_error = '';
2001 + }
2002 + wp_die( esc_html( $permission_error ) );
2390 2003 }
2391 -
2392 - if ( 'hide' === $show_message ) {
2393 - $permission_error = '';
2394 - }
2395 -
2396 - wp_die( esc_html( $permission_error ) );
2397 2004 }
2398 2005
2399 2006 /**
2400 2007 * Check user permission and nonce
@@ -2401,27 +2008,24 @@
2401 2008 *
2402 2009 * @since 2.0
2403 2010 *
2404 2011 * @param string $permission
2405 - * @param string $nonce_name
2406 - * @param string $nonce
2407 2012 *
2408 2013 * @return false|string The permission message or false if allowed
2409 2014 */
2410 2015 public static function permission_nonce_error( $permission, $nonce_name = '', $nonce = '' ) {
2411 - if ( $permission && ! current_user_can( $permission ) && ! current_user_can( 'administrator' ) ) {
2016 + if ( ! empty( $permission ) && ! current_user_can( $permission ) && ! current_user_can( 'administrator' ) ) {
2412 2017 $frm_settings = self::get_settings();
2018 +
2413 2019 return $frm_settings->admin_permission;
2414 2020 }
2415 2021
2416 2022 $error = false;
2417 -
2418 - if ( ! $nonce_name ) {
2023 + if ( empty( $nonce_name ) ) {
2419 2024 return $error;
2420 2025 }
2421 2026
2422 2027 $nonce_value = $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
2423 -
2424 2028 if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $nonce_value, $nonce ) ) ) {
2425 2029 $frm_settings = self::get_settings();
2426 2030 $error = $frm_settings->admin_permission;
2427 2031 }
@@ -2428,14 +2032,8 @@
2428 2032
2429 2033 return $error;
2430 2034 }
2431 2035
2432 - /**
2433 - * @param array|string $values
2434 - * @param string $current
2435 - *
2436 - * @return void
2437 - */
2438 2036 public static function checked( $values, $current ) {
2439 2037 if ( self::check_selected( $values, $current ) ) {
2440 2038 echo ' checked="checked"';
2441 2039 }
@@ -2440,47 +2038,38 @@
2440 2038 echo ' checked="checked"';
2441 2039 }
2442 2040 }
2443 2041
2444 - /**
2445 - * @param array|string $values
2446 - * @param string|null $current
2447 - *
2448 - * @return bool
2449 - */
2450 2042 public static function check_selected( $values, $current ) {
2451 - $values = self::recursive_function_map( $values, 'trim' );
2452 - $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
2043 + $values = self::recursive_function_map( $values, 'trim' );
2044 + $values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
2045 +
2453 2046 $current = is_null( $current ) ? '' : htmlspecialchars_decode( trim( $current ) );
2454 2047
2455 - // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict, Universal.Operators.StrictComparisons
2456 - return is_array( $values ) ? in_array( $current, $values ) : $values == $current;
2048 + return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
2457 2049 }
2458 2050
2459 - /**
2460 - * @param array|string $value
2461 - * @param callable|string $function
2462 - *
2463 - * @return array|string
2464 - */
2465 2051 public static function recursive_function_map( $value, $function ) {
2466 2052 if ( is_array( $value ) ) {
2467 2053 $original_function = $function;
2468 - $function = count( $value ) ? explode( ', ', FrmDb::prepare_array_values( $value, $function ) ) : array( $function );
2469 -
2470 - if ( self::is_assoc( $value ) ) {
2054 + if ( count( $value ) ) {
2055 + $function = explode( ', ', FrmDb::prepare_array_values( $value, $function ) );
2056 + } else {
2057 + $function = array( $function );
2058 + }
2059 + if ( ! self::is_assoc( $value ) ) {
2060 + $value = array_map( array( 'FrmAppHelper', 'recursive_function_map' ), $value, $function );
2061 + } else {
2471 2062 foreach ( $value as $k => $v ) {
2472 2063 if ( ! is_array( $v ) ) {
2473 2064 $value[ $k ] = call_user_func( $original_function, $v );
2474 2065 }
2475 2066 }
2476 - } else {
2477 - $value = array_map( array( 'FrmAppHelper', 'recursive_function_map' ), $value, $function );
2478 2067 }
2479 2068 } else {
2480 2069 $value = self::maybe_update_value_if_null( $value, $function );
2481 2070 $value = call_user_func( $function, $value );
2482 - }//end if
2071 + }
2483 2072
2484 2073 return $value;
2485 2074 }
2486 2075
@@ -2487,27 +2076,20 @@
2487 2076 /**
2488 2077 * Updates value to empty string if it is null and being passed to a string function.
2489 2078 *
2490 2079 * @since 6.8.4
2491 - *
2492 2080 * @param mixed $value
2493 2081 * @param string $function
2494 - *
2495 2082 * @return mixed
2496 2083 */
2497 2084 private static function maybe_update_value_if_null( $value, $function ) {
2498 2085 if ( null === $value && in_array( $function, array( 'trim', 'strlen' ), true ) ) {
2499 - return '';
2086 + $value = '';
2500 2087 }
2501 2088
2502 2089 return $value;
2503 2090 }
2504 2091
2505 - /**
2506 - * @param array $array
2507 - *
2508 - * @return bool
2509 - */
2510 2092 public static function is_assoc( $array ) {
2511 2093 return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
2512 2094 }
2513 2095
@@ -2512,22 +2094,16 @@
2512 2094 }
2513 2095
2514 2096 /**
2515 2097 * Flatten a multi-dimensional array
2516 - *
2517 - * @param array $array
2518 - * @param string $keys
2519 - *
2520 - * @return array
2521 2098 */
2522 2099 public static function array_flatten( $array, $keys = 'keep' ) {
2523 2100 $return = array();
2524 -
2525 2101 foreach ( $array as $key => $value ) {
2526 2102 if ( is_array( $value ) ) {
2527 2103 $return = array_merge( $return, self::array_flatten( $value, $keys ) );
2528 2104 } elseif ( $keys === 'keep' ) {
2529 - $return[ $key ] = $value;
2105 + $return[ $key ] = $value;
2530 2106 } else {
2531 2107 $return[] = $value;
2532 2108 }
2533 2109 }
@@ -2535,35 +2111,17 @@
2535 2111 return $return;
2536 2112 }
2537 2113
2538 2114 /**
2539 - * Flatten an array before imploding it to avoid Array to string conversion warnings.
2540 - *
2541 - * @since 6.16.1
2542 - *
2543 - * @param string $sep
2544 - * @param array $array
2545 - *
2546 - * @return string
2547 - */
2548 - public static function safe_implode( $sep, $array ) {
2549 - $array = self::array_flatten( $array );
2550 - return implode( $sep, $array );
2551 - }
2552 -
2553 - /**
2554 2115 * @param string $text
2555 2116 * @param bool $is_rich_text
2556 - *
2557 2117 * @return string
2558 2118 */
2559 2119 public static function esc_textarea( $text, $is_rich_text = false ) {
2560 2120 $safe_text = str_replace( '&quot;', '"', $text );
2561 -
2562 2121 if ( ! $is_rich_text ) {
2563 2122 $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
2564 2123 }
2565 -
2566 2124 $safe_text = str_replace( '&amp; ', '& ', $safe_text );
2567 2125
2568 2126 /**
2569 2127 * @param string $safe_text
@@ -2575,59 +2133,44 @@
2575 2133 /**
2576 2134 * Add auto paragraphs to text areas
2577 2135 *
2578 2136 * @since 2.0
2579 - *
2580 - * @param mixed $content
2581 - *
2582 - * @return mixed
2583 2137 */
2584 2138 public static function use_wpautop( $content ) {
2585 - if ( apply_filters( 'frm_use_wpautop', true ) && is_string( $content ) ) {
2586 - return wpautop( str_replace( '<br>', '<br />', $content ) );
2139 + if ( apply_filters( 'frm_use_wpautop', true ) && ! is_array( $content ) ) {
2140 + $content = wpautop( str_replace( '<br>', '<br />', $content ) );
2587 2141 }
2588 2142
2589 2143 return $content;
2590 2144 }
2591 2145
2592 - /**
2593 - * Replace quotes with their HTML entities.
2594 - *
2595 - * @param string $val
2596 - *
2597 - * @return string
2598 - */
2599 2146 public static function replace_quotes( $val ) {
2600 2147 // Replace double quotes.
2601 2148 $val = str_replace( array( '&#8220;', '&#8221;', '&#8243;' ), '"', $val );
2602 2149
2603 2150 // Replace single quotes.
2604 - return str_replace( array( '&#8216;', '&#8217;', '&#8242;', '&prime;', '&rsquo;', '&lsquo;' ), "'", $val );
2151 + $val = str_replace( array( '&#8216;', '&#8217;', '&#8242;', '&prime;', '&rsquo;', '&lsquo;' ), "'", $val );
2152 +
2153 + return $val;
2605 2154 }
2606 2155
2607 2156 /**
2608 - * @param string $handle
2609 - * @param int|string $default
2610 - *
2611 - * @return int|string
2157 + * @param string $handle
2612 2158 */
2613 2159 public static function script_version( $handle, $default = 0 ) {
2614 2160 global $wp_scripts;
2615 -
2616 2161 if ( ! $wp_scripts ) {
2617 2162 return $default;
2618 2163 }
2619 2164
2620 2165 $ver = $default;
2621 -
2622 2166 if ( ! isset( $wp_scripts->registered[ $handle ] ) ) {
2623 2167 return $ver;
2624 2168 }
2625 2169
2626 2170 $query = $wp_scripts->registered[ $handle ];
2627 -
2628 2171 if ( is_object( $query ) && ! empty( $query->ver ) ) {
2629 - return $query->ver;
2172 + $ver = $query->ver;
2630 2173 }
2631 2174
2632 2175 return $ver;
2633 2176 }
@@ -2636,9 +2179,8 @@
2636 2179 * @since 5.0.13 added $echo param.
2637 2180 *
2638 2181 * @param string $url
2639 2182 * @param bool $echo
2640 - *
2641 2183 * @return string|null
2642 2184 */
2643 2185 public static function js_redirect( $url, $echo = false ) {
2644 2186 $callback = function () use ( $url ) {
@@ -2646,13 +2188,8 @@
2646 2188 };
2647 2189 return self::clip( $callback, $echo );
2648 2190 }
2649 2191
2650 - /**
2651 - * @param int|string $user_id
2652 - *
2653 - * @return int|string
2654 - */
2655 2192 public static function get_user_id_param( $user_id ) {
2656 2193 if ( ! $user_id || is_numeric( $user_id ) ) {
2657 2194 return $user_id;
2658 2195 }
@@ -2657,13 +2194,16 @@
2657 2194 return $user_id;
2658 2195 }
2659 2196
2660 2197 $user_id = sanitize_text_field( $user_id );
2661 -
2662 2198 if ( $user_id === 'current' ) {
2663 2199 $user_id = get_current_user_id();
2664 2200 } else {
2665 - $user = is_email( $user_id ) ? get_user_by( 'email', $user_id ) : get_user_by( 'login', $user_id );
2201 + if ( is_email( $user_id ) ) {
2202 + $user = get_user_by( 'email', $user_id );
2203 + } else {
2204 + $user = get_user_by( 'login', $user_id );
2205 + }
2666 2206
2667 2207 if ( $user ) {
2668 2208 $user_id = $user->ID;
2669 2209 }
@@ -2675,9 +2215,8 @@
2675 2215
2676 2216 /**
2677 2217 * @param string $filename
2678 2218 * @param array $atts
2679 - *
2680 2219 * @return false|string
2681 2220 */
2682 2221 public static function get_file_contents( $filename, $atts = array() ) {
2683 2222 if ( ! is_file( $filename ) ) {
@@ -2686,9 +2225,12 @@
2686 2225
2687 2226 extract( $atts ); // phpcs:ignore WordPress.PHP.DontExtract
2688 2227 ob_start();
2689 2228 include $filename;
2690 - return ob_get_clean();
2229 + $contents = ob_get_contents();
2230 + ob_end_clean();
2231 +
2232 + return $contents;
2691 2233 }
2692 2234
2693 2235 /**
2694 2236 * @param string $name
@@ -2698,9 +2240,8 @@
2698 2240 * @param int $num_chars
2699 2241 */
2700 2242 public static function get_unique_key( $name, $table_name, $column, $id = 0, $num_chars = 5 ) {
2701 2243 $key = '';
2702 -
2703 2244 if ( $name ) {
2704 2245 $key = sanitize_key( $name );
2705 2246 $key = self::maybe_clear_long_key( $key, $column );
2706 2247 }
@@ -2720,31 +2261,31 @@
2720 2261 $column
2721 2262 );
2722 2263
2723 2264 // Create a unique field id if it has already been used.
2724 - if ( ! in_array( $key, $similar_keys, true ) ) {
2725 - return $key;
2726 - }
2265 + if ( in_array( $key, $similar_keys, true ) ) {
2266 + $key = self::maybe_truncate_key_before_appending( $column, $key );
2727 2267
2728 - $key = self::maybe_truncate_key_before_appending( $column, $key );
2268 + /**
2269 + * Allow for a custom separator between the attempted key and the generated suffix.
2270 + *
2271 + * @since 5.2.03
2272 + *
2273 + * @param string $separator. Default empty.
2274 + * @param string $key the key without the added suffix.
2275 + */
2276 + $separator = apply_filters( 'frm_unique_' . $column . '_separator', '', $key );
2729 2277
2730 - /**
2731 - * Allow for a custom separator between the attempted key and the generated suffix.
2732 - *
2733 - * @since 5.2.03
2734 - *
2735 - * @param string $separator. Default empty.
2736 - * @param string $key the key without the added suffix.
2737 - */
2738 - $separator = apply_filters( 'frm_unique_' . $column . '_separator', '', $key );
2278 + $suffix = 2;
2279 + do {
2280 + $key_check = $key . $separator . $suffix;
2281 + ++$suffix;
2282 + } while ( in_array( $key_check, $similar_keys, true ) );
2739 2283
2740 - $suffix = 2;
2741 - do {
2742 - $key_check = $key . $separator . $suffix;
2743 - ++$suffix;
2744 - } while ( in_array( $key_check, $similar_keys, true ) );
2284 + $key = $key_check;
2285 + }//end if
2745 2286
2746 - return $key_check;
2287 + return $key;
2747 2288 }
2748 2289
2749 2290 /**
2750 2291 * Avoid trying to append to a really long key,
@@ -2751,26 +2292,20 @@
2751 2292 * The database limit is 100 for form and field keys so we want to avoid getting too close.
2752 2293 *
2753 2294 * @param string $column
2754 2295 * @param string $key
2755 - *
2756 2296 * @return string
2757 2297 */
2758 2298 private static function maybe_truncate_key_before_appending( $column, $key ) {
2759 - if ( ! in_array( $column, array( 'form_key', 'field_key' ), true ) ) {
2760 - return $key;
2761 - }
2762 -
2763 - $max_key_length_before_truncating = 60;
2764 -
2765 - if ( strlen( $key ) > $max_key_length_before_truncating ) {
2766 - $key = substr( $key, 0, $max_key_length_before_truncating );
2767 -
2768 - if ( is_numeric( $key ) ) {
2769 - $key .= 'a';
2299 + if ( in_array( $column, array( 'form_key', 'field_key' ), true ) ) {
2300 + $max_key_length_before_truncating = 60;
2301 + if ( strlen( $key ) > $max_key_length_before_truncating ) {
2302 + $key = substr( $key, 0, $max_key_length_before_truncating );
2303 + if ( is_numeric( $key ) ) {
2304 + $key .= 'a';
2305 + }
2770 2306 }
2771 2307 }
2772 -
2773 2308 return $key;
2774 2309 }
2775 2310
2776 2311 /**
@@ -2777,36 +2312,31 @@
2777 2312 * Possibly reset a key to avoid conflicts with column size limits.
2778 2313 *
2779 2314 * @param string $key
2780 2315 * @param string $column
2781 - *
2782 2316 * @return string either the original key value, or an empty string if the key was too long.
2783 2317 */
2784 2318 private static function maybe_clear_long_key( $key, $column ) {
2785 2319 if ( 'field_key' === $column && strlen( $key ) >= 70 ) {
2786 - return '';
2320 + $key = '';
2787 2321 }
2788 2322 return $key;
2789 2323 }
2790 2324
2791 2325 /**
2792 - * @since 6.21 This is changed from `private` to `public`.
2793 - *
2794 2326 * @param int $num_chars
2795 - *
2796 2327 * @return string
2797 2328 */
2798 - public static function generate_new_key( $num_chars ) {
2799 - $max_slug_value = 36 ** $num_chars;
2329 + private static function generate_new_key( $num_chars ) {
2330 + $max_slug_value = pow( 36, $num_chars );
2800 2331
2801 2332 // We want to have at least 2 characters in the slug.
2802 2333 $min_slug_value = 37;
2803 - return base_convert( random_int( $min_slug_value, $max_slug_value ), 10, 36 );
2334 + return base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
2804 2335 }
2805 2336
2806 2337 /**
2807 2338 * @param string $key
2808 - *
2809 2339 * @return string
2810 2340 */
2811 2341 private static function prevent_numeric_and_reserved_keys( $key ) {
2812 2342 if ( is_numeric( $key ) ) {
@@ -2820,14 +2350,12 @@
2820 2350 'editlink',
2821 2351 'siteurl',
2822 2352 'evenodd',
2823 2353 );
2824 -
2825 2354 if ( in_array( $key, $not_allowed, true ) ) {
2826 2355 $key .= 'a';
2827 2356 }
2828 2357 }
2829 -
2830 2358 return $key;
2831 2359 }
2832 2360
2833 2361 /**
@@ -2846,9 +2374,9 @@
2846 2374 if ( ! $record ) {
2847 2375 return false;
2848 2376 }
2849 2377
2850 - if ( ! $post_values ) {
2378 + if ( empty( $post_values ) ) {
2851 2379 $post_values = wp_unslash( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
2852 2380 }
2853 2381
2854 2382 $values = array(
@@ -2856,9 +2384,9 @@
2856 2384 'fields' => array(),
2857 2385 );
2858 2386
2859 2387 foreach ( array( 'name', 'description' ) as $var ) {
2860 - $default_val = $record->{$var} ?? '';
2388 + $default_val = isset( $record->{$var} ) ? $record->{$var} : '';
2861 2389 $values[ $var ] = self::get_param( $var, $default_val, 'get', 'wp_kses_post' );
2862 2390 unset( $var, $default_val );
2863 2391 }
2864 2392
@@ -2876,67 +2404,46 @@
2876 2404
2877 2405 return $values;
2878 2406 }
2879 2407
2880 - /**
2881 - * @param array|string $fields
2882 - * @param object $record
2883 - * @param array $values
2884 - * @param array $args
2885 - *
2886 - * @return void
2887 - */
2888 2408 private static function prepare_field_arrays( $fields, $record, array &$values, $args ) {
2889 - if ( ! $fields ) {
2890 - return;
2891 - }
2892 -
2893 - foreach ( (array) $fields as $field ) {
2894 - if ( ! self::is_admin_page() ) {
2895 - // Don't prep default values on the form settings page.
2896 - $field->default_value = apply_filters( 'frm_get_default_value', $field->default_value, $field, true );
2409 + if ( ! empty( $fields ) ) {
2410 + foreach ( (array) $fields as $field ) {
2411 + if ( ! self::is_admin_page() ) {
2412 + // Don't prep default values on the form settings page.
2413 + $field->default_value = apply_filters( 'frm_get_default_value', $field->default_value, $field, true );
2414 + }
2415 + $args['parent_form_id'] = isset( $args['parent_form_id'] ) ? $args['parent_form_id'] : $field->form_id;
2416 + self::fill_field_defaults( $field, $record, $values, $args );
2897 2417 }
2898 -
2899 - $args['parent_form_id'] = $args['parent_form_id'] ?? $field->form_id;
2900 - self::fill_field_defaults( $field, $record, $values, $args );
2901 2418 }
2902 2419 }
2903 2420
2904 - /**
2905 - * @param object $field
2906 - * @param object $record
2907 - * @param array $values
2908 - * @param array $args
2909 - *
2910 - * @return void
2911 - */
2912 2421 private static function fill_field_defaults( $field, $record, array &$values, $args ) {
2913 2422 $post_values = $args['post_values'];
2914 2423
2915 2424 if ( $args['default'] ) {
2916 2425 $meta_value = $field->default_value;
2917 - } elseif ( $record->post_id && self::pro_is_installed() && ! empty( $field->field_options['post_field'] ) ) {
2426 + } elseif ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
2918 2427 if ( ! isset( $field->field_options['custom_field'] ) ) {
2919 2428 $field->field_options['custom_field'] = '';
2920 2429 }
2921 -
2922 - $meta_value = FrmProEntryMetaHelper::get_post_value(
2923 - $record->post_id,
2924 - $field->field_options['post_field'],
2925 - $field->field_options['custom_field'],
2926 - array(
2927 - 'truncate' => false,
2928 - 'type' => $field->type,
2929 - 'form_id' => $field->form_id,
2930 - 'field' => $field,
2931 - )
2932 - );
2430 + $meta_value = FrmProEntryMetaHelper::get_post_value(
2431 + $record->post_id,
2432 + $field->field_options['post_field'],
2433 + $field->field_options['custom_field'],
2434 + array(
2435 + 'truncate' => false,
2436 + 'type' => $field->type,
2437 + 'form_id' => $field->form_id,
2438 + 'field' => $field,
2439 + )
2440 + );
2933 2441 } else {
2934 2442 $meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
2935 2443 }//end if
2936 2444
2937 - $field_type = $post_values['field_options'][ 'type_' . $field->id ] ?? $field->type;
2938 -
2445 + $field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
2939 2446 if ( isset( $post_values['item_meta'][ $field->id ] ) ) {
2940 2447 $new_value = $post_values['item_meta'][ $field->id ];
2941 2448 self::unserialize_or_decode( $new_value );
2942 2449 } else {
@@ -2951,9 +2458,9 @@
2951 2458 $args['field_type'] = $field_type;
2952 2459
2953 2460 FrmFieldsHelper::prepare_edit_front_field( $field_array, $field, $values['id'], $args );
2954 2461
2955 - if ( empty( $field_array['unique'] ) ) {
2462 + if ( ! isset( $field_array['unique'] ) || ! $field_array['unique'] ) {
2956 2463 $field_array['unique_msg'] = '';
2957 2464 }
2958 2465
2959 2466 $field_array = array_merge( (array) $field->field_options, $field_array );
@@ -3020,21 +2527,15 @@
3020 2527 }
3021 2528
3022 2529 /**
3023 2530 * Set to POST value or default
3024 - *
3025 - * @param array $post_values
3026 - * @param array $values
3027 - *
3028 - * @return void
3029 2531 */
3030 2532 private static function fill_form_defaults( $post_values, array &$values ) {
3031 2533 $form_defaults = FrmFormsHelper::get_default_opts();
3032 2534
3033 2535 foreach ( $form_defaults as $opt => $default ) {
3034 - // phpcs:ignore Universal.Operators.StrictComparisons
3035 2536 if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
3036 - $values[ $opt ] = $post_values['options'][ $opt ] ?? $default;
2537 + $values[ $opt ] = $post_values && isset( $post_values['options'][ $opt ] ) ? $post_values['options'][ $opt ] : $default;
3037 2538 }
3038 2539
3039 2540 unset( $opt, $default );
3040 2541 }
@@ -3044,9 +2545,9 @@
3044 2545 }
3045 2546
3046 2547 foreach ( array( 'before', 'after', 'submit' ) as $h ) {
3047 2548 if ( ! isset( $values[ $h . '_html' ] ) ) {
3048 - $values[ $h . '_html' ] = $post_values['options'][ $h . '_html' ] ?? FrmFormsHelper::get_default_html( $h );
2549 + $values[ $h . '_html' ] = ( isset( $post_values['options'][ $h . '_html' ] ) ? $post_values['options'][ $h . '_html' ] : FrmFormsHelper::get_default_html( $h ) );
3049 2550 }
3050 2551 unset( $h );
3051 2552 }
3052 2553 }
@@ -3058,14 +2559,16 @@
3058 2559 *
3059 2560 * @return bool|int
3060 2561 */
3061 2562 public static function custom_style_value( $post_values ) {
3062 - if ( $post_values && isset( $post_values['options']['custom_style'] ) ) {
3063 - return absint( $post_values['options']['custom_style'] );
2563 + if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
2564 + $custom_style = absint( $post_values['options']['custom_style'] );
2565 + } else {
2566 + $frm_settings = self::get_settings();
2567 + $custom_style = ( $frm_settings->load_style !== 'none' );
3064 2568 }
3065 2569
3066 - $frm_settings = self::get_settings();
3067 - return $frm_settings->load_style !== 'none';
2570 + return $custom_style;
3068 2571 }
3069 2572
3070 2573 /**
3071 2574 * @param mixed $original_string
@@ -3071,9 +2574,8 @@
3071 2574 * @param mixed $original_string
3072 2575 * @param int|string $length
3073 2576 * @param int $minword
3074 2577 * @param string $continue
3075 - *
3076 2578 * @return string
3077 2579 */
3078 2580 public static function truncate( $original_string, $length, $minword = 3, $continue = '...' ) {
3079 2581 if ( ! is_string( $original_string ) && ! is_int( $original_string ) ) {
@@ -3079,24 +2581,24 @@
3079 2581 if ( ! is_string( $original_string ) && ! is_int( $original_string ) ) {
3080 2582 return '';
3081 2583 }
3082 2584
3083 - $length = (int) $length;
2585 + $length = (int) $length;
2586 + $str = wp_strip_all_tags( (string) $original_string );
2587 + $original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
3084 2588
3085 - if ( $length === 0 ) {
2589 + if ( $length == 0 ) {
3086 2590 return '';
3087 2591 }
3088 2592
3089 - $str = wp_strip_all_tags( (string) $original_string );
3090 - $original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
3091 -
3092 2593 if ( $length <= 10 ) {
3093 2594 $sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
3094 2595 return $sub . ( $length < $original_len ? $continue : '' );
3095 2596 }
3096 2597
3097 - $sub = '';
3098 - $len = 0;
2598 + $sub = '';
2599 + $len = 0;
2600 +
3099 2601 $words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
3100 2602
3101 2603 if ( ! is_array( $words ) ) {
3102 2604 return $original_string;
@@ -3102,11 +2604,10 @@
3102 2604 return $original_string;
3103 2605 }
3104 2606
3105 2607 foreach ( $words as $word ) {
3106 - $part = ( $sub !== '' ? ' ' : '' ) . $word;
2608 + $part = ( $sub != '' ? ' ' : '' ) . $word;
3107 2609 $total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
3108 -
3109 2610 if ( $total_len > $length && substr_count( $sub, ' ' ) ) {
3110 2611 break;
3111 2612 }
3112 2613
@@ -3131,9 +2632,8 @@
3131 2632 * @since 6.5.4
3132 2633 *
3133 2634 * @param string $sub Current substring.
3134 2635 * @param int $length The length limit.
3135 - *
3136 2636 * @return string
3137 2637 */
3138 2638 private static function maybe_force_truncate_on_string_with_no_spaces( $sub, $length ) {
3139 2639 if ( strlen( $sub ) < $length + 50 ) {
@@ -3141,9 +2641,8 @@
3141 2641 return $sub;
3142 2642 }
3143 2643
3144 2644 $first_space = strpos( $sub, ' ', $length );
3145 -
3146 2645 if ( false !== $first_space ) {
3147 2646 // Ignore anything with spaces.
3148 2647 return $sub;
3149 2648 }
@@ -3150,18 +2649,11 @@
3150 2649
3151 2650 return substr( $sub, 0, $length + 10 );
3152 2651 }
3153 2652
3154 - /**
3155 - * @param array $function_names
3156 - * @param array $args
3157 - *
3158 - * @return mixed
3159 - */
3160 2653 public static function mb_function( $function_names, $args ) {
3161 2654 $mb_function_name = $function_names[0];
3162 2655 $function_name = $function_names[1];
3163 -
3164 2656 if ( function_exists( $mb_function_name ) ) {
3165 2657 $function_name = $mb_function_name;
3166 2658 }
3167 2659
@@ -3167,21 +2659,14 @@
3167 2659
3168 2660 return call_user_func_array( $function_name, $args );
3169 2661 }
3170 2662
3171 - /**
3172 - * @param string $date
3173 - * @param string $date_format
3174 - * @param string $time_format
3175 - *
3176 - * @return string
3177 - */
3178 2663 public static function get_formatted_time( $date, $date_format = '', $time_format = '' ) {
3179 - if ( ! $date ) {
2664 + if ( empty( $date ) ) {
3180 2665 return $date;
3181 2666 }
3182 2667
3183 - if ( ! $date_format ) {
2668 + if ( empty( $date_format ) ) {
3184 2669 $date_format = get_option( 'date_format' );
3185 2670 }
3186 2671
3187 2672 if ( preg_match( '/^\d{1-2}\/\d{1-2}\/\d{4}$/', $date ) && self::pro_is_installed() ) {
@@ -3189,10 +2674,10 @@
3189 2674 $date = FrmProAppHelper::convert_date( $date, $frmpro_settings->date_format, 'Y-m-d' );
3190 2675 }
3191 2676
3192 2677 $formatted = self::get_localized_date( $date_format, $date );
3193 - $do_time = gmdate( 'H:i:s', strtotime( $date ) ) !== '00:00:00';
3194 2678
2679 + $do_time = ( gmdate( 'H:i:s', strtotime( $date ) ) != '00:00:00' );
3195 2680 if ( $do_time ) {
3196 2681 $formatted .= self::add_time_to_date( $time_format, $date );
3197 2682 }
3198 2683
@@ -3198,38 +2683,28 @@
3198 2683
3199 2684 return $formatted;
3200 2685 }
3201 2686
3202 - /**
3203 - * @param string $time_format
3204 - * @param string $date
3205 - *
3206 - * @return string
3207 - */
3208 2687 private static function add_time_to_date( $time_format, $date ) {
3209 - if ( ! $time_format ) {
2688 + if ( empty( $time_format ) ) {
3210 2689 $time_format = get_option( 'time_format' );
3211 2690 }
3212 2691
3213 2692 $trimmed_format = trim( $time_format );
3214 -
3215 - if ( $time_format && $trimmed_format ) {
3216 - return ' ' . __( 'at', 'formidable' ) . ' ' . self::get_localized_date( $time_format, $date );
2693 + $time = '';
2694 + if ( $time_format && ! empty( $trimmed_format ) ) {
2695 + $time = ' ' . __( 'at', 'formidable' ) . ' ' . self::get_localized_date( $time_format, $date );
3217 2696 }
3218 2697
3219 - return '';
2698 + return $time;
3220 2699 }
3221 2700
3222 2701 /**
3223 2702 * @since 2.0.8
3224 - *
3225 - * @param string $date_format
3226 - * @param string $date
3227 - *
3228 - * @return string
3229 2703 */
3230 2704 public static function get_localized_date( $date_format, $date ) {
3231 2705 $date = get_date_from_gmt( $date );
2706 +
3232 2707 return date_i18n( $date_format, strtotime( $date ) );
3233 2708 }
3234 2709
3235 2710 /**
@@ -3234,16 +2709,19 @@
3234 2709
3235 2710 /**
3236 2711 * Gets the time ago in words.
3237 2712 *
3238 - * @param int $from In seconds.
3239 - * @param int|string $to In seconds.
3240 - * @param int|string $levels Number of time units to include or a specific unit.
2713 + * @param int $from In seconds.
2714 + * @param int|string $to In seconds.
3241 2715 *
3242 - * @return string Time ago.
2716 + * @return string $time_ago
3243 2717 */
3244 2718 public static function human_time_diff( $from, $to = '', $levels = 1 ) {
3245 - $now = ! $to && 0 !== $to ? new DateTime() : new DateTime( '@' . $to );
2719 + if ( empty( $to ) && 0 !== $to ) {
2720 + $now = new DateTime();
2721 + } else {
2722 + $now = new DateTime( '@' . $to );
2723 + }
3246 2724 $ago = new DateTime( '@' . $from );
3247 2725
3248 2726 // Get the time difference
3249 2727 $diff_object = $now->diff( $ago );
@@ -3257,9 +2735,8 @@
3257 2735
3258 2736 if ( ! is_numeric( $levels ) ) {
3259 2737 // Show time in specified unit.
3260 2738 $levels = self::get_unit( $levels );
3261 -
3262 2739 if ( isset( $time_strings[ $levels ] ) ) {
3263 2740 $diff = array(
3264 2741 $levels => self::time_format( $levels, $diff ),
3265 2742 );
@@ -3266,14 +2743,13 @@
3266 2743 $time_strings = array(
3267 2744 $levels => $time_strings[ $levels ],
3268 2745 );
3269 2746 }
3270 -
3271 2747 $levels = 1;
3272 2748 }
3273 2749
3274 2750 foreach ( $time_strings as $k => $v ) {
3275 - if ( ! empty( $diff[ $k ] ) ) {
2751 + if ( isset( $diff[ $k ] ) && $diff[ $k ] ) {
3276 2752 $time_strings[ $k ] = $diff[ $k ] . ' ' . ( $diff[ $k ] > 1 ? $v[1] : $v[0] );
3277 2753 } elseif ( isset( $diff[ $k ] ) && count( $time_strings ) === 1 ) {
3278 2754 // Account for 0.
3279 2755 $time_strings[ $k ] = $diff[ $k ] . ' ' . $v[1];
@@ -3281,21 +2757,17 @@
3281 2757 unset( $time_strings[ $k ] );
3282 2758 }
3283 2759 }
3284 2760
3285 - $levels_deep = apply_filters( 'frm_time_ago_levels', $levels, compact( 'time_strings', 'from', 'to' ) );
3286 - $time_strings = array_slice( $time_strings, 0, absint( $levels_deep ) );
2761 + $levels_deep = apply_filters( 'frm_time_ago_levels', $levels, compact( 'time_strings', 'from', 'to' ) );
2762 + $time_strings = array_slice( $time_strings, 0, absint( $levels_deep ) );
2763 + $time_ago_string = implode( ' ', $time_strings );
3287 2764
3288 - return implode( ' ', $time_strings );
2765 + return $time_ago_string;
3289 2766 }
3290 2767
3291 2768 /**
3292 2769 * @since 4.05.01
3293 - *
3294 - * @param string $unit
3295 - * @param array $diff
3296 - *
3297 - * @return int
3298 2770 */
3299 2771 private static function time_format( $unit, $diff ) {
3300 2772 $return = array(
3301 2773 'y' => 'y',
@@ -3300,14 +2772,14 @@
3300 2772 $return = array(
3301 2773 'y' => 'y',
3302 2774 'd' => 'days',
3303 2775 );
3304 -
3305 2776 if ( isset( $return[ $unit ] ) ) {
3306 2777 return $diff[ $return[ $unit ] ];
3307 2778 }
3308 2779
3309 2780 $total = $diff['days'] * self::convert_time( 'd', $unit );
2781 +
3310 2782 $times = array( 'h', 'i', 's' );
3311 2783
3312 2784 foreach ( $times as $time ) {
3313 2785 if ( ! isset( $diff[ $time ] ) ) {
@@ -3321,13 +2793,8 @@
3321 2793 }
3322 2794
3323 2795 /**
3324 2796 * @since 4.05.01
3325 - *
3326 - * @param string $from
3327 - * @param string $to
3328 - *
3329 - * @return int
3330 2797 */
3331 2798 private static function convert_time( $from, $to ) {
3332 2799 $convert = array(
3333 2800 's' => 1,
@@ -3343,26 +2810,20 @@
3343 2810 }
3344 2811
3345 2812 /**
3346 2813 * @since 4.05.01
3347 - *
3348 - * @param string $unit
3349 - *
3350 - * @return int|string
3351 2814 */
3352 2815 private static function get_unit( $unit ) {
3353 2816 $units = self::get_time_strings();
3354 -
3355 2817 if ( isset( $units[ $unit ] ) || is_numeric( $unit ) ) {
3356 2818 return $unit;
3357 2819 }
3358 2820
3359 2821 foreach ( $units as $u => $strings ) {
3360 - if ( in_array( $unit, $strings, true ) ) {
2822 + if ( in_array( $unit, $strings ) ) {
3361 2823 return $u;
3362 2824 }
3363 2825 }
3364 -
3365 2826 return 1;
3366 2827 }
3367 2828
3368 2829 /**
@@ -3369,9 +2830,8 @@
3369 2830 * Get the translatable time strings. The untranslated version is a failsafe
3370 2831 * in case languages are changing for the unit set in the shortcode.
3371 2832 *
3372 2833 * @since 2.0.20
3373 - *
3374 2834 * @return array
3375 2835 */
3376 2836 private static function get_time_strings() {
3377 2837 return array(
@@ -3418,13 +2878,12 @@
3418 2878 /**
3419 2879 * @param int $r_count
3420 2880 * @param int $current_p
3421 2881 * @param int $p_size
3422 - *
3423 2882 * @return int
3424 2883 */
3425 2884 public static function get_last_record_num( $r_count, $current_p, $p_size ) {
3426 - 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 );
3427 2886 }
3428 2887
3429 2888 /**
3430 2889 * @param int $r_count
@@ -3429,13 +2888,11 @@
3429 2888 /**
3430 2889 * @param int $r_count
3431 2890 * @param int $current_p
3432 2891 * @param int $p_size
3433 - *
3434 2892 * @return int
3435 2893 */
3436 2894 public static function get_first_record_num( $r_count, $current_p, $p_size ) {
3437 - // phpcs:ignore Universal.Operators.StrictComparisons
3438 2895 if ( $current_p == 1 ) {
3439 2896 return 1;
3440 2897 }
3441 2898 return self::get_last_record_num( $r_count, $current_p - 1, $p_size ) + 1;
@@ -3441,22 +2898,17 @@
3441 2898 return self::get_last_record_num( $r_count, $current_p - 1, $p_size ) + 1;
3442 2899 }
3443 2900
3444 2901 /**
3445 - * @param array $json_vars
3446 - *
3447 2902 * @return array
3448 2903 */
3449 2904 public static function json_to_array( $json_vars ) {
3450 2905 $vars = array();
3451 -
3452 2906 foreach ( $json_vars as $jv ) {
3453 2907 $jv_name = explode( '[', $jv['name'] );
3454 2908 $last = count( $jv_name ) - 1;
3455 -
3456 2909 foreach ( $jv_name as $p => $n ) {
3457 2910 $name = trim( $n, ']' );
3458 -
3459 2911 if ( ! isset( $l1 ) ) {
3460 2912 $l1 = $name;
3461 2913 }
3462 2914
@@ -3467,9 +2919,9 @@
3467 2919 if ( ! isset( $l3 ) ) {
3468 2920 $l3 = $name;
3469 2921 }
3470 2922
3471 - $this_val = $p === $last ? $jv['value'] : array();
2923 + $this_val = $p == $last ? $jv['value'] : array();
3472 2924
3473 2925 switch ( $p ) {
3474 2926 case 0:
3475 2927 $l1 = $name;
@@ -3502,15 +2954,10 @@
3502 2954
3503 2955 /**
3504 2956 * @param string $name
3505 2957 * @param string $l1
3506 - * @param mixed $val
3507 - * @param array $vars
3508 - *
3509 - * @return void
3510 2958 */
3511 2959 public static function add_value_to_array( $name, $l1, $val, &$vars ) {
3512 - // phpcs:ignore Universal.Operators.StrictComparisons
3513 2960 if ( $name == '' ) {
3514 2961 $vars[] = $val;
3515 2962 } elseif ( ! isset( $vars[ $l1 ] ) ) {
3516 2963 $vars[ $l1 ] = $val;
@@ -3516,26 +2963,19 @@
3516 2963 $vars[ $l1 ] = $val;
3517 2964 }
3518 2965 }
3519 2966
3520 - /**
3521 - * @param string $name
3522 - * @param string $class
3523 - * @param string $form_name
3524 - *
3525 - * @return void
3526 - */
3527 2967 public static function maybe_add_tooltip( $name, $class = 'closed', $form_name = '' ) {
3528 2968 $tooltips = array(
3529 2969 'action_title' => __( 'Give this action a label for easy reference.', 'formidable' ),
3530 - 'email_to' => __( 'Add one or more recipient addresses separated by a ",". FORMAT: Name <name@email.com> or name@email.com. [default-email] is the address set in the global "Default Email Address" settings.', 'formidable' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
2970 + 'email_to' => __( 'Add one or more recipient addresses separated by a ",". FORMAT: Name <name@email.com> or name@email.com. [admin_email] is the address set in WP General Settings.', 'formidable' ),
3531 2971 'cc' => __( 'Add CC addresses separated by a ",". FORMAT: Name <name@email.com> or name@email.com.', 'formidable' ),
3532 2972 'bcc' => __( 'Add BCC addresses separated by a ",". FORMAT: Name <name@email.com> or name@email.com.', 'formidable' ),
3533 - 'reply_to' => __( 'If you would like a different reply to address than the "from" address, add a single address here. FORMAT: Name <name@email.com> or name@email.com.', 'formidable' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
2973 + 'reply_to' => __( 'If you would like a different reply to address than the "from" address, add a single address here. FORMAT: Name <name@email.com> or name@email.com.', 'formidable' ),
3534 2974 'from' => __( 'Enter the name and/or email address of the sender. FORMAT: John Bates <john@example.com> or john@example.com.', 'formidable' ),
3535 2975 /* translators: %1$s: Form name, %2$s: Date */
3536 - 'email_subject' => esc_attr( sprintf( __( 'If you leave the subject blank, the default will be used: %1$s Form submitted on %2$s', 'formidable' ), $form_name, self::site_name() ) ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
3537 - 'new_tab' => __( 'This option will open the link in a new browser tab. Please note that some popup blockers may prevent this from happening, in which case the link will be displayed.', 'formidable' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
2976 + 'email_subject' => esc_attr( sprintf( __( 'If you leave the subject blank, the default will be used: %1$s Form submitted on %2$s', 'formidable' ), $form_name, self::site_name() ) ),
2977 + 'new_tab' => __( 'This option will open the link in a new browser tab. Please note that some popup blockers may prevent this from happening, in which case the link will be displayed.', 'formidable' ),
3538 2978 );
3539 2979
3540 2980 if ( ! isset( $tooltips[ $name ] ) ) {
3541 2981 return;
@@ -3540,9 +2980,9 @@
3540 2980 if ( ! isset( $tooltips[ $name ] ) ) {
3541 2981 return;
3542 2982 }
3543 2983
3544 - if ( 'open' === $class ) {
2984 + if ( 'open' == $class ) {
3545 2985 echo ' frm_help"';
3546 2986 } else {
3547 2987 echo ' class="frm_help"';
3548 2988 }
@@ -3548,9 +2988,9 @@
3548 2988 }
3549 2989
3550 2990 echo ' title="' . esc_attr( $tooltips[ $name ] );
3551 2991
3552 - if ( 'open' !== $class ) {
2992 + if ( 'open' != $class ) {
3553 2993 echo '"';
3554 2994 }
3555 2995 }
3556 2996
@@ -3555,28 +2995,20 @@
3555 2995 }
3556 2996
3557 2997 /**
3558 2998 * Add the current_page class to that page in the form nav
3559 - *
3560 - * @param int|string $page
3561 - * @param int|string $current_page
3562 - * @param array $action
3563 - *
3564 - * @return void
3565 2999 */
3566 3000 public static function select_current_page( $page, $current_page, $action = array() ) {
3567 - // phpcs:ignore Universal.Operators.StrictComparisons
3568 3001 if ( $current_page != $page ) {
3569 3002 return;
3570 3003 }
3571 3004
3572 3005 $frm_action = self::simple_get( 'frm_action', 'sanitize_title' );
3573 -
3574 3006 if ( 'lite-reports' === $frm_action ) {
3575 3007 $frm_action = 'reports';
3576 3008 }
3577 3009
3578 - if ( ! $action || ( $frm_action && in_array( $frm_action, $action, true ) ) ) {
3010 + if ( empty( $action ) || ( ! empty( $frm_action ) && in_array( $frm_action, $action ) ) ) {
3579 3011 echo ' class="current_page"';
3580 3012 }
3581 3013 }
3582 3014
@@ -3606,19 +3038,14 @@
3606 3038
3607 3039 // Add extra slashes for \r\n since WP strips them.
3608 3040 $post_content = str_replace( array( '\\r', '\\n', '\\u', '\\t' ), array( '\\\\r', '\\\\n', '\\\\u', '\\\\t' ), $post_content );
3609 3041
3610 - // Allow for &quot
3611 - return str_replace( '&quot;', '\\"', $post_content );
3042 + // allow for &quot
3043 + $post_content = str_replace( '&quot;', '\\"', $post_content );
3044 +
3045 + return $post_content;
3612 3046 }
3613 3047
3614 - /**
3615 - * @param array|string $val
3616 - * @param int|string $key
3617 - * @param array $post_content
3618 - *
3619 - * @return void
3620 - */
3621 3048 private static function prepare_action_slashes( $val, $key, &$post_content ) {
3622 3049 if ( ! isset( $post_content[ $key ] ) || is_numeric( $val ) ) {
3623 3050 return;
3624 3051 }
@@ -3627,17 +3054,15 @@
3627 3054 foreach ( $val as $k1 => $v1 ) {
3628 3055 self::prepare_action_slashes( $v1, $k1, $post_content[ $key ] );
3629 3056 unset( $k1, $v1 );
3630 3057 }
3058 + } else {
3059 + // Strip all slashes so everything is the same, no matter where the value is coming from
3060 + $val = stripslashes( $val );
3631 3061
3632 - return;
3062 + // Add backslashes before double quotes and forward slashes only
3063 + $post_content[ $key ] = addcslashes( $val, '"\\/' );
3633 3064 }
3634 -
3635 - // Strip all slashes so everything is the same, no matter where the value is coming from
3636 - $val = stripslashes( $val );
3637 -
3638 - // Add backslashes before double quotes and forward slashes only
3639 - $post_content[ $key ] = addcslashes( $val, '"\\/' );
3640 3065 }
3641 3066
3642 3067 /**
3643 3068 * Check for either json or serialized data. This is temporary while transitioning
@@ -3645,9 +3070,8 @@
3645 3070 *
3646 3071 * @since 4.02.03
3647 3072 *
3648 3073 * @param array|string $value
3649 - *
3650 3074 * @return void
3651 3075 */
3652 3076 public static function unserialize_or_decode( &$value ) {
3653 3077 if ( is_array( $value ) ) {
@@ -3653,9 +3077,13 @@
3653 3077 if ( is_array( $value ) ) {
3654 3078 return;
3655 3079 }
3656 3080
3657 - $value = is_serialized( $value ) ? self::maybe_unserialize_array( $value ) : self::maybe_json_decode( $value, false );
3081 + if ( is_serialized( $value ) ) {
3082 + $value = self::maybe_unserialize_array( $value );
3083 + } else {
3084 + $value = self::maybe_json_decode( $value, false );
3085 + }
3658 3086 }
3659 3087
3660 3088 /**
3661 3089 * Safely unserialize an array if necessary.
@@ -3663,9 +3091,8 @@
3663 3091 *
3664 3092 * @since 6.2
3665 3093 *
3666 3094 * @param mixed $value
3667 - *
3668 3095 * @return mixed
3669 3096 */
3670 3097 public static function maybe_unserialize_array( $value ) {
3671 3098 if ( ! is_string( $value ) ) {
@@ -3672,15 +3099,18 @@
3672 3099 return $value;
3673 3100 }
3674 3101
3675 3102 // Since we only expect an array, skip anything that doesn't start with a:.
3676 - if ( ! is_serialized( $value ) || ! str_starts_with( $value, 'a:' ) ) {
3103 + if ( ! is_serialized( $value ) || 'a:' !== substr( $value, 0, 2 ) ) {
3677 3104 return $value;
3678 3105 }
3679 3106
3680 3107 $parsed = FrmSerializedStringParserHelper::get()->parse( $value );
3108 + if ( is_array( $parsed ) ) {
3109 + $value = $parsed;
3110 + }
3681 3111
3682 - return is_array( $parsed ) ? $parsed : $value;
3112 + return $value;
3683 3113 }
3684 3114
3685 3115 /**
3686 3116 * Decode a JSON string.
@@ -3685,12 +3115,11 @@
3685 3115 /**
3686 3116 * Decode a JSON string.
3687 3117 * Do not switch shortcodes like [24] to array unless intentional ie XML values.
3688 3118 *
3689 - * @param array|string|null $string
3690 - * @param bool $single_to_array
3691 - *
3692 - * @return array|string|null
3119 + * @param mixed $string
3120 + * @param bool $single_to_array
3121 + * @return mixed
3693 3122 */
3694 3123 public static function maybe_json_decode( $string, $single_to_array = true ) {
3695 3124 if ( is_array( $string ) || is_null( $string ) ) {
3696 3125 return $string;
@@ -3695,19 +3124,20 @@
3695 3124 if ( is_array( $string ) || is_null( $string ) ) {
3696 3125 return $string;
3697 3126 }
3698 3127
3699 - $new_string = json_decode( $string, true );
3700 - $single_value = false;
3701 -
3702 - if ( ! $single_to_array ) {
3703 - $single_value = is_array( $new_string ) && count( $new_string ) === 1 && isset( $new_string[0] );
3128 + $new_string = json_decode( $string, true );
3129 + if ( function_exists( 'json_last_error' ) ) {
3130 + // php 5.3+
3131 + $single_value = false;
3132 + if ( ! $single_to_array ) {
3133 + $single_value = is_array( $new_string ) && count( $new_string ) === 1 && isset( $new_string[0] );
3134 + }
3135 + if ( json_last_error() == JSON_ERROR_NONE && is_array( $new_string ) && ! $single_value ) {
3136 + $string = $new_string;
3137 + }
3704 3138 }
3705 3139
3706 - if ( json_last_error() === JSON_ERROR_NONE && is_array( $new_string ) && ! $single_value ) {
3707 - return $new_string;
3708 - }
3709 -
3710 3140 return $string;
3711 3141 }
3712 3142
3713 3143 /**
@@ -3713,9 +3143,8 @@
3713 3143 /**
3714 3144 * @since 6.2.3
3715 3145 *
3716 3146 * @param string $value
3717 - *
3718 3147 * @return string
3719 3148 */
3720 3149 public static function maybe_utf8_encode( $value ) {
3721 3150 $from_format = 'ISO-8859-1';
@@ -3724,15 +3153,13 @@
3724 3153 if ( function_exists( 'mb_check_encoding' ) && function_exists( 'mb_convert_encoding' ) ) {
3725 3154 if ( mb_check_encoding( $value, $from_format ) ) {
3726 3155 return mb_convert_encoding( $value, $to_format, $from_format );
3727 3156 }
3728 -
3729 3157 return $value;
3730 3158 }
3731 3159
3732 3160 if ( function_exists( 'iconv' ) ) {
3733 3161 $converted = iconv( $from_format, $to_format, $value );
3734 -
3735 3162 // Value is false if $value is not ISO-8859-1.
3736 3163 if ( false !== $converted ) {
3737 3164 return $converted;
3738 3165 }
@@ -3744,12 +3171,8 @@
3744 3171 /**
3745 3172 * Reformat the json serialized array in name => value array.
3746 3173 *
3747 3174 * @since 4.02.03
3748 - *
3749 - * @param array $form
3750 - *
3751 - * @return void
3752 3175 */
3753 3176 public static function format_form_data( &$form ) {
3754 3177 $formatted = array();
3755 3178
@@ -3756,21 +3179,18 @@
3756 3179 foreach ( $form as $input ) {
3757 3180 if ( ! isset( $input['name'] ) ) {
3758 3181 continue;
3759 3182 }
3760 -
3761 3183 $key = $input['name'];
3762 -
3763 - if ( ! isset( $formatted[ $key ] ) ) {
3184 + if ( isset( $formatted[ $key ] ) ) {
3185 + if ( is_array( $formatted[ $key ] ) ) {
3186 + $formatted[ $key ][] = $input['value'];
3187 + } else {
3188 + $formatted[ $key ] = array( $formatted[ $key ], $input['value'] );
3189 + }
3190 + } else {
3764 3191 $formatted[ $key ] = $input['value'];
3765 - continue;
3766 3192 }
3767 -
3768 - if ( is_array( $formatted[ $key ] ) ) {
3769 - $formatted[ $key ][] = $input['value'];
3770 - } else {
3771 - $formatted[ $key ] = array( $formatted[ $key ], $input['value'] );
3772 - }
3773 3193 }
3774 3194
3775 3195 parse_str( http_build_query( $formatted ), $form );
3776 3196 }
@@ -3778,13 +3198,15 @@
3778 3198 /**
3779 3199 * @since 4.02.03
3780 3200 *
3781 3201 * @param array|string $value
3782 - *
3783 3202 * @return string
3784 3203 */
3785 3204 public static function maybe_json_encode( $value ) {
3786 - return is_array( $value ) ? wp_json_encode( $value ) : $value;
3205 + if ( is_array( $value ) ) {
3206 + $value = wp_json_encode( $value );
3207 + }
3208 + return $value;
3787 3209 }
3788 3210
3789 3211 /**
3790 3212 * Echo The javascript to open and highlight the Formidable menu
@@ -3791,19 +3213,18 @@
3791 3213 *
3792 3214 * @since 1.07.10
3793 3215 *
3794 3216 * @param string $post_type The name of the post type that may need to be highlighted.
3795 - *
3796 3217 * @return void
3797 3218 */
3798 3219 public static function maybe_highlight_menu( $post_type ) {
3799 3220 global $post;
3800 3221
3801 - if ( isset( $_REQUEST['post_type'] ) && $_REQUEST['post_type'] !== $post_type ) {
3222 + if ( isset( $_REQUEST['post_type'] ) && $_REQUEST['post_type'] != $post_type ) {
3802 3223 return;
3803 3224 }
3804 3225
3805 - if ( is_object( $post ) && $post->post_type !== $post_type ) {
3226 + if ( is_object( $post ) && $post->post_type != $post_type ) {
3806 3227 return;
3807 3228 }
3808 3229
3809 3230 self::load_admin_wide_js();
@@ -3815,9 +3236,8 @@
3815 3236 *
3816 3237 * @since 2.0
3817 3238 *
3818 3239 * @param bool $load
3819 - *
3820 3240 * @return void
3821 3241 */
3822 3242 public static function load_admin_wide_js( $load = true ) {
3823 3243 $version = self::plugin_version();
@@ -3828,9 +3248,9 @@
3828 3248 'deauthorize' => __( 'Are you sure you want to deauthorize Formidable Forms on this site?', 'formidable' ),
3829 3249 'url' => self::plugin_url(),
3830 3250 'app_url' => 'https://formidableforms.com/',
3831 3251 'applicationsUrl' => admin_url( 'admin.php?page=formidable-applications' ),
3832 - 'canAccessApplicationDashboard' => current_user_can( is_callable( 'FrmProApplicationsHelper::get_required_templates_capability' ) ? FrmProApplicationsHelper::get_required_templates_capability() : 'frm_edit_forms' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
3252 + 'canAccessApplicationDashboard' => current_user_can( is_callable( 'FrmProApplicationsHelper::get_required_templates_capability' ) ? FrmProApplicationsHelper::get_required_templates_capability() : 'frm_edit_forms' ),
3833 3253 'loading' => __( 'Loading&hellip;', 'formidable' ),
3834 3254 'nonce' => wp_create_nonce( 'frm_ajax' ),
3835 3255 'proIncludesSliderJs' => is_callable( 'FrmProFormsHelper::prepare_custom_currency' ),
3836 3256 'inboxSlideIn' => FrmInbox::get_inbox_slide_in_value_for_js(),
@@ -3843,9 +3263,8 @@
3843 3263 }
3844 3264
3845 3265 /**
3846 3266 * @since 2.0.9
3847 - *
3848 3267 * @return void
3849 3268 */
3850 3269 public static function load_font_style() {
3851 3270 wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
@@ -3852,13 +3271,12 @@
3852 3271 }
3853 3272
3854 3273 /**
3855 3274 * @param string $location
3856 - *
3857 3275 * @return void
3858 3276 */
3859 3277 public static function localize_script( $location ) {
3860 - global $wp_scripts, $wp_version;
3278 + global $wp_scripts;
3861 3279
3862 3280 $script_strings = array(
3863 3281 'ajax_url' => esc_url_raw( self::get_ajax_url() ),
3864 3282 'images_url' => self::plugin_url() . '/images',
@@ -3877,9 +3295,8 @@
3877 3295 'include_resend_email' => false,
3878 3296 );
3879 3297
3880 3298 $data = $wp_scripts->get_data( 'formidable', 'data' );
3881 -
3882 3299 if ( ! $data ) {
3883 3300 wp_localize_script( 'formidable', 'frm_js', $script_strings );
3884 3301 }
3885 3302
@@ -3884,73 +3301,68 @@
3884 3301 }
3885 3302
3886 3303 if ( $location === 'admin' ) {
3887 3304 $admin_script_strings = array(
3888 - 'desc' => __( '(Click to add description)', 'formidable' ),
3889 - 'blank' => __( '(Blank)', 'formidable' ),
3890 - 'no_label' => self::get_no_label_text(),
3891 - 'ok' => __( 'OK', 'formidable' ),
3892 - 'cancel' => __( 'Cancel', 'formidable' ),
3893 - 'default_label' => __( 'Default', 'formidable' ),
3894 - 'clear_default' => __( 'Clear default value when typing', 'formidable' ),
3895 - 'no_clear_default' => __( 'Do not clear default value when typing', 'formidable' ),
3896 - 'valid_default' => __( 'Default value will pass form validation', 'formidable' ),
3897 - 'no_valid_default' => __( 'Default value will NOT pass form validation', 'formidable' ),
3898 - 'confirm' => __( 'Are you sure?', 'formidable' ),
3899 - 'conf_delete' => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
3900 - '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' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
3901 - 'conf_no_repeat' => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
3902 - 'default_unique' => FrmFieldsHelper::default_unique_msg(),
3903 - 'default_conf' => __( 'The entered values do not match', 'formidable' ),
3904 - 'enter_email' => __( 'Enter Email', 'formidable' ),
3905 - 'confirm_email' => __( 'Confirm Email', 'formidable' ),
3906 - 'conditional_text' => __( 'Conditional content here', 'formidable' ),
3907 - 'new_option' => __( 'New Option', 'formidable' ),
3908 - 'css_invalid_size' => __( 'In certain browsers (e.g. Firefox) text will not display correctly if the field height is too small relative to the field padding and text size. Please increase your field height or decrease your field padding.', 'formidable' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
3909 - 'enter_password' => __( 'Enter Password', 'formidable' ),
3910 - 'confirm_password' => __( 'Confirm Password', 'formidable' ),
3911 - 'import_complete' => __( 'Import Complete', 'formidable' ),
3912 - 'updating' => __( 'Please wait while your site updates.', 'formidable' ),
3913 - 'no_save_warning' => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
3914 - 'private_label' => __( 'Private', 'formidable' ),
3915 - 'jquery_ui_url' => '',
3916 - 'pro_url' => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
3917 - 'no_licenses' => __( 'No new licenses were found', 'formidable' ),
3918 - 'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3919 - 'view_shortcodes' => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
3920 - 'text_shortcodes' => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
3305 + 'desc' => __( '(Click to add description)', 'formidable' ),
3306 + 'blank' => __( '(Blank)', 'formidable' ),
3307 + 'no_label' => __( '(no label)', 'formidable' ),
3308 + 'ok' => __( 'OK', 'formidable' ),
3309 + 'cancel' => __( 'Cancel', 'formidable' ),
3310 + 'default_label' => __( 'Default', 'formidable' ),
3311 + 'clear_default' => __( 'Clear default value when typing', 'formidable' ),
3312 + 'no_clear_default' => __( 'Do not clear default value when typing', 'formidable' ),
3313 + 'valid_default' => __( 'Default value will pass form validation', 'formidable' ),
3314 + 'no_valid_default' => __( 'Default value will NOT pass form validation', 'formidable' ),
3315 + 'confirm' => __( 'Are you sure?', 'formidable' ),
3316 + 'conf_delete' => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
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' ),
3318 + 'conf_no_repeat' => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
3319 + 'default_unique' => FrmFieldsHelper::default_unique_msg(),
3320 + 'default_conf' => __( 'The entered values do not match', 'formidable' ),
3321 + 'enter_email' => __( 'Enter Email', 'formidable' ),
3322 + 'confirm_email' => __( 'Confirm Email', 'formidable' ),
3323 + 'conditional_text' => __( 'Conditional content here', 'formidable' ),
3324 + 'new_option' => __( 'New Option', 'formidable' ),
3325 + 'css_invalid_size' => __( 'In certain browsers (e.g. Firefox) text will not display correctly if the field height is too small relative to the field padding and text size. Please increase your field height or decrease your field padding.', 'formidable' ),
3326 + 'enter_password' => __( 'Enter Password', 'formidable' ),
3327 + 'confirm_password' => __( 'Confirm Password', 'formidable' ),
3328 + 'import_complete' => __( 'Import Complete', 'formidable' ),
3329 + 'updating' => __( 'Please wait while your site updates.', 'formidable' ),
3330 + 'no_save_warning' => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
3331 + 'private_label' => __( 'Private', 'formidable' ),
3332 + 'jquery_ui_url' => '',
3333 + 'pro_url' => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
3334 + 'no_licenses' => __( 'No new licenses were found', 'formidable' ),
3335 + 'unmatched_parens' => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
3336 + 'view_shortcodes' => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
3337 + 'text_shortcodes' => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
3921 3338 /* translators: %d is the number of allowed actions per form */
3922 - 'only_one_action' => sprintf( __( 'This form action is limited to %d per form.', 'formidable' ), 1 ),
3923 - 'edit_action_text' => __( 'Please edit the existing form action.', 'formidable' ),
3924 - 'unsafe_params' => FrmFormsHelper::reserved_words(),
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' ),
3341 + 'unsafe_params' => FrmFormsHelper::reserved_words(),
3925 3342 /* Translators: %s is the name of a Detail Page Slug that is a reserved word.*/
3926 - 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
3343 + 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ),
3927 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. */
3928 - 'param_is_reserved' => sprintf( __( 'The parameter "%s" is reserved by WordPress. This may cause problems when included in the URL. Is this intentional? ', 'formidable' ), '****' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
3929 - 'reserved_words' => __( 'See the list of reserved words in WordPress.', 'formidable' ),
3930 - 'repeat_limit_min' => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
3931 - 'checkbox_limit' => __( 'Please select a limit between 0 and 200.', 'formidable' ),
3932 - 'install' => __( 'Install', 'formidable' ),
3933 - 'active' => __( 'Active', 'formidable' ),
3934 - 'installed' => __( 'Installed', 'formidable' ),
3935 - 'not_installed' => __( 'Not Installed', 'formidable' ),
3936 - 'select_a_field' => __( 'Select a Field', 'formidable' ),
3937 - 'no_items_found' => __( 'No items found.', 'formidable' ),
3938 - 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
3345 + 'param_is_reserved' => sprintf( __( 'The parameter "%s" is reserved by WordPress. This may cause problems when included in the URL. Is this intentional? ', 'formidable' ), '****' ),
3346 + 'reserved_words' => __( 'See the list of reserved words in WordPress.', 'formidable' ),
3347 + 'repeat_limit_min' => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
3348 + 'checkbox_limit' => __( 'Please select a limit between 0 and 200.', 'formidable' ),
3349 + 'install' => __( 'Install', 'formidable' ),
3350 + 'active' => __( 'Active', 'formidable' ),
3351 + 'installed' => __( 'Installed', 'formidable' ),
3352 + 'not_installed' => __( 'Not Installed', 'formidable' ),
3353 + 'select_a_field' => __( 'Select a Field', 'formidable' ),
3354 + 'no_items_found' => __( 'No items found.', 'formidable' ),
3355 + 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
3939 3356
3940 3357 // Deprecated in 6.0.
3941 - 'saving' => '',
3358 + 'saving' => '',
3942 3359
3943 3360 // Deprecated in 6.0.
3944 - 'saved' => '',
3361 + 'saved' => '',
3945 3362
3946 3363 // translators: %1$s: HTML open tag, %2$s: HTML end tag.
3947 - 'holdShiftMsg' => esc_html__( 'You can hold %1$sShift%2$s on your keyboard to select multiple fields', 'formidable' ),
3948 - 'noTitleText' => FrmFormsHelper::get_no_title_text(),
3949 -
3950 - // In older versions this event listener causes the section to immediately close again
3951 - // When the h3 element is clicked. It's only required in WP 6.7+.
3952 - 'requireAccordionTitleClickListener' => version_compare( $wp_version, '6.7', '>=' ),
3364 + 'holdShiftMsg' => esc_html__( 'You can hold %1$sShift%2$s on your keyboard to select multiple fields', 'formidable' ),
3953 3365 );
3954 3366 /**
3955 3367 * @param array $admin_script_strings
3956 3368 */
@@ -3956,9 +3368,8 @@
3956 3368 */
3957 3369 $admin_script_strings = apply_filters( 'frm_admin_script_strings', $admin_script_strings );
3958 3370
3959 3371 $data = $wp_scripts->get_data( 'formidable_admin', 'data' );
3960 -
3961 3372 if ( ! $data ) {
3962 3373 wp_localize_script( 'formidable_admin', 'frm_admin_js', $admin_script_strings );
3963 3374 }
3964 3375 }//end if
@@ -3964,19 +3375,8 @@
3964 3375 }//end if
3965 3376 }
3966 3377
3967 3378 /**
3968 - * Get the no label text.
3969 - *
3970 - * @since 6.25.1
3971 - *
3972 - * @return string
3973 - */
3974 - public static function get_no_label_text() {
3975 - return __( '(no label)', 'formidable' );
3976 - }
3977 -
3978 - /**
3979 3379 * @since 6.5
3980 3380 *
3981 3381 * @return string
3982 3382 */
@@ -4018,9 +3418,8 @@
4018 3418 *
4019 3419 * @since 1.07.10
4020 3420 *
4021 3421 * @param float $min_version The version the add-on requires.
4022 - *
4023 3422 * @return void
4024 3423 */
4025 3424 public static function min_version_notice( $min_version ) {
4026 3425 $frm_version = self::plugin_version();
@@ -4030,11 +3429,11 @@
4030 3429 return;
4031 3430 }
4032 3431
4033 3432 $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
4034 - echo '<tr class="plugin-update-tr active"><th colspan="' . absint( $wp_list_table->get_column_count() ) . '" class="check-column plugin-update colspanchange"><div class="update-message">' . // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
4035 - esc_html__( 'You are running an outdated version of Formidable. This plugin may not work correctly if you do not update Formidable.', 'formidable' ) .
4036 - '</div></td></tr>';
3433 + echo '<tr class="plugin-update-tr active"><th colspan="' . absint( $wp_list_table->get_column_count() ) . '" class="check-column plugin-update colspanchange"><div class="update-message">' .
3434 + esc_html__( 'You are running an outdated version of Formidable. This plugin may not work correctly if you do not update Formidable.', 'formidable' ) .
3435 + '</div></td></tr>';
4037 3436 }
4038 3437
4039 3438 /**
4040 3439 * If Pro is far outdated, show a message.
@@ -4040,10 +3439,8 @@
4040 3439 * If Pro is far outdated, show a message.
4041 3440 *
4042 3441 * @since 4.0.01
4043 3442 *
4044 - * @param string $min_version
4045 - *
4046 3443 * @return void
4047 3444 */
4048 3445 public static function min_pro_version_notice( $min_version ) {
4049 3446 if ( ! self::is_formidable_admin() ) {
@@ -4053,14 +3450,25 @@
4053 3450
4054 3451 self::php_version_notice();
4055 3452
4056 3453 $is_pro = self::pro_is_installed() && class_exists( 'FrmProDb' );
4057 -
4058 3454 if ( ! $is_pro || self::meets_min_pro_version( $min_version ) ) {
4059 3455 return;
4060 3456 }
4061 3457
4062 - include self::plugin_path() . '/classes/views/addons/min-version-notice.php';
3458 + $expired = FrmAddonsController::is_license_expired();
3459 + ?>
3460 + <div class="frm-banner-alert frm_error_style frm_previous_install">
3461 + <?php
3462 + esc_html_e( 'You are running a version of Formidable Forms that may not be compatible with your version of Formidable Forms Pro.', 'formidable' );
3463 + if ( empty( $expired ) ) {
3464 + echo ' Please <a href="' . esc_url( admin_url( 'plugins.php?s=formidable%20forms%20pro' ) ) . '">update now</a>.';
3465 + } else {
3466 + echo '<br/>Please <a href="https://formidableforms.com/account/downloads/?utm_source=WordPress&utm_medium=outdated">renew now</a> to get the latest version.';
3467 + }
3468 + ?>
3469 + </div>
3470 + <?php
4063 3471 }
4064 3472
4065 3473 /**
4066 3474 * If Pro is installed, check the version number.
@@ -4067,9 +3475,8 @@
4067 3475 *
4068 3476 * @since 4.0.01
4069 3477 *
4070 3478 * @param string $min_version
4071 - *
4072 3479 * @return bool
4073 3480 */
4074 3481 public static function meets_min_pro_version( $min_version ) {
4075 3482 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
@@ -4075,22 +3482,25 @@
4075 3482 return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
4076 3483 }
4077 3484
4078 3485 /**
4079 - * Show a message if the PHP version is below the recommendations.
3486 + * Show a message if the browser or PHP version is below the recommendations.
4080 3487 *
4081 3488 * @since 4.0.02
4082 - *
4083 3489 * @return void
4084 3490 */
4085 3491 private static function php_version_notice() {
4086 3492 $message = array();
3493 + if ( version_compare( phpversion(), '7.0', '<' ) ) {
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' );
3495 + }
4087 3496
4088 - if ( version_compare( phpversion(), '7.0', '<' ) ) {
4089 - $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' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
3497 + $browser = self::get_server_value( 'HTTP_USER_AGENT' );
3498 + $is_ie = strpos( $browser, 'MSIE' ) !== false;
3499 + if ( $is_ie ) {
3500 + $message[] = __( 'You are using an outdated browser that is not compatible with Formidable Forms. Please update to a more current browser (we recommend Chrome).', 'formidable' );
4090 3501 }
4091 3502
4092 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
4093 3503 foreach ( $message as $m ) {
4094 3504 ?>
4095 3505 <div class="frm-banner-alert frm_error_style frm_previous_install">
4096 3506 <?php echo esc_html( $m ); ?>
@@ -4096,14 +3506,12 @@
4096 3506 <?php echo esc_html( $m ); ?>
4097 3507 </div>
4098 3508 <?php
4099 3509 }
4100 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
4101 3510 }
4102 3511
4103 3512 /**
4104 3513 * @param string $type
4105 - *
4106 3514 * @return array<string,string>
4107 3515 */
4108 3516 public static function locales( $type = 'date' ) {
4109 3517 $locales = array(
@@ -4197,12 +3605,12 @@
4197 3605 'zu' => __( 'Zulu', 'formidable' ),
4198 3606 );
4199 3607
4200 3608 if ( $type === 'captcha' ) {
4201 - // Remove the languages unavailable for the captcha
3609 + // remove the languages unavailable for the captcha
4202 3610 $unset = array( 'sq', 'bs', 'eo', 'fo', 'fr-CH', 'sr-SR', 'ar-DZ', 'be', 'cy-GB', 'kk', 'km', 'ky', 'lb', 'mk', 'nb', 'nn', 'rm', 'tj' );
4203 3611 } else {
4204 - // Remove the languages unavailable for the datepicker
3612 + // remove the languages unavailable for the datepicker
4205 3613 $unset = array( 'fil', 'fr-CA', 'de-AT', 'de-CH', 'iw', 'hi', 'pt', 'pt-PT', 'es-419', 'mr', 'lo', 'kn', 'si', 'gu', 'bn', 'zu', 'ur', 'te', 'sw', 'am' );
4206 3614 }
4207 3615
4208 3616 $locales = array_diff_key( $locales, array_flip( $unset ) );
@@ -4213,13 +3621,14 @@
4213 3621 * @since 5.4.5 Added $args parameter with type.
4214 3622 *
4215 3623 * @param array<string,string> $locales
4216 3624 * @param array $args {
4217 - *
4218 3625 * @type string $type
4219 3626 * }
4220 3627 */
4221 - return apply_filters( 'frm_locales', $locales, compact( 'type' ) );
3628 + $locales = apply_filters( 'frm_locales', $locales, compact( 'type' ) );
3629 +
3630 + return $locales;
4222 3631 }
4223 3632
4224 3633 /**
4225 3634 * @return string
@@ -4226,14 +3635,12 @@
4226 3635 */
4227 3636 public static function get_menu_icon_class() {
4228 3637 if ( is_callable( 'FrmProAppHelper::get_settings' ) ) {
4229 3638 $settings = FrmProAppHelper::get_settings();
4230 -
4231 3639 if ( is_object( $settings ) && ! empty( $settings->menu_icon ) ) {
4232 3640 return $settings->menu_icon;
4233 3641 }
4234 3642 }
4235 -
4236 3643 return 'frmfont frm_logo_icon';
4237 3644 }
4238 3645
4239 3646 /**
@@ -4251,9 +3658,10 @@
4251 3658 * @type array $input_attrs Attributes of value input.
4252 3659 * }
4253 3660 */
4254 3661 public static function images_dropdown( $args ) {
4255 - $args = self::fill_default_images_dropdown_args( $args );
3662 + $args = self::fill_default_images_dropdown_args( $args );
3663 +
4256 3664 $input_attrs_str = self::get_images_dropdown_input_attrs( $args );
4257 3665 ob_start();
4258 3666 include self::plugin_path() . '/classes/views/shared/images-dropdown.php';
4259 3667 $output = ob_get_clean();
@@ -4274,9 +3682,8 @@
4274 3682 *
4275 3683 * @since 5.0.04
4276 3684 *
4277 3685 * @param array $args The arguments.
4278 - *
4279 3686 * @return array
4280 3687 */
4281 3688 private static function fill_default_images_dropdown_args( $args ) {
4282 3689 $defaults = array(
@@ -4289,8 +3696,14 @@
4289 3696
4290 3697 $new_args['options'] = (array) $new_args['options'];
4291 3698 $new_args['input_attrs'] = (array) $new_args['input_attrs'];
4292 3699
3700 + // Set the number of columns.
3701 + $new_args['col_class'] = ceil( 12 / count( $new_args['options'] ) );
3702 + if ( $new_args['col_class'] > 6 ) {
3703 + $new_args['col_class'] = ceil( $new_args['col_class'] / 2 );
3704 + }
3705 +
4293 3706 /**
4294 3707 * Allows modifying the arguments of images_dropdown() method.
4295 3708 *
4296 3709 * @since 5.0.04
@@ -4306,9 +3719,8 @@
4306 3719 *
4307 3720 * @since 5.0.04
4308 3721 *
4309 3722 * @param array $args The arguments.
4310 - *
4311 3723 * @return string
4312 3724 */
4313 3725 private static function get_images_dropdown_input_attrs( $args ) {
4314 3726 $input_attrs = $args['input_attrs'];
@@ -4315,9 +3727,8 @@
4315 3727 $input_attrs['type'] = 'radio';
4316 3728 $input_attrs['name'] = $args['name'];
4317 3729
4318 3730 $input_attrs_str = '';
4319 -
4320 3731 foreach ( $input_attrs as $key => $input_attr ) {
4321 3732 $input_attrs_str .= ' ' . sprintf( '%s="%s"', esc_attr( $key ), esc_attr( $input_attr ) );
4322 3733 }
4323 3734
@@ -4333,13 +3744,8 @@
4333 3744 }
4334 3745
4335 3746 /**
4336 3747 * @since 6.7.1
4337 - *
4338 - * @param array $option Option data.
4339 - * @param array $args The arguments of images_dropdown() method.
4340 - *
4341 - * @return array
4342 3748 */
4343 3749 public static function get_images_dropdown_atts( $option, $args ) {
4344 3750 $image = self::get_images_dropdown_option_image( $option, $args );
4345 3751 $classes = self::get_images_dropdown_option_classes( $option, $args );
@@ -4353,9 +3759,8 @@
4353 3759 * @since 5.0.04
4354 3760 *
4355 3761 * @param array $option Option data.
4356 3762 * @param array $args The arguments of images_dropdown() method.
4357 - *
4358 3763 * @return string
4359 3764 */
4360 3765 private static function get_images_dropdown_option_image( $option, $args ) {
4361 3766 $image = self::icon_by_class(
@@ -4384,9 +3789,8 @@
4384 3789 * @since 5.0.04
4385 3790 *
4386 3791 * @param array $option Option data.
4387 3792 * @param array $args The arguments of images_dropdown() method.
4388 - *
4389 3793 * @return string
4390 3794 */
4391 3795 private static function get_images_dropdown_option_classes( $option, $args ) {
4392 3796 $classes = '';
@@ -4414,19 +3818,17 @@
4414 3818 * @since 5.0.04
4415 3819 *
4416 3820 * @param array $option Option data.
4417 3821 * @param array $args The arguments of images_dropdown() method.
4418 - *
4419 3822 * @return string
4420 3823 */
4421 3824 private static function get_images_dropdown_option_html_attrs( $option, $args ) {
4422 3825 $html_attrs = '';
4423 -
4424 3826 if ( ! empty( $option['custom_attrs'] ) && is_array( $option['custom_attrs'] ) ) {
4425 3827 $html_attrs_arr = array();
4426 3828
4427 3829 foreach ( $option['custom_attrs'] as $key => $value ) {
4428 - if ( in_array( $key, array( 'type', 'class', 'data-value' ), true ) ) {
3830 + if ( in_array( $key, array( 'type', 'class', 'data-value' ) ) ) {
4429 3831 continue;
4430 3832 }
4431 3833
4432 3834 $html_attrs_arr[] = sprintf( '%s="%s"', esc_attr( $key ), esc_attr( $value ) );
@@ -4484,9 +3886,8 @@
4484 3886 * @since 5.0.07
4485 3887 *
4486 3888 * @param array $values
4487 3889 * @param array $keys
4488 - *
4489 3890 * @return array
4490 3891 */
4491 3892 public static function maybe_filter_array( $values, $keys ) {
4492 3893 $allow_unfiltered_html = self::allow_unfiltered_html();
@@ -4511,14 +3912,13 @@
4511 3912 * @since 5.0.13
4512 3913 *
4513 3914 * @param string $value
4514 3915 * @param array|string $allowed 'all' for everything included as defaults.
4515 - *
4516 3916 * @return string
4517 3917 */
4518 3918 public static function maybe_kses( $value, $allowed = 'all' ) {
4519 3919 if ( self::should_never_allow_unfiltered_html() ) {
4520 - return self::kses( $value, $allowed );
3920 + $value = self::kses( $value, $allowed );
4521 3921 }
4522 3922 return $value;
4523 3923 }
4524 3924
@@ -4528,18 +3928,17 @@
4528 3928 * @since 6.11.2
4529 3929 *
4530 3930 * @param string $key
4531 3931 * @param string $context Either 'display' or 'update'. On update, we want to allow a few keys that are never displayed.
4532 - *
4533 3932 * @return bool
4534 3933 */
4535 3934 public static function input_key_is_safe( $key, $context = 'display' ) {
4536 3935 if ( 'update' === $context && in_array( $key, array( 'opt', 'label' ), true ) ) {
4537 3936 $safe = true;
4538 - } elseif ( str_starts_with( $key, 'data-' ) ) {
3937 + } elseif ( 0 === strpos( $key, 'data-' ) ) {
4539 3938 // Allow all data attributes.
4540 3939 $safe = true;
4541 - } elseif ( str_starts_with( $key, 'aria-' ) ) {
3940 + } elseif ( 0 === strpos( $key, 'aria-' ) ) {
4542 3941 // Allow all aria attributes.
4543 3942 $safe = true;
4544 3943 } else {
4545 3944 $safe_keys = array(
@@ -4581,9 +3980,16 @@
4581 3980
4582 3981 /**
4583 3982 * @since 5.0.16
4584 3983 *
4585 - * @param string $medium
3984 + * @return bool
3985 + */
3986 + public static function show_landing_pages() {
3987 + return self::show_new_feature( 'landing' );
3988 + }
3989 +
3990 + /**
3991 + * @since 5.0.16
4586 3992 *
4587 3993 * @return array
4588 3994 */
4589 3995 public static function get_landing_page_upgrade_data_params( $medium = 'landing' ) {
@@ -4591,9 +3997,8 @@
4591 3997 'medium' => $medium,
4592 3998 'upgrade' => __( 'Form Landing Pages', 'formidable' ),
4593 3999 'message' => __( 'Easily manage a landing page for your form. Upgrade to get form landing pages.', 'formidable' ),
4594 4000 'screenshot' => 'landing.png',
4595 - 'learn-more' => self::get_doc_url( 'landing-page-forms', 'form-landing-page-settings', false ),
4596 4001 );
4597 4002 return self::get_upgrade_data_params( 'landing', $params );
4598 4003 }
4599 4004
@@ -4600,35 +4005,24 @@
4600 4005 /**
4601 4006 * @since 5.0.17
4602 4007 *
4603 4008 * @param string $feature
4604 - *
4605 4009 * @return bool
4606 4010 */
4607 4011 public static function show_new_feature( $feature ) {
4608 4012 $link = FrmAddonsController::install_link( $feature );
4609 -
4610 - if ( array_key_exists( 'status', $link ) || array_key_exists( 'class', $link ) ) {
4611 - return true;
4612 - }
4613 -
4614 - return 'coupons' === $feature && class_exists( 'FrmCouponsAppController' );
4013 + return array_key_exists( 'status', $link ) || array_key_exists( 'class', $link );
4615 4014 }
4616 4015
4617 4016 /**
4618 - * Enhances upgrade data parameters with installation link and plan requirement information.
4619 - *
4620 4017 * @since 5.0.17
4621 4018 *
4622 - * @param string $plugin The plugin slug to get installation data for.
4623 - * @param array $params Initial parameters for the upgrade data.
4624 - * @param bool $detailed Whether to include detailed information.
4625 - *
4626 - * @return array Modified parameters with installation data.
4019 + * @param string $plugin
4020 + * @param array $params
4021 + * @return array
4627 4022 */
4628 - public static function get_upgrade_data_params( $plugin, $params, $detailed = false ) {
4023 + public static function get_upgrade_data_params( $plugin, $params ) {
4629 4024 $link = FrmAddonsController::install_link( $plugin );
4630 -
4631 4025 if ( ! $link ) {
4632 4026 return $params;
4633 4027 }
4634 4028
@@ -4634,20 +4028,15 @@
4634 4028
4635 4029 if ( ! empty( $link['url'] ) && self::pro_is_installed() ) {
4636 4030 $params['oneclick'] = json_encode( $link );
4637 4031 unset( $params['message'] );
4638 -
4639 4032 if ( ! isset( $params['medium'] ) ) {
4640 4033 $params['medium'] = $plugin;
4641 4034 }
4642 4035 } else {
4643 - $params['requires'] = $params['requires'] ?? FrmFormsHelper::get_plan_required( $link );
4036 + $params['requires'] = FrmFormsHelper::get_plan_required( $link );
4644 4037 }
4645 4038
4646 - if ( $detailed ) {
4647 - $params['plugin-status'] = $link['status'] ?? '';
4648 - }
4649 -
4650 4039 return $params;
4651 4040 }
4652 4041
4653 4042 /**
@@ -4656,9 +4045,8 @@
4656 4045 *
4657 4046 * @since 5.0.17
4658 4047 *
4659 4048 * @param string $text
4660 - *
4661 4049 * @return bool
4662 4050 */
4663 4051 public static function ctype_xdigit( $text ) {
4664 4052 if ( function_exists( 'ctype_xdigit' ) ) {
@@ -4673,14 +4061,12 @@
4673 4061 * @since 5.2.01
4674 4062 */
4675 4063 public static function set_current_screen_and_hook_suffix() {
4676 4064 global $hook_suffix;
4677 -
4678 4065 if ( is_null( $hook_suffix ) ) {
4679 4066 // $hook_suffix gets used in substr so make sure it's not null. PHP 8.1 deprecates null in substr.
4680 4067 $hook_suffix = ''; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
4681 4068 }
4682 -
4683 4069 set_current_screen();
4684 4070 }
4685 4071
4686 4072 /**
@@ -4687,9 +4073,9 @@
4687 4073 * Shows pill text.
4688 4074 *
4689 4075 * @since 5.2.02
4690 4076 *
4691 - * @param string|null $text Text in the pill. Default is NEW.
4077 + * @param string $text Text in the pill. Default is NEW.
4692 4078 */
4693 4079 public static function show_pill_text( $text = null ) {
4694 4080 if ( null === $text ) {
4695 4081 $text = __( 'NEW', 'formidable' );
@@ -4702,9 +4088,8 @@
4702 4088 *
4703 4089 * @since 5.2.07
4704 4090 *
4705 4091 * @param mixed $num Number.
4706 - *
4707 4092 * @return false|int Returns `false` if the passed parameter is not number.
4708 4093 */
4709 4094 public static function count_decimals( $num ) {
4710 4095 if ( ! is_numeric( $num ) ) {
@@ -4712,9 +4097,8 @@
4712 4097 }
4713 4098
4714 4099 $num = (string) $num;
4715 4100 $parts = explode( '.', $num );
4716 -
4717 4101 if ( 1 === count( $parts ) ) {
4718 4102 return 0;
4719 4103 }
4720 4104
@@ -4796,20 +4180,17 @@
4796 4180 * @since 5.5.5
4797 4181 *
4798 4182 * @param string $url
4799 4183 * @param string $expected_extension
4800 - *
4801 4184 * @return bool
4802 4185 */
4803 4186 public static function validate_url_is_in_s3_bucket( $url, $expected_extension ) {
4804 - $file_is_in_expected_s3_bucket = str_starts_with( $url, 'https://s3.amazonaws.com/fp.strategy11.com' );
4805 -
4187 + $file_is_in_expected_s3_bucket = 0 === strpos( $url, 'https://s3.amazonaws.com/fp.strategy11.com' );
4806 4188 if ( ! $file_is_in_expected_s3_bucket ) {
4807 4189 return false;
4808 4190 }
4809 4191
4810 4192 $parsed = parse_url( $url );
4811 -
4812 4193 if ( ! is_array( $parsed ) ) {
4813 4194 // URL is malformed.
4814 4195 return false;
4815 4196 }
@@ -4815,10 +4196,14 @@
4815 4196 }
4816 4197
4817 4198 $path = $parsed['path'];
4818 4199 $ext = pathinfo( $path, PATHINFO_EXTENSION );
4819 - // The URL isn't to an XML file.
4820 - return $expected_extension === $ext;
4200 + if ( $expected_extension !== $ext ) {
4201 + // The URL isn't to an XML file.
4202 + return false;
4203 + }
4204 +
4205 + return true;
4821 4206 }
4822 4207
4823 4208 /**
4824 4209 * Display a dismissable warning message and save its dismissal state.
@@ -4826,9 +4211,8 @@
4826 4211 * @since 6.3
4827 4212 *
4828 4213 * @param string $message The warning message to display.
4829 4214 * @param string $option The unique identifier for the dismissal state of the message and the WP Ajax action.
4830 - *
4831 4215 * @return void
4832 4216 */
4833 4217 public static function add_dismissable_warning_message( $message = '', $option = '' ) {
4834 4218 if ( ! $message || ! $option ) {
@@ -4871,9 +4255,8 @@
4871 4255 *
4872 4256 * @since 6.3
4873 4257 *
4874 4258 * @param string $option The unique identifier for the dismissal state of the message.
4875 - *
4876 4259 * @return void
4877 4260 */
4878 4261 public static function dismiss_warning_message( $option = '' ) {
4879 4262 self::permission_check( 'frm_change_settings' );
@@ -4879,9 +4262,9 @@
4879 4262 self::permission_check( 'frm_change_settings' );
4880 4263 check_ajax_referer( 'frm_ajax', 'nonce' );
4881 4264
4882 4265 if ( $option ) {
4883 - update_option( $option, true, false );
4266 + update_option( $option, true, 'no' );
4884 4267 }
4885 4268
4886 4269 wp_send_json_success();
4887 4270 }
@@ -4895,8 +4278,17 @@
4895 4278 * @return string
4896 4279 */
4897 4280 public static function copy_for_lite_license() {
4898 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 +
4899 4291 return apply_filters( 'frm_license_type_text', $message );
4900 4292 }
4901 4293
4902 4294 /**
@@ -4902,9 +4294,8 @@
4902 4294 /**
4903 4295 * Removes scripts that are unnecessarily loaded across the pages!
4904 4296 *
4905 4297 * @since 6.9
4906 - *
4907 4298 * @return void
4908 4299 */
4909 4300 public static function dequeue_extra_global_scripts() {
4910 4301 wp_dequeue_script( 'frm-surveys-admin' );
@@ -4922,134 +4313,16 @@
4922 4313 * @return void
4923 4314 */
4924 4315 public static function tooltip_icon( $tooltip_text, $atts = array() ) {
4925 4316 $atts['title'] = $tooltip_text;
4926 -
4927 4317 if ( isset( $atts['class'] ) ) {
4928 4318 $atts['class'] .= ' frm_help';
4929 4319 } else {
4930 4320 $atts['class'] = 'frm_help';
4931 4321 }
4932 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
4933 4322 ?>
4934 4323 <span <?php self::array_to_html_params( $atts, true ); ?>>
4935 4324 <?php self::icon_by_class( 'frmfont frm_tooltip_icon' ); ?>
4936 4325 </span>
4937 4326 <?php
4938 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
4939 - }
4940 -
4941 - /**
4942 - * Prints errors for settings in onboarding wizard or template settings.
4943 - *
4944 - * @since 6.15
4945 - *
4946 - * @param array $args Args.
4947 - *
4948 - * @return void
4949 - */
4950 - public static function print_setting_error( $args ) {
4951 - $args = wp_parse_args(
4952 - $args,
4953 - array(
4954 - 'id' => '',
4955 - 'errors' => array(),
4956 - 'class' => '',
4957 - )
4958 - );
4959 -
4960 - $args['class'] .= ' frm-validation-error frm-mt-xs frm_hidden';
4961 -
4962 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
4963 - ?>
4964 - <span id="<?php echo esc_attr( $args['id'] ); ?>" class="<?php echo esc_attr( $args['class'] ); ?>">
4965 - <?php
4966 - if ( is_array( $args['errors'] ) ) {
4967 - foreach ( $args['errors'] as $key => $msg ) {
4968 - ?>
4969 - <span frm-error="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $msg ); ?></span>
4970 - <?php
4971 - }
4972 - } else {
4973 - echo '<span>' . esc_html( $args['errors'] ) . '</span>';
4974 - }
4975 - ?>
4976 - </span>
4977 - <?php
4978 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
4979 - }
4980 -
4981 - /**
4982 - * Check if GDPR is enabled.
4983 - *
4984 - * @since 6.19
4985 - *
4986 - * @return bool
4987 - */
4988 - public static function is_gdpr_enabled() {
4989 - $frm_settings = self::get_settings();
4990 - return $frm_settings->enable_gdpr || $frm_settings->no_ips || $frm_settings->custom_header_ip || $frm_settings->no_gdpr_cookies;
4991 - }
4992 -
4993 - /**
4994 - * Check if GDPR cookies are disabled.
4995 - *
4996 - * @since 6.19
4997 - *
4998 - * @return bool
4999 - */
5000 - public static function no_gdpr_cookies() {
5001 - $frm_settings = self::get_settings();
5002 - return $frm_settings->enable_gdpr && $frm_settings->no_gdpr_cookies;
5003 - }
5004 -
5005 - /**
5006 - * Check if a string is valid UTF-8.
5007 - *
5008 - * @since 6.24
5009 - *
5010 - * @param string $string The string to check.
5011 - *
5012 - * @return bool
5013 - */
5014 - public static function is_valid_utf8( $string ) {
5015 - // wp_is_valid_utf8 is added in WP 6.9.
5016 - if ( function_exists( 'wp_is_valid_utf8' ) ) {
5017 - return wp_is_valid_utf8( $string );
5018 - }
5019 -
5020 - // As of WP 6.9, seems_utf8 is deprecated.
5021 - return function_exists( 'seems_utf8' ) ? seems_utf8( $string ) : false;
5022 - }
5023 -
5024 - /**
5025 - * Get a documentation URL with UTM parameters and affiliate tracking.
5026 - *
5027 - * @since 6.26
5028 - *
5029 - * @param string $path The relative path to append to the base URL.
5030 - * @param string $campaign The campaign to use for UTM parameters.
5031 - * @param bool $add_kb_base Whether to prepend 'knowledgebase/' to the path. Default true.
5032 - *
5033 - * @return string The processed URL with UTM parameters and affiliate tracking.
5034 - */
5035 - public static function get_doc_url( $path, $campaign, $add_kb_base = true ) {
5036 - $path = trim( $path, '/' );
5037 -
5038 - if ( $add_kb_base ) {
5039 - $path = 'knowledgebase/' . $path;
5040 - }
5041 -
5042 - return self::maybe_add_missing_utm( 'https://formidableforms.com/' . $path, array( 'campaign' => $campaign ) );
5043 - }
5044 -
5045 - /**
5046 - * @since 5.0.16
5047 - * @deprecated 6.26
5048 - *
5049 - * @return bool
5050 - */
5051 - public static function show_landing_pages() {
5052 - _deprecated_function( __METHOD__, '6.26' );
5053 - return true;
5054 4327 }
5055 4328 }