Completed
Pull Request — master (#136)
by Stephanie
02:15
created

FrmAppHelper::maybe_json_encode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	die( 'You are not allowed to call this page directly.' );
4
}
5
6
class FrmAppHelper {
7
	public static $db_version = 97; //version of the database we are moving to
8
	public static $pro_db_version = 37; //deprecated
9
	public static $font_version = 7;
10
11
	/**
12
	 * @since 2.0
13
	 */
14
	public static $plug_version = '4.03.05';
15
16
	/**
17
	 * @since 1.07.02
18
	 *
19
	 * @param none
20
	 *
21
	 * @return string The version of this plugin
22
	 */
23
	public static function plugin_version() {
24
		return self::$plug_version;
25
	}
26
27
	public static function plugin_folder() {
28
		return basename( self::plugin_path() );
29
	}
30
31
	public static function plugin_path() {
32
		return dirname( dirname( dirname( __FILE__ ) ) );
33
	}
34
35
	public static function plugin_url() {
36
		// Prevously FRM_URL constant.
37
		return plugins_url( '', self::plugin_path() . '/formidable.php' );
38
	}
39
40
	public static function relative_plugin_url() {
41
		return str_replace( array( 'https:', 'http:' ), '', self::plugin_url() );
42
	}
43
44
	/**
45
	 * @return string Site URL
46
	 */
47
	public static function site_url() {
48
		return site_url();
49
	}
50
51
	/**
52
	 * Get the name of this site
53
	 * Used for [sitename] shortcode
54
	 *
55
	 * @since 2.0
56
	 * @return string
57
	 */
58
	public static function site_name() {
59
		return get_option( 'blogname' );
60
	}
61
62
	public static function make_affiliate_url( $url ) {
63
		$affiliate_id = self::get_affiliate();
64
		if ( ! empty( $affiliate_id ) ) {
65
			$url = str_replace( array( 'http://', 'https://' ), '', $url );
66
			$url = 'http://www.shareasale.com/r.cfm?u=' . absint( $affiliate_id ) . '&b=841990&m=64739&afftrack=plugin&urllink=' . urlencode( $url );
67
		}
68
69
		return $url;
70
	}
71
72
	public static function get_affiliate() {
73
		return absint( apply_filters( 'frm_affiliate_id', 0 ) );
74
	}
75
76
	/**
77
	 * @since 3.04.02
78
	 * @param array|string $args
79
	 * @param string       $page
80
	 */
81
	public static function admin_upgrade_link( $args, $page = '' ) {
82
		if ( empty( $page ) ) {
83
			$page = 'https://formidableforms.com/lite-upgrade/';
84
		} else {
85
			$page = 'https://formidableforms.com/' . $page;
86
		}
87
88
		$anchor = '';
89
		if ( is_array( $args ) ) {
90
			$medium  = $args['medium'];
91
			$content = $args['content'];
92
			if ( isset( $args['anchor'] ) ) {
93
				$anchor = '#' . $args['anchor'];
94
			}
95
		} else {
96
			$medium = $args;
97
		}
98
99
		$query_args = array(
100
			'utm_source'   => 'WordPress',
101
			'utm_medium'   => $medium,
102
			'utm_campaign' => 'liteplugin',
103
		);
104
105
		if ( isset( $content ) ) {
106
			$query_args['utm_content'] = $content;
107
		}
108
109
		if ( is_array( $args ) && isset( $args['param'] ) ) {
110
			$query_args['f'] = $args['param'];
111
		}
112
113
		$link = add_query_arg( $query_args, $page ) . $anchor;
114
		return self::make_affiliate_url( $link );
115
	}
116
117
	/**
118
	 * Get the Formidable settings
119
	 *
120
	 * @since 2.0
121
	 *
122
	 * @param array $args - May include the form id when values need translation.
123
	 * @return FrmSettings $frm_setings
124
	 */
125
	public static function get_settings( $args = array() ) {
126
		global $frm_settings;
127
		if ( empty( $frm_settings ) ) {
128
			$frm_settings = new FrmSettings( $args );
129
		} elseif ( isset( $args['current_form'] ) ) {
130
			// If the global has already been set, allow strings to be filtered.
131
			$frm_settings->maybe_filter_for_form( $args );
132
		}
133
134
		return $frm_settings;
135
	}
136
137
	public static function get_menu_name() {
138
		$frm_settings = self::get_settings();
139
140
		return $frm_settings->menu;
141
	}
142
143
	/**
144
	 * @since 3.05
145
	 */
146
	public static function svg_logo( $atts = array() ) {
147
		$defaults = array(
148
			'height' => 18,
149
			'width'  => 18,
150
			'fill'   => '#4d4d4d',
151
			'orange' => '#f05a24',
152
		);
153
		$atts     = array_merge( $defaults, $atts );
154
155
		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'] ) . '">
156
			<path fill="' . esc_attr( $atts['orange'] ) . '" d="M289.6 384h140v76h-140z"/>
157
			<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"/>
158
		</svg>';
159
	}
160
161
	/**
162
	 * @since 4.0
163
	 */
164
	public static function show_logo( $atts = array() ) {
165
		echo self::kses( self::svg_logo( $atts ), 'all' ); // WPCS: XSS ok.
166
	}
167
168
	/**
169
	 * @since 4.03.02
170
	 */
171
	public static function show_header_logo() {
172
		$icon = self::svg_logo(
173
			array(
174
				'height' => 35,
175
				'width'  => 35,
176
			)
177
		);
178
179
		$new_icon = apply_filters( 'frm_icon', $icon, true );
180
		if ( $new_icon !== $icon ) {
181
			if ( strpos( $new_icon, '<svg' ) === 0 ) {
182
				$icon = str_replace( 'viewBox="0 0 20', 'width="30" height="35" style="color:#929699" viewBox="0 0 20', $new_icon );
183
			} else {
184
				// Show nothing if it isn't an SVG.
185
				$icon = '<div style="height:39px"></div>';
186
			}
187
		}
188
		echo self::kses( $icon, 'all' ); // WPCS: XSS ok.
189
	}
190
191
	/**
192
	 * @since 2.02.04
193
	 */
194
	public static function ips_saved() {
195
		$frm_settings = self::get_settings();
196
197
		return ! $frm_settings->no_ips;
198
	}
199
200
	public static function pro_is_installed() {
201
		return apply_filters( 'frm_pro_installed', false );
202
	}
203
204
	public static function is_formidable_admin() {
205
		$page          = self::simple_get( 'page', 'sanitize_title' );
206
		$is_formidable = strpos( $page, 'formidable' ) !== false;
207
		if ( empty( $page ) ) {
208
			global $pagenow;
209
			$post_type     = self::simple_get( 'post_type', 'sanitize_title' );
210
			$is_formidable = ( $post_type == 'frm_display' );
211
			if ( empty( $post_type ) && $pagenow == 'post.php' ) {
212
				global $post;
213
				$is_formidable = ( $post && $post->post_type == 'frm_display' );
214
			}
215
		}
216
217
		return $is_formidable;
218
	}
219
220
	/**
221
	 * Check for certain page in Formidable settings
222
	 *
223
	 * @since 2.0
224
	 *
225
	 * @param string $page The name of the page to check
226
	 *
227
	 * @return boolean
228
	 */
229
	public static function is_admin_page( $page = 'formidable' ) {
230
		global $pagenow;
231
		$get_page = self::simple_get( 'page', 'sanitize_title' );
232
		if ( $pagenow ) {
233
			// allow this to be true during ajax load i.e. ajax form builder loading
234
			return ( $pagenow == 'admin.php' || $pagenow == 'admin-ajax.php' ) && $get_page == $page;
235
		}
236
237
		return is_admin() && $get_page == $page;
238
	}
239
240
	/**
241
	 * If the current page is for editing or creating a view.
242
	 * Returns false for the views listing page.
243
	 *
244
	 * @since 4.0
245
	 */
246
	public static function is_view_builder_page() {
247
		global $pagenow;
248
249
		if ( $pagenow !== 'post.php' && $pagenow !== 'post-new.php' ) {
250
			return false;
251
		}
252
253
		$post_type = self::simple_get( 'post_type', 'sanitize_title' );
254
255
		if ( empty( $post_type ) ) {
256
			$post_id = self::simple_get( 'post', 'absint' );
257
			$post    = get_post( $post_id );
258
			if ( ! empty( $post ) ) {
259
				$post_type = $post->post_type;
260
			}
261
		}
262
263
		return $post_type === 'frm_display';
264
	}
265
266
	/**
267
	 * Check for the form preview page
268
	 *
269
	 * @since 2.0
270
	 *
271
	 * @param None
272
	 *
273
	 * @return boolean
274
	 */
275
	public static function is_preview_page() {
276
		global $pagenow;
277
		$action = self::simple_get( 'action', 'sanitize_title' );
278
279
		return $pagenow && $pagenow == 'admin-ajax.php' && $action == 'frm_forms_preview';
280
	}
281
282
	/**
283
	 * Check for ajax except the form preview page
284
	 *
285
	 * @since 2.0
286
	 *
287
	 * @param None
288
	 *
289
	 * @return boolean
290
	 */
291
	public static function doing_ajax() {
292
		return self::wp_doing_ajax() && ! self::is_preview_page();
293
	}
294
295
	public static function js_suffix() {
296
		return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
297
	}
298
299
	/**
300
	 * Use the WP 4.7 wp_doing_ajax function
301
	 *
302
	 * @since 2.05.07
303
	 */
304
	public static function wp_doing_ajax() {
305
		if ( function_exists( 'wp_doing_ajax' ) ) {
306
			$doing_ajax = wp_doing_ajax();
307
		} else {
308
			$doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
309
		}
310
311
		return $doing_ajax;
312
	}
313
314
	/**
315
	 * @since 2.0.8
316
	 */
317
	public static function prevent_caching() {
318
		global $frm_vars;
319
320
		return isset( $frm_vars['prevent_caching'] ) && $frm_vars['prevent_caching'];
321
	}
322
323
	/**
324
	 * Check if on an admin page
325
	 *
326
	 * @since 2.0
327
	 *
328
	 * @param None
329
	 *
330
	 * @return boolean
331
	 */
332
	public static function is_admin() {
333
		return is_admin() && ! self::wp_doing_ajax();
334
	}
335
336
	/**
337
	 * Check if value contains blank value or empty array
338
	 *
339
	 * @since 2.0
340
	 *
341
	 * @param mixed $value - value to check
342
	 * @param string
343
	 *
344
	 * @return boolean
345
	 */
346
	public static function is_empty_value( $value, $empty = '' ) {
347
		return ( is_array( $value ) && empty( $value ) ) || $value === $empty;
348
	}
349
350
	public static function is_not_empty_value( $value, $empty = '' ) {
351
		return ! self::is_empty_value( $value, $empty );
352
	}
353
354
	/**
355
	 * Get any value from the $_SERVER
356
	 *
357
	 * @since 2.0
358
	 *
359
	 * @param string $value
360
	 *
361
	 * @return string
362
	 */
363
	public static function get_server_value( $value ) {
364
		return isset( $_SERVER[ $value ] ) ? wp_strip_all_tags( wp_unslash( $_SERVER[ $value ] ) ) : '';
365
	}
366
367
	/**
368
	 * Check for the IP address in several places
369
	 * Used by [ip] shortcode
370
	 *
371
	 * @return string The IP address of the current user
372
	 */
373
	public static function get_ip_address() {
374
		$ip_options = array(
375
			'HTTP_CLIENT_IP',
376
			'HTTP_CF_CONNECTING_IP',
377
			'HTTP_X_FORWARDED_FOR',
378
			'HTTP_X_FORWARDED',
379
			'HTTP_X_CLUSTER_CLIENT_IP',
380
			'HTTP_X_REAL_IP',
381
			'HTTP_FORWARDED_FOR',
382
			'HTTP_FORWARDED',
383
			'REMOTE_ADDR',
384
		);
385
		$ip = '';
386
		foreach ( $ip_options as $key ) {
387
			if ( ! isset( $_SERVER[ $key ] ) ) {
388
				continue;
389
			}
390
391
			$key = self::get_server_value( $key );
392
			foreach ( explode( ',', $key ) as $ip ) {
393
				$ip = trim( $ip ); // just to be safe.
394
395
				if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
396
					return sanitize_text_field( $ip );
397
				}
398
			}
399
		}
400
401
		return sanitize_text_field( $ip );
402
	}
403
404
	public static function get_param( $param, $default = '', $src = 'get', $sanitize = '' ) {
405
		if ( strpos( $param, '[' ) ) {
406
			$params = explode( '[', $param );
407
			$param  = $params[0];
408
		}
409
410
		if ( $src == 'get' ) {
411
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
412
			$value = isset( $_POST[ $param ] ) ? wp_unslash( $_POST[ $param ] ) : ( isset( $_GET[ $param ] ) ? wp_unslash( $_GET[ $param ] ) : $default );
413
			if ( ! isset( $_POST[ $param ] ) && isset( $_GET[ $param ] ) && ! is_array( $value ) ) {
414
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
415
				$value = htmlspecialchars_decode( wp_unslash( $_GET[ $param ] ) );
416
			}
417
			self::sanitize_value( $sanitize, $value );
418
		} else {
419
			$value = self::get_simple_request(
420
				array(
421
					'type'     => $src,
422
					'param'    => $param,
423
					'default'  => $default,
424
					'sanitize' => $sanitize,
425
				)
426
			);
427
		}
428
429
		if ( isset( $params ) && is_array( $value ) && ! empty( $value ) ) {
430
			foreach ( $params as $k => $p ) {
431
				if ( ! $k || ! is_array( $value ) ) {
432
					continue;
433
				}
434
435
				$p     = trim( $p, ']' );
436
				$value = isset( $value[ $p ] ) ? $value[ $p ] : $default;
437
			}
438
		}
439
440
		return $value;
441
	}
442
443 View Code Duplication
	public static function get_post_param( $param, $default = '', $sanitize = '', $serialized = false ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
444
		return self::get_simple_request(
445
			array(
446
				'type'     => 'post',
447
				'param'    => $param,
448
				'default'  => $default,
449
				'sanitize' => $sanitize,
450
				'serialized' => $serialized,
451
			)
452
		);
453
	}
454
455
	/**
456
	 * @since 2.0
457
	 *
458
	 * @param string $param
459
	 * @param string $sanitize
460
	 * @param string $default
461
	 *
462
	 * @return string|array
463
	 */
464 View Code Duplication
	public static function simple_get( $param, $sanitize = 'sanitize_text_field', $default = '' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
465
		return self::get_simple_request(
466
			array(
467
				'type'     => 'get',
468
				'param'    => $param,
469
				'default'  => $default,
470
				'sanitize' => $sanitize,
471
			)
472
		);
473
	}
474
475
	/**
476
	 * Get a GET/POST/REQUEST value and sanitize it
477
	 *
478
	 * @since 2.0.6
479
	 *
480
	 * @param array $args
481
	 *
482
	 * @return string|array
483
	 */
484
	public static function get_simple_request( $args ) {
485
		$defaults = array(
486
			'param'    => '',
487
			'default'  => '',
488
			'type'     => 'get',
489
			'sanitize' => 'sanitize_text_field',
490
			'serialized' => false,
491
		);
492
		$args     = wp_parse_args( $args, $defaults );
493
494
		$value = $args['default'];
495
		if ( $args['type'] == 'get' ) {
496 View Code Duplication
			if ( $_GET && isset( $_GET[ $args['param'] ] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
497
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
498
				$value = wp_unslash( $_GET[ $args['param'] ] );
499
			}
500
		} elseif ( $args['type'] == 'post' ) {
501
			if ( isset( $_POST[ $args['param'] ] ) ) {
502
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
503
				$value = wp_unslash( $_POST[ $args['param'] ] );
504
				if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
505
					self::unserialize_or_decode( $value );
506
				}
507
			}
508 View Code Duplication
		} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
509
			if ( isset( $_REQUEST[ $args['param'] ] ) ) {
510
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
511
				$value = wp_unslash( $_REQUEST[ $args['param'] ] );
512
			}
513
		}
514
515
		self::sanitize_value( $args['sanitize'], $value );
516
517
		return $value;
518
	}
519
520
	/**
521
	 * Preserve backslashes in a value, but make sure value doesn't get compounding slashes
522
	 *
523
	 * @since 2.0.8
524
	 *
525
	 * @param string $value
526
	 *
527
	 * @return string $value
528
	 */
529
	public static function preserve_backslashes( $value ) {
530
		// If backslashes have already been added, don't add them again
531
		if ( strpos( $value, '\\\\' ) === false ) {
532
			$value = addslashes( $value );
533
		}
534
535
		return $value;
536
	}
537
538
	public static function sanitize_value( $sanitize, &$value ) {
539
		if ( ! empty( $sanitize ) ) {
540
			if ( is_array( $value ) ) {
541
				$temp_values = $value;
542
				foreach ( $temp_values as $k => $v ) {
543
					self::sanitize_value( $sanitize, $value[ $k ] );
544
				}
545
			} else {
546
				$value = call_user_func( $sanitize, $value );
547
			}
548
		}
549
	}
550
551
	public static function sanitize_request( $sanitize_method, &$values ) {
552
		$temp_values = $values;
553
		foreach ( $temp_values as $k => $val ) {
554
			if ( isset( $sanitize_method[ $k ] ) ) {
555
				$values[ $k ] = call_user_func( $sanitize_method[ $k ], $val );
556
			}
557
		}
558
	}
559
560
	/**
561
	 * @since 4.0.04
562
	 */
563
	public static function sanitize_with_html( &$value ) {
564
		self::sanitize_value( 'wp_kses_post', $value );
565
		self::decode_specialchars( $value );
566
	}
567
568
	/**
569
	 * Do wp_specialchars_decode to get back '&' that wp_kses_post might have turned to '&amp;'
570
	 * this MUST be done, else we'll be back to the '& entity' problem.
571
	 *
572
	 * @since 4.0.04
573
	 */
574
	public static function decode_specialchars( &$value ) {
575
		if ( is_array( $value ) ) {
576
			$temp_values = $value;
577
			foreach ( $temp_values as $k => $v ) {
578
				self::decode_specialchars( $value[ $k ] );
579
			}
580
		} else {
581
			self::decode_amp( $value );
582
		}
583
	}
584
585
	/**
586
	 * The wp_specialchars_decode function changes too much.
587
	 * This will leave HTML as is, but still convert &.
588
	 * Adapted from wp_specialchars_decode().
589
	 *
590
	 * @since 4.03.01
591
	 *
592
	 * @param string $string The string to prep.
593
	 */
594
	private static function decode_amp( &$string ) {
595
		// Don't bother if there are no entities - saves a lot of processing
596
		if ( empty( $string ) || strpos( $string, '&' ) === false ) {
597
			return;
598
		}
599
600
		$translation = array(
601
			'&quot;'  => '"',
602
			'&#034;'  => '"',
603
			'&#x22;'  => '"',
604
			'&lt; '   => '< ', // The space preserves the HTML.
605
			'&#060; ' => '< ', // The space preserves the HTML.
606
			'&gt;'    => '>',
607
			'&#062;'  => '>',
608
			'&amp;'   => '&',
609
			'&#038;'  => '&',
610
			'&#x26;'  => '&',
611
		);
612
613
		$translation_preg = array(
614
			'/&#0*34;/'   => '&#034;',
615
			'/&#x0*22;/i' => '&#x22;',
616
			'/&#0*60;/'   => '&#060;',
617
			'/&#0*62;/'   => '&#062;',
618
			'/&#0*38;/'   => '&#038;',
619
			'/&#x0*26;/i' => '&#x26;',
620
		);
621
622
		// Remove zero padding on numeric entities
623
		$string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string );
624
625
		// Replace characters according to translation table
626
		$string = strtr( $string, $translation );
627
	}
628
629
	/**
630
	 * Sanitize the value, and allow some HTML
631
	 *
632
	 * @since 2.0
633
	 *
634
	 * @param string $value
635
	 * @param array|string $allowed 'all' for everything included as defaults
636
	 *
637
	 * @return string
638
	 */
639
	public static function kses( $value, $allowed = array() ) {
640
		$allowed_html = self::allowed_html( $allowed );
641
642
		return wp_kses( $value, $allowed_html );
643
	}
644
645
	/**
646
	 * @since 2.05.03
647
	 */
648
	private static function allowed_html( $allowed ) {
649
		$html         = self::safe_html();
650
		$allowed_html = array();
651
		if ( $allowed == 'all' ) {
652
			$allowed_html = $html;
653
		} elseif ( ! empty( $allowed ) ) {
654
			foreach ( (array) $allowed as $a ) {
655
				$allowed_html[ $a ] = isset( $html[ $a ] ) ? $html[ $a ] : array();
656
			}
657
		}
658
659
		return apply_filters( 'frm_striphtml_allowed_tags', $allowed_html );
660
	}
661
662
	/**
663
	 * @since 2.05.03
664
	 */
665
	private static function safe_html() {
666
		$allow_class = array(
667
			'class' => true,
668
			'id'    => true,
669
		);
670
671
		return array(
672
			'a'          => array(
673
				'class'  => true,
674
				'href'   => true,
675
				'id'     => true,
676
				'rel'    => true,
677
				'target' => true,
678
				'title'  => true,
679
			),
680
			'abbr'       => array(
681
				'title' => true,
682
			),
683
			'aside'      => $allow_class,
684
			'b'          => array(),
685
			'blockquote' => array(
686
				'cite' => true,
687
			),
688
			'br'         => array(),
689
			'cite'       => array(
690
				'title' => true,
691
			),
692
			'code'       => array(),
693
			'defs'       => array(),
694
			'del'        => array(
695
				'datetime' => true,
696
				'title'    => true,
697
			),
698
			'dd'         => array(),
699
			'div'        => array(
700
				'class' => true,
701
				'id'    => true,
702
				'title' => true,
703
				'style' => true,
704
			),
705
			'dl'         => array(),
706
			'dt'         => array(),
707
			'em'         => array(),
708
			'h1'         => $allow_class,
709
			'h2'         => $allow_class,
710
			'h3'         => $allow_class,
711
			'h4'         => $allow_class,
712
			'h5'         => $allow_class,
713
			'h6'         => $allow_class,
714
			'i'          => array(
715
				'class' => true,
716
				'id'    => true,
717
				'icon'  => true,
718
				'style' => true,
719
			),
720
			'img'        => array(
721
				'alt'    => true,
722
				'class'  => true,
723
				'height' => true,
724
				'id'     => true,
725
				'src'    => true,
726
				'width'  => true,
727
			),
728
			'li'         => $allow_class,
729
			'ol'         => $allow_class,
730
			'p'          => $allow_class,
731
			'path'       => array(
732
				'd'    => true,
733
				'fill' => true,
734
			),
735
			'pre'        => array(),
736
			'q'          => array(
737
				'cite'  => true,
738
				'title' => true,
739
			),
740
			'rect'       => array(
741
				'class'  => true,
742
				'fill'   => true,
743
				'height' => true,
744
				'width'  => true,
745
				'x'      => true,
746
				'y'      => true,
747
			),
748
			'section'    => $allow_class,
749
			'span'       => array(
750
				'class' => true,
751
				'id'    => true,
752
				'title' => true,
753
				'style' => true,
754
			),
755
			'strike'     => array(),
756
			'strong'     => array(),
757
			'symbol'     => array(
758
				'class'   => true,
759
				'id'      => true,
760
				'viewbox' => true,
761
			),
762
			'svg'        => array(
763
				'class'   => true,
764
				'id'      => true,
765
				'xmlns'   => true,
766
				'viewbox' => true,
767
				'width'   => true,
768
				'height'  => true,
769
				'style'   => true,
770
			),
771
			'use'        => array(
772
				'href'   => true,
773
				'xlink:href' => true,
774
			),
775
			'ul'         => $allow_class,
776
		);
777
	}
778
779
	/**
780
	 * Used when switching the action for a bulk action
781
	 *
782
	 * @since 2.0
783
	 */
784
	public static function remove_get_action() {
785
		if ( ! isset( $_GET ) ) {
786
			return;
787
		}
788
789
		$action_name = isset( $_GET['action'] ) ? 'action' : ( isset( $_GET['action2'] ) ? 'action2' : '' );
790
		if ( empty( $action_name ) ) {
791
			return;
792
		}
793
794
		$new_action = self::get_param( $action_name, '', 'get', 'sanitize_text_field' );
795
		if ( ! empty( $new_action ) ) {
796
			$_SERVER['REQUEST_URI'] = str_replace( '&action=' . $new_action, '', self::get_server_value( 'REQUEST_URI' ) );
797
		}
798
	}
799
800
	/**
801
	 * Check the WP query for a parameter
802
	 *
803
	 * @since 2.0
804
	 * @return string|array
805
	 */
806
	public static function get_query_var( $value, $param ) {
807
		if ( $value != '' ) {
808
			return $value;
809
		}
810
811
		global $wp_query;
812
		if ( isset( $wp_query->query_vars[ $param ] ) ) {
813
			$value = $wp_query->query_vars[ $param ];
814
		}
815
816
		return $value;
817
	}
818
819
	/**
820
	 * Try to show the SVG if possible. Otherwise, use the font icon.
821
	 *
822
	 * @since 4.0.02
823
	 * @param string $class
824
	 * @param array  $atts
825
	 */
826
	public static function icon_by_class( $class, $atts = array() ) {
827
		$echo = ! isset( $atts['echo'] ) || $atts['echo'];
828
		if ( isset( $atts['echo'] ) ) {
829
			unset( $atts['echo'] );
830
		}
831
832
		$html_atts = self::array_to_html_params( $atts );
833
834
		$icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
835
		if ( $icon === $class ) {
836
			$icon = '<i class="' . esc_attr( $class ) . '"' . $html_atts . '></i>';
837
		} else {
838
			$class = strpos( $icon, ' ' ) === false ? '' : ' ' . $icon;
839
			if ( strpos( $icon, ' ' ) ) {
840
				$icon = explode( ' ', $icon );
841
				$icon = reset( $icon );
842
			}
843
			$icon  = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '>
844
				<use xlink:href="#' . esc_attr( $icon ) . '" />
845
			</svg>';
846
		}
847
848
		if ( $echo ) {
849
			echo $icon; // WPCS: XSS ok.
850
		} else {
851
			return $icon;
852
		}
853
	}
854
855
	/**
856
	 * Include svg images.
857
	 *
858
	 * @since 4.0.02
859
	 */
860
	public static function include_svg() {
861
		include_once( self::plugin_path() . '/images/icons.svg' );
862
	}
863
864
	/**
865
	 * Convert an associative array to HTML values.
866
	 *
867
	 * @since 4.0.02
868
	 * @param array $atts
869
	 * @return string
870
	 */
871
	public static function array_to_html_params( $atts ) {
872
		$html = '';
873
		if ( ! empty( $atts ) ) {
874
			foreach ( $atts as $key => $value ) {
875
				$html .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
876
			}
877
		}
878
		return $html;
879
	}
880
881
	/**
882
	 * @since 3.0
883
	 */
884
	public static function get_admin_header( $atts ) {
885
		$has_nav = ( isset( $atts['form'] ) && ! empty( $atts['form'] ) && ( ! isset( $atts['is_template'] ) || ! $atts['is_template'] ) );
886
		if ( ! isset( $atts['close'] ) || empty( $atts['close'] ) ) {
887
			$atts['close'] = admin_url( 'admin.php?page=formidable' );
888
		}
889
890
		include( self::plugin_path() . '/classes/views/shared/admin-header.php' );
891
	}
892
893
	/**
894
	 * @since 3.0
895
	 */
896
	public static function add_new_item_link( $atts ) {
897
		if ( isset( $atts['new_link'] ) && ! empty( $atts['new_link'] ) ) { ?>
898
			<a href="<?php echo esc_url( $atts['new_link'] ); ?>" class="button button-primary frm-button-primary frm-with-plus">
899
				<?php self::icon_by_class( 'frmfont frm_plus_icon frm_svg15' ); ?>
900
				<?php esc_html_e( 'Add New', 'formidable' ); ?>
901
			</a>
902
			<?php
903
		} elseif ( isset( $atts['link_hook'] ) ) {
904
			do_action( $atts['link_hook']['hook'], $atts['link_hook']['param'] );
905
		}
906
	}
907
908
	/**
909
	 * @since 3.06
910
	 */
911
	public static function show_search_box( $atts ) {
912
		$defaults = array(
913
			'placeholder' => '',
914
			'tosearch'    => '',
915
			'text'        => __( 'Search', 'formidable' ),
916
			'input_id'    => '',
917
		);
918
		$atts = array_merge( $defaults, $atts );
919
920
		if ( $atts['input_id'] === 'template' && empty( $atts['tosearch'] ) ) {
921
			$atts['tosearch'] = 'frm-card';
922
		}
923
924
		$class = 'frm-search-input';
925
		if ( ! empty( $atts['tosearch'] ) ) {
926
			$class .= ' frm-auto-search';
927
		}
928
929
		$input_id = $atts['input_id'] . '-search-input';
930
931
		?>
932
		<p class="frm-search">
933
			<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
934
				<?php echo esc_html( $atts['text'] ); ?>:
935
			</label>
936
			<span class="frmfont frm_search_icon"></span>
937
			<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s"
938
				value="<?php _admin_search_query(); ?>" placeholder="<?php echo esc_attr( $atts['placeholder'] ); ?>"
939
				class="<?php echo esc_attr( $class ); ?>" data-tosearch="<?php echo esc_attr( $atts['tosearch'] ); ?>"
940
				<?php if ( ! empty( $atts['tosearch'] ) ) { ?>
941
				autocomplete="off"
942
				<?php } ?>
943
				/>
944
			<?php
945
			if ( empty( $atts['tosearch'] ) ) {
946
				submit_button( $atts['text'], 'button-secondary', '', false, array( 'id' => 'search-submit' ) );
947
			}
948
			?>
949
		</p>
950
		<?php
951
	}
952
953
	/**
954
	 * @param string $type
955
	 */
956
	public static function trigger_hook_load( $type, $object = null ) {
957
		// Only load the form hooks once.
958
		$hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
959
		if ( ! $hooks_loaded ) {
960
			do_action( 'frm_load_' . $type . '_hooks' );
961
		}
962
	}
963
964
	/**
965
	 * Save all front-end js scripts into a single file
966
	 *
967
	 * @since 3.0
968
	 */
969
	public static function save_combined_js() {
970
		$file_atts = apply_filters(
971
			'frm_js_location',
972
			array(
973
				'file_name'     => 'frm.min.js',
974
				'new_file_path' => self::plugin_path() . '/js',
975
			)
976
		);
977
		$new_file  = new FrmCreateFile( $file_atts );
978
979
		$files = array(
980
			self::plugin_path() . '/js/jquery/jquery.placeholder.min.js',
981
			self::plugin_path() . '/js/formidable.min.js',
982
		);
983
		$files = apply_filters( 'frm_combined_js_files', $files );
984
		$new_file->combine_files( $files );
985
	}
986
987
	/**
988
	 * Check a value from a shortcode to see if true or false.
989
	 * True when value is 1, true, 'true', 'yes'
990
	 *
991
	 * @since 1.07.10
992
	 *
993
	 * @param string $value The value to compare
994
	 *
995
	 * @return boolean True or False
996
	 */
997
	public static function is_true( $value ) {
998
		return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
999
	}
1000
1001
	public static function get_pages() {
1002
		$query = array(
1003
			'post_type'   => 'page',
1004
			'post_status' => array( 'publish', 'private' ),
1005
			'numberposts' => - 1,
1006
			'orderby'     => 'title',
1007
			'order'       => 'ASC',
1008
		);
1009
1010
		return get_posts( $query );
1011
	}
1012
1013
	/**
1014
	 * Autocomplete page admin ajax endpoint
1015
	 *
1016
	 * @since 4.03.06
1017
	 */
1018
	public static function page_search() {
1019
		global $wpdb;
1020
1021
		$nonce = self::get_param( 'nonce', '', 'get', 'sanitize_text_field' );
1022
		$term = self::get_param( 'term', '', 'get', 'sanitize_text_field' );
1023
1024
		if ( ! wp_verify_nonce( $nonce, 'frm_ajax' ) ) {
1025
			wp_send_json(
1026
				array(
1027
					'status'  => 'error',
1028
					'message' => esc_html__( 'You do not have permission to do that', 'formidable' ),
1029
				)
1030
			);
1031
		}
1032
1033
		$results = array();
1034
		$pages = $wpdb->get_results(
1035
			$wpdb->prepare(
1036
				"SELECT ID, post_title FROM {$wpdb->posts}
1037
				WHERE post_status = %s AND post_type = %s AND post_title LIKE %s
1038
				LIMIT 25",
1039
				'publish',
1040
				'page',
1041
				'%' . $wpdb->esc_like( $term ) . '%'
1042
			)
1043
		);
1044
1045
		if ( count( $pages ) ) {
1046
			foreach ( $pages as $page ) {
1047
				$results[] = array(
1048
					'value' => $page->ID,
1049
					'label' => $page->post_title,
1050
				);
1051
			}
1052
		}
1053
1054
		wp_send_json( $results );
1055
	}
1056
1057
	/**
1058
	 * Renders an autocomplete page selection or a regular dropdown depending on
1059
	 * the total page count
1060
	 *
1061
	 * @since 4.03.06
1062
	 */
1063
	public static function maybe_autocomplete_pages_options( $args ) {
1064
		$args = self::preformat_selection_args( $args );
1065
1066
		$pages_count = wp_count_posts( 'page' );
1067
1068
		if ( $pages_count->publish <= 50 ) {
1069
			self::wp_pages_dropdown( $args );
1070
			return;
1071
		}
1072
1073
		wp_enqueue_script( 'jquery-ui-autocomplete' );
1074
1075
		$selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
0 ignored issues
show
Security Bug introduced by
It seems like $args['page_id'] can also be of type false; however, FrmAppHelper::get_post_param() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
1076
		$title = '';
1077
1078
		if ( $selected ) {
1079
			$title = get_the_title( $selected );
1080
		}
1081
1082
		?>
1083
		<input type="text" class="frm-page-search"
1084
			placeholder="<?php esc_html_e( 'Select a Page...', 'formidable' ); ?>"
1085
			value="<?php echo esc_attr( $title ); ?>" />
1086
		<input type="hidden" name="<?php echo esc_attr( $args['field_name'] ); ?>"
1087
			value="<?php echo esc_attr( $selected ); ?>" />
1088
		<?php
1089
	}
1090
1091
	/**
1092
	 * @param array   $args
1093
	 * @param string  $page_id Deprecated.
1094
	 * @param boolean $truncate Deprecated.
1095
	 */
1096
	public static function wp_pages_dropdown( $args = array(), $page_id = '', $truncate = false ) {
1097
		self::prep_page_dropdown_params( $page_id, $truncate, $args );
1098
1099
		$pages    = self::get_pages();
1100
		$selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
1101
1102
		?>
1103
		<select name="<?php echo esc_attr( $args['field_name'] ); ?>" id="<?php echo esc_attr( $args['field_name'] ); ?>" class="frm-pages-dropdown">
1104
			<option value=""><?php echo esc_html( $args['placeholder'] ); ?></option>
1105
			<?php foreach ( $pages as $page ) { ?>
1106
				<option value="<?php echo esc_attr( $page->ID ); ?>" <?php selected( $selected, $page->ID ); ?>>
1107
					<?php echo esc_html( $args['truncate'] ? self::truncate( $page->post_title, $args['truncate'] ) : $page->post_title ); ?>
1108
				</option>
1109
			<?php } ?>
1110
		</select>
1111
		<?php
1112
	}
1113
1114
	/**
1115
	 * Fill in missing parameters passed to wp_pages_dropdown().
1116
	 * This is for reverse compatibility with switching 3 params to 1.
1117
	 *
1118
	 * @since 4.03.06
1119
	 */
1120
	private static function prep_page_dropdown_params( $page_id, $truncate, &$args ) {
1121
		if ( ! is_array( $args ) ) {
1122
			$args = array(
1123
				'field_name' => $args,
1124
				'page_id'    => $page_id,
1125
				'truncate'   => $truncate,
1126
			);
1127
		}
1128
1129
		$args = self::preformat_selection_args( $args );
1130
	}
1131
1132
	/**
1133
	 * Filter to format args for page dropdown or autocomplete
1134
	 *
1135
	 * @since 4.03.06
1136
	 */
1137
	private static function preformat_selection_args( $args ) {
1138
		$defaults = array(
1139
			'truncate'    => false,
1140
			'placeholder' => ' ',
1141
			'field_name'  => '',
1142
			'page_id'     => '',
1143
		);
1144
1145
		return array_merge( $defaults, $args );
1146
	}
1147
1148
	public static function post_edit_link( $post_id ) {
1149
		$post = get_post( $post_id );
1150
		if ( $post ) {
1151
			$post_url = admin_url( 'post.php?post=' . $post_id . '&action=edit' );
1152
			$post_url = self::maybe_full_screen_link( $post_url );
1153
1154
			return '<a href="' . esc_url( $post_url ) . '">' . self::truncate( $post->post_title, 50 ) . '</a>';
1155
		}
1156
1157
		return '';
1158
	}
1159
1160
	/**
1161
	 * Hide the WordPress menus on some pages.
1162
	 *
1163
	 * @since 4.0
1164
	 */
1165
	public static function is_full_screen() {
1166
		$action       = self::simple_get( 'frm_action', 'sanitize_title' );
1167
		$full_builder = self::is_admin_page( 'formidable' ) && ( $action === 'edit' || $action === 'settings' || $action === 'duplicate' );
1168
		$styler       = self::is_admin_page( 'formidable-styles' );
1169
		$full_entries = self::simple_get( 'frm-full', 'absint' );
1170
1171
		return $full_builder || $full_entries || $styler || self::is_view_builder_page();
1172
	}
1173
1174
	/**
1175
	 * @since 4.0
1176
	 */
1177
	public static function maybe_full_screen_link( $link ) {
1178
		$is_full = self::simple_get( 'frm-full', 'absint' );
1179
		if ( $is_full && ! empty( $link ) && $link !== '#' ) {
1180
			$link .= '&frm-full=1';
1181
		}
1182
		return $link;
1183
	}
1184
1185
	public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
1186
		?>
1187
		<select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>"
1188
			<?php echo ( 'multiple' === $multiple ) ? 'multiple="multiple"' : ''; ?>
1189
			class="frm_multiselect">
1190
			<?php self::roles_options( $capability ); ?>
1191
		</select>
1192
		<?php
1193
	}
1194
1195
	public static function roles_options( $capability ) {
1196
		global $frm_vars;
1197
		if ( isset( $frm_vars['editable_roles'] ) ) {
1198
			$editable_roles = $frm_vars['editable_roles'];
1199
		} else {
1200
			$editable_roles             = get_editable_roles();
1201
			$frm_vars['editable_roles'] = $editable_roles;
1202
		}
1203
1204
		foreach ( $editable_roles as $role => $details ) {
1205
			$name = translate_user_role( $details['name'] );
1206
			?>
1207
			<option value="<?php echo esc_attr( $role ); ?>" <?php echo in_array( $role, (array) $capability ) ? ' selected="selected"' : ''; ?>><?php echo esc_attr( $name ); ?> </option>
1208
			<?php
1209
			unset( $role, $details );
1210
		}
1211
	}
1212
1213
	public static function frm_capabilities( $type = 'auto' ) {
1214
		$cap = array(
1215
			'frm_view_forms'      => __( 'View Forms and Templates', 'formidable' ),
1216
			'frm_edit_forms'      => __( 'Add/Edit Forms and Templates', 'formidable' ),
1217
			'frm_delete_forms'    => __( 'Delete Forms and Templates', 'formidable' ),
1218
			'frm_change_settings' => __( 'Access this Settings Page', 'formidable' ),
1219
			'frm_view_entries'    => __( 'View Entries from Admin Area', 'formidable' ),
1220
			'frm_delete_entries'  => __( 'Delete Entries from Admin Area', 'formidable' ),
1221
		);
1222
1223
		if ( ! self::pro_is_installed() && 'pro' != $type ) {
1224
			return $cap;
1225
		}
1226
1227
		$cap['frm_create_entries'] = __( 'Add Entries from Admin Area', 'formidable' );
1228
		$cap['frm_edit_entries']   = __( 'Edit Entries from Admin Area', 'formidable' );
1229
		$cap['frm_view_reports']   = __( 'View Reports', 'formidable' );
1230
		$cap['frm_edit_displays']  = __( 'Add/Edit Views', 'formidable' );
1231
1232
		return $cap;
1233
	}
1234
1235
	public static function user_has_permission( $needed_role ) {
1236
		if ( $needed_role == '-1' ) {
1237
			return false;
1238
		}
1239
1240
		// $needed_role will be equal to blank if "Logged-in users" is selected.
1241
		if ( ( $needed_role == '' && is_user_logged_in() ) || current_user_can( $needed_role ) ) {
1242
			return true;
1243
		}
1244
1245
		$roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
1246
		foreach ( $roles as $role ) {
1247
			if ( current_user_can( $role ) ) {
1248
				return true;
1249
			}
1250
			if ( $role == $needed_role ) {
1251
				break;
1252
			}
1253
		}
1254
1255
		return false;
1256
	}
1257
1258
	/**
1259
	 * Make sure administrators can see Formidable menu
1260
	 *
1261
	 * @since 2.0
1262
	 */
1263
	public static function maybe_add_permissions() {
1264
		self::force_capability( 'frm_view_entries' );
1265
1266
		if ( ! current_user_can( 'administrator' ) || current_user_can( 'frm_view_forms' ) ) {
1267
			return;
1268
		}
1269
1270
		$user_id   = get_current_user_id();
1271
		$user      = new WP_User( $user_id );
1272
		$frm_roles = self::frm_capabilities();
1273
		foreach ( $frm_roles as $frm_role => $frm_role_description ) {
1274
			$user->add_cap( $frm_role );
1275
			unset( $frm_role, $frm_role_description );
1276
		}
1277
	}
1278
1279
	/**
1280
	 * Make sure admins have permission to see the menu items
1281
	 *
1282
	 * @since 2.0.6
1283
	 */
1284
	public static function force_capability( $cap = 'frm_change_settings' ) {
1285
		if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
1286
			$role      = get_role( 'administrator' );
1287
			$frm_roles = self::frm_capabilities();
1288
			foreach ( $frm_roles as $frm_role => $frm_role_description ) {
1289
				$role->add_cap( $frm_role );
1290
			}
1291
		}
1292
	}
1293
1294
	/**
1295
	 * Check if the user has permision for action.
1296
	 * Return permission message and stop the action if no permission
1297
	 *
1298
	 * @since 2.0
1299
	 *
1300
	 * @param string $permission
1301
	 */
1302
	public static function permission_check( $permission, $show_message = 'show' ) {
1303
		$permission_error = self::permission_nonce_error( $permission );
1304
		if ( $permission_error !== false ) {
1305
			if ( 'hide' == $show_message ) {
1306
				$permission_error = '';
1307
			}
1308
			wp_die( esc_html( $permission_error ) );
1309
		}
1310
	}
1311
1312
	/**
1313
	 * Check user permission and nonce
1314
	 *
1315
	 * @since 2.0
1316
	 *
1317
	 * @param string $permission
1318
	 *
1319
	 * @return false|string The permission message or false if allowed
1320
	 */
1321
	public static function permission_nonce_error( $permission, $nonce_name = '', $nonce = '' ) {
1322
		if ( ! empty( $permission ) && ! current_user_can( $permission ) && ! current_user_can( 'administrator' ) ) {
1323
			$frm_settings = self::get_settings();
1324
1325
			return $frm_settings->admin_permission;
1326
		}
1327
1328
		$error = false;
1329
		if ( empty( $nonce_name ) ) {
1330
			return $error;
1331
		}
1332
1333
		$nonce_value = ( $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
1334
		if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $nonce_value, $nonce ) ) ) {
1335
			$frm_settings = self::get_settings();
1336
			$error        = $frm_settings->admin_permission;
1337
		}
1338
1339
		return $error;
1340
	}
1341
1342
	public static function checked( $values, $current ) {
1343
		if ( self::check_selected( $values, $current ) ) {
1344
			echo ' checked="checked"';
1345
		}
1346
	}
1347
1348
	public static function check_selected( $values, $current ) {
1349
		$values  = self::recursive_function_map( $values, 'trim' );
1350
		$values  = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1351
		$current = htmlspecialchars_decode( trim( $current ) );
1352
1353
		return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
1354
	}
1355
1356
	public static function recursive_function_map( $value, $function ) {
1357
		if ( is_array( $value ) ) {
1358
			$original_function = $function;
1359
			if ( count( $value ) ) {
1360
				$function = explode( ', ', FrmDb::prepare_array_values( $value, $function ) );
1361
			} else {
1362
				$function = array( $function );
1363
			}
1364
			if ( ! self::is_assoc( $value ) ) {
1365
				$value = array_map( array( 'FrmAppHelper', 'recursive_function_map' ), $value, $function );
1366
			} else {
1367
				foreach ( $value as $k => $v ) {
1368
					if ( ! is_array( $v ) ) {
1369
						$value[ $k ] = call_user_func( $original_function, $v );
1370
					}
1371
				}
1372
			}
1373
		} else {
1374
			$value = call_user_func( $function, $value );
1375
		}
1376
1377
		return $value;
1378
	}
1379
1380
	public static function is_assoc( $array ) {
1381
		return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
1382
	}
1383
1384
	/**
1385
	 * Flatten a multi-dimensional array
1386
	 */
1387
	public static function array_flatten( $array, $keys = 'keep' ) {
1388
		$return = array();
1389
		foreach ( $array as $key => $value ) {
1390
			if ( is_array( $value ) ) {
1391
				$return = array_merge( $return, self::array_flatten( $value, $keys ) );
1392
			} else {
1393
				if ( $keys == 'keep' ) {
1394
					$return[ $key ] = $value;
1395
				} else {
1396
					$return[] = $value;
1397
				}
1398
			}
1399
		}
1400
1401
		return $return;
1402
	}
1403
1404
	public static function esc_textarea( $text, $is_rich_text = false ) {
1405
		$safe_text = str_replace( '&quot;', '"', $text );
1406
		if ( ! $is_rich_text ) {
1407
			$safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
1408
		}
1409
		$safe_text = str_replace( '&amp; ', '& ', $safe_text );
1410
1411
		return apply_filters( 'esc_textarea', $safe_text, $text );
1412
	}
1413
1414
	/**
1415
	 * Add auto paragraphs to text areas
1416
	 *
1417
	 * @since 2.0
1418
	 */
1419
	public static function use_wpautop( $content ) {
1420
		if ( apply_filters( 'frm_use_wpautop', true ) && ! is_array( $content ) ) {
1421
			$content = wpautop( str_replace( '<br>', '<br />', $content ) );
1422
		}
1423
1424
		return $content;
1425
	}
1426
1427
	public static function replace_quotes( $val ) {
1428
		// Replace double quotes.
1429
		$val = str_replace( array( '&#8220;', '&#8221;', '&#8243;' ), '"', $val );
1430
1431
		// Replace single quotes.
1432
		$val = str_replace( array( '&#8216;', '&#8217;', '&#8242;', '&prime;', '&rsquo;', '&lsquo;' ), "'", $val );
1433
1434
		return $val;
1435
	}
1436
1437
	/**
1438
	 * @since 2.0
1439
	 * @return string The base Google APIS url for the current version of jQuery UI
1440
	 */
1441
	public static function jquery_ui_base_url() {
1442
		$url = 'http' . ( is_ssl() ? 's' : '' ) . '://ajax.googleapis.com/ajax/libs/jqueryui/' . self::script_version( 'jquery-ui-core', '1.11.4' );
1443
		$url = apply_filters( 'frm_jquery_ui_base_url', $url );
1444
1445
		return $url;
1446
	}
1447
1448
	/**
1449
	 * @param string $handle
1450
	 */
1451
	public static function script_version( $handle, $default = 0 ) {
1452
		global $wp_scripts;
1453
		if ( ! $wp_scripts ) {
1454
			return $default;
1455
		}
1456
1457
		$ver = $default;
1458
		if ( ! isset( $wp_scripts->registered[ $handle ] ) ) {
1459
			return $ver;
1460
		}
1461
1462
		$query = $wp_scripts->registered[ $handle ];
1463
		if ( is_object( $query ) && ! empty( $query->ver ) ) {
1464
			$ver = $query->ver;
1465
		}
1466
1467
		return $ver;
1468
	}
1469
1470
	public static function js_redirect( $url ) {
1471
		return '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
1472
	}
1473
1474
	public static function get_user_id_param( $user_id ) {
1475
		if ( ! $user_id || empty( $user_id ) || is_numeric( $user_id ) ) {
1476
			return $user_id;
1477
		}
1478
1479
		$user_id = sanitize_text_field( $user_id );
1480
		if ( $user_id == 'current' ) {
1481
			$user_id = get_current_user_id();
1482
		} else {
1483
			if ( is_email( $user_id ) ) {
1484
				$user = get_user_by( 'email', $user_id );
1485
			} else {
1486
				$user = get_user_by( 'login', $user_id );
1487
			}
1488
1489
			if ( $user ) {
1490
				$user_id = $user->ID;
1491
			}
1492
			unset( $user );
1493
		}
1494
1495
		return $user_id;
1496
	}
1497
1498
	public static function get_file_contents( $filename, $atts = array() ) {
1499
		if ( ! is_file( $filename ) ) {
1500
			return false;
1501
		}
1502
1503
		extract( $atts );
1504
		ob_start();
1505
		include( $filename );
1506
		$contents = ob_get_contents();
1507
		ob_end_clean();
1508
1509
		return $contents;
1510
	}
1511
1512
	/**
1513
	 * @param string $table_name
1514
	 * @param string $column
1515
	 * @param int $id
1516
	 * @param int $num_chars
1517
	 */
1518
	public static function get_unique_key( $name = '', $table_name, $column, $id = 0, $num_chars = 5 ) {
1519
		$key = '';
1520
1521
		if ( ! empty( $name ) ) {
1522
			$key = sanitize_key( $name );
1523
		}
1524
1525
		if ( empty( $key ) ) {
1526
			$max_slug_value = pow( 36, $num_chars );
1527
			$min_slug_value = 37; // we want to have at least 2 characters in the slug
1528
			$key            = base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
1529
		}
1530
1531
		$not_allowed = array(
1532
			'id',
1533
			'key',
1534
			'created-at',
1535
			'detaillink',
1536
			'editlink',
1537
			'siteurl',
1538
			'evenodd',
1539
		);
1540
1541
		if ( is_numeric( $key ) || in_array( $key, $not_allowed ) ) {
1542
			$key = $key . 'a';
1543
		}
1544
1545
		$key_check = FrmDb::get_var(
1546
			$table_name,
1547
			array(
1548
				$column => $key,
1549
				'ID !'  => $id,
1550
			),
1551
			$column
1552
		);
1553
1554
		if ( $key_check || is_numeric( $key_check ) ) {
1555
			$suffix = 2;
1556
			do {
1557
				$alt_post_name = substr( $key, 0, 200 - ( strlen( $suffix ) + 1 ) ) . $suffix;
1558
				$key_check     = FrmDb::get_var(
1559
					$table_name,
1560
					array(
1561
						$column => $alt_post_name,
1562
						'ID !'  => $id,
1563
					),
1564
					$column
1565
				);
1566
				$suffix ++;
1567
			} while ( $key_check || is_numeric( $key_check ) );
1568
			$key = $alt_post_name;
1569
		}
1570
1571
		return $key;
1572
	}
1573
1574
	/**
1575
	 * Editing a Form or Entry
1576
	 *
1577
	 * @param string $table
1578
	 *
1579
	 * @return bool|array
1580
	 */
1581
	public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
1582
		if ( ! $record ) {
1583
			return false;
1584
		}
1585
1586
		if ( empty( $post_values ) ) {
1587
			$post_values = wp_unslash( $_POST );
1588
		}
1589
1590
		$values = array(
1591
			'id'     => $record->id,
1592
			'fields' => array(),
1593
		);
1594
1595
		foreach ( array( 'name', 'description' ) as $var ) {
1596
			$default_val    = isset( $record->{$var} ) ? $record->{$var} : '';
1597
			$values[ $var ] = self::get_param( $var, $default_val, 'get', 'wp_kses_post' );
1598
			unset( $var, $default_val );
1599
		}
1600
1601
		$values['description'] = self::use_wpautop( $values['description'] );
1602
1603
		self::fill_form_opts( $record, $table, $post_values, $values );
1604
1605
		self::prepare_field_arrays( $fields, $record, $values, array_merge( $args, compact( 'default', 'post_values' ) ) );
1606
1607
		if ( $table == 'entries' ) {
1608
			$values = FrmEntriesHelper::setup_edit_vars( $values, $record );
1609
		} elseif ( $table == 'forms' ) {
1610
			$values = FrmFormsHelper::setup_edit_vars( $values, $record, $post_values );
1611
		}
1612
1613
		return $values;
1614
	}
1615
1616
	private static function prepare_field_arrays( $fields, $record, array &$values, $args ) {
1617
		if ( ! empty( $fields ) ) {
1618
			foreach ( (array) $fields as $field ) {
1619
				$field->default_value   = apply_filters( 'frm_get_default_value', $field->default_value, $field, true );
1620
				$args['parent_form_id'] = isset( $args['parent_form_id'] ) ? $args['parent_form_id'] : $field->form_id;
1621
				self::fill_field_defaults( $field, $record, $values, $args );
1622
			}
1623
		}
1624
	}
1625
1626
	private static function fill_field_defaults( $field, $record, array &$values, $args ) {
1627
		$post_values = $args['post_values'];
1628
1629
		if ( $args['default'] ) {
1630
			$meta_value = $field->default_value;
1631
		} else {
1632
			if ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
1633
				if ( ! isset( $field->field_options['custom_field'] ) ) {
1634
					$field->field_options['custom_field'] = '';
1635
				}
1636
				$meta_value = FrmProEntryMetaHelper::get_post_value(
1637
					$record->post_id,
1638
					$field->field_options['post_field'],
1639
					$field->field_options['custom_field'],
1640
					array(
1641
						'truncate' => false,
1642
						'type'     => $field->type,
1643
						'form_id'  => $field->form_id,
1644
						'field'    => $field,
1645
					)
1646
				);
1647
			} else {
1648
				$meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
1649
			}
1650
		}
1651
1652
		$field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
1653
		if ( isset( $post_values['item_meta'][ $field->id ] ) ) {
1654
			$new_value = $post_values['item_meta'][ $field->id ];
1655
			self::unserialize_or_decode( $new_value );
1656
		} else {
1657
			$new_value = $meta_value;
1658
		}
1659
1660
		$field_array                   = self::start_field_array( $field );
1661
		$field_array['value']          = $new_value;
1662
		$field_array['type']           = apply_filters( 'frm_field_type', $field_type, $field, $new_value );
1663
		$field_array['parent_form_id'] = $args['parent_form_id'];
1664
1665
		$args['field_type'] = $field_type;
1666
1667
		FrmFieldsHelper::prepare_edit_front_field( $field_array, $field, $values['id'], $args );
1668
1669
		if ( ! isset( $field_array['unique'] ) || ! $field_array['unique'] ) {
1670
			$field_array['unique_msg'] = '';
1671
		}
1672
1673
		$field_array = array_merge( $field->field_options, $field_array );
1674
1675
		$values['fields'][ $field->id ] = $field_array;
1676
	}
1677
1678
	/**
1679
	 * @since 3.0
1680
	 *
1681
	 * @param object $field
1682
	 *
1683
	 * @return array
1684
	 */
1685
	public static function start_field_array( $field ) {
1686
		return array(
1687
			'id'            => $field->id,
1688
			'default_value' => $field->default_value,
1689
			'name'          => $field->name,
1690
			'description'   => $field->description,
1691
			'options'       => $field->options,
1692
			'required'      => $field->required,
1693
			'field_key'     => $field->field_key,
1694
			'field_order'   => $field->field_order,
1695
			'form_id'       => $field->form_id,
1696
		);
1697
	}
1698
1699
	/**
1700
	 * @param string $table
1701
	 */
1702
	private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
1703
		if ( $table == 'entries' ) {
1704
			$form = $record->form_id;
1705
			FrmForm::maybe_get_form( $form );
1706
		} else {
1707
			$form = $record;
1708
		}
1709
1710
		if ( ! $form ) {
1711
			return;
1712
		}
1713
1714
		$values['form_name']      = isset( $record->form_id ) ? $form->name : '';
1715
		$values['parent_form_id'] = isset( $record->form_id ) ? $form->parent_form_id : 0;
1716
1717
		if ( ! is_array( $form->options ) ) {
1718
			return;
1719
		}
1720
1721
		foreach ( $form->options as $opt => $value ) {
1722
			if ( isset( $post_values[ $opt ] ) ) {
1723
				$values[ $opt ] = $post_values[ $opt ];
1724
				self::unserialize_or_decode( $values[ $opt ] );
1725
			} else {
1726
				$values[ $opt ] = $value;
1727
			}
1728
		}
1729
1730
		self::fill_form_defaults( $post_values, $values );
1731
	}
1732
1733
	/**
1734
	 * Set to POST value or default
1735
	 */
1736
	private static function fill_form_defaults( $post_values, array &$values ) {
1737
		$form_defaults = FrmFormsHelper::get_default_opts();
1738
1739
		foreach ( $form_defaults as $opt => $default ) {
1740
			if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
1741
				$values[ $opt ] = ( $post_values && isset( $post_values['options'][ $opt ] ) ) ? $post_values['options'][ $opt ] : $default;
1742
			}
1743
1744
			unset( $opt, $default );
1745
		}
1746
1747
		if ( ! isset( $values['custom_style'] ) ) {
1748
			$values['custom_style'] = self::custom_style_value( $post_values );
1749
		}
1750
1751
		foreach ( array( 'before', 'after', 'submit' ) as $h ) {
1752
			if ( ! isset( $values[ $h . '_html' ] ) ) {
1753
				$values[ $h . '_html' ] = ( isset( $post_values['options'][ $h . '_html' ] ) ? $post_values['options'][ $h . '_html' ] : FrmFormsHelper::get_default_html( $h ) );
1754
			}
1755
			unset( $h );
1756
		}
1757
	}
1758
1759
	/**
1760
	 * @since 2.2.10
1761
	 *
1762
	 * @param array $post_values
1763
	 *
1764
	 * @return boolean|int
1765
	 */
1766
	public static function custom_style_value( $post_values ) {
1767
		if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
1768
			$custom_style = absint( $post_values['options']['custom_style'] );
1769
		} else {
1770
			$frm_settings = self::get_settings();
1771
			$custom_style = ( $frm_settings->load_style != 'none' );
1772
		}
1773
1774
		return $custom_style;
1775
	}
1776
1777
	public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
1778
		if ( is_array( $str ) ) {
1779
			return '';
1780
		}
1781
1782
		$length       = (int) $length;
1783
		$str          = wp_strip_all_tags( $str );
1784
		$original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
1785
1786
		if ( $length == 0 ) {
1787
			return '';
1788
		} elseif ( $length <= 10 ) {
1789
			$sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
1790
1791
			return $sub . ( ( $length < $original_len ) ? $continue : '' );
1792
		}
1793
1794
		$sub = '';
1795
		$len = 0;
1796
1797
		$words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
1798
1799
		foreach ( $words as $word ) {
1800
			$part      = ( ( $sub != '' ) ? ' ' : '' ) . $word;
1801
			$total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
1802
			if ( $total_len > $length && substr_count( $sub, ' ' ) ) {
1803
				break;
1804
			}
1805
1806
			$sub .= $part;
1807
			$len += self::mb_function( array( 'mb_strlen', 'strlen' ), array( $part ) );
1808
1809
			if ( substr_count( $sub, ' ' ) > $minword && $total_len >= $length ) {
1810
				break;
1811
			}
1812
1813
			unset( $total_len, $word );
1814
		}
1815
1816
		return $sub . ( ( $len < $original_len ) ? $continue : '' );
1817
	}
1818
1819
	public static function mb_function( $function_names, $args ) {
1820
		$mb_function_name = $function_names[0];
1821
		$function_name    = $function_names[1];
1822
		if ( function_exists( $mb_function_name ) ) {
1823
			$function_name = $mb_function_name;
1824
		}
1825
1826
		return call_user_func_array( $function_name, $args );
1827
	}
1828
1829
	public static function get_formatted_time( $date, $date_format = '', $time_format = '' ) {
1830
		if ( empty( $date ) ) {
1831
			return $date;
1832
		}
1833
1834
		if ( empty( $date_format ) ) {
1835
			$date_format = get_option( 'date_format' );
1836
		}
1837
1838
		if ( preg_match( '/^\d{1-2}\/\d{1-2}\/\d{4}$/', $date ) && self::pro_is_installed() ) {
1839
			$frmpro_settings = new FrmProSettings();
1840
			$date            = FrmProAppHelper::convert_date( $date, $frmpro_settings->date_format, 'Y-m-d' );
1841
		}
1842
1843
		$formatted = self::get_localized_date( $date_format, $date );
1844
1845
		$do_time = ( gmdate( 'H:i:s', strtotime( $date ) ) != '00:00:00' );
1846
		if ( $do_time ) {
1847
			$formatted .= self::add_time_to_date( $time_format, $date );
1848
		}
1849
1850
		return $formatted;
1851
	}
1852
1853
	private static function add_time_to_date( $time_format, $date ) {
1854
		if ( empty( $time_format ) ) {
1855
			$time_format = get_option( 'time_format' );
1856
		}
1857
1858
		$trimmed_format = trim( $time_format );
1859
		$time           = '';
1860
		if ( $time_format && ! empty( $trimmed_format ) ) {
1861
			$time = ' ' . __( 'at', 'formidable' ) . ' ' . self::get_localized_date( $time_format, $date );
1862
		}
1863
1864
		return $time;
1865
	}
1866
1867
	/**
1868
	 * @since 2.0.8
1869
	 */
1870
	public static function get_localized_date( $date_format, $date ) {
1871
		$date = get_date_from_gmt( $date );
1872
1873
		return date_i18n( $date_format, strtotime( $date ) );
1874
	}
1875
1876
	/**
1877
	 * Gets the time ago in words
1878
	 *
1879
	 * @param int $from in seconds
1880
	 * @param int|string $to in seconds
1881
	 *
1882
	 * @return string $time_ago
1883
	 */
1884
	public static function human_time_diff( $from, $to = '', $levels = 1 ) {
1885
		if ( empty( $to ) ) {
1886
			$now = new DateTime();
1887
		} else {
1888
			$now = new DateTime( '@' . $to );
1889
		}
1890
		$ago = new DateTime( '@' . $from );
1891
1892
		// Get the time difference
1893
		$diff_object = $now->diff( $ago );
1894
		$diff        = get_object_vars( $diff_object );
1895
1896
		// Add week amount and update day amount
1897
		$diff['w'] = floor( $diff['d'] / 7 );
1898
		$diff['d'] -= $diff['w'] * 7;
1899
1900
		$time_strings = self::get_time_strings();
1901
1902
		foreach ( $time_strings as $k => $v ) {
1903
			if ( $diff[ $k ] ) {
1904
				$time_strings[ $k ] = $diff[ $k ] . ' ' . ( $diff[ $k ] > 1 ? $v[1] : $v[0] );
1905
			} else {
1906
				unset( $time_strings[ $k ] );
1907
			}
1908
		}
1909
1910
		$levels_deep     = apply_filters( 'frm_time_ago_levels', $levels, compact( 'time_strings', 'from', 'to' ) );
1911
		$time_strings    = array_slice( $time_strings, 0, $levels_deep );
1912
		$time_ago_string = $time_strings ? implode( ' ', $time_strings ) : '0 ' . __( 'seconds', 'formidable' );
1913
1914
		return $time_ago_string;
1915
	}
1916
1917
	/**
1918
	 * Get the translatable time strings
1919
	 *
1920
	 * @since 2.0.20
1921
	 * @return array
1922
	 */
1923
	private static function get_time_strings() {
1924
		return array(
1925
			'y' => array( __( 'year', 'formidable' ), __( 'years', 'formidable' ) ),
1926
			'm' => array( __( 'month', 'formidable' ), __( 'months', 'formidable' ) ),
1927
			'w' => array( __( 'week', 'formidable' ), __( 'weeks', 'formidable' ) ),
1928
			'd' => array( __( 'day', 'formidable' ), __( 'days', 'formidable' ) ),
1929
			'h' => array( __( 'hour', 'formidable' ), __( 'hours', 'formidable' ) ),
1930
			'i' => array( __( 'minute', 'formidable' ), __( 'minutes', 'formidable' ) ),
1931
			's' => array( __( 'second', 'formidable' ), __( 'seconds', 'formidable' ) ),
1932
		);
1933
	}
1934
1935
	// Pagination Methods.
1936
1937
	/**
1938
	 * @param integer $current_p
1939
	 */
1940
	public static function get_last_record_num( $r_count, $current_p, $p_size ) {
1941
		return ( ( $r_count < ( $current_p * $p_size ) ) ? $r_count : ( $current_p * $p_size ) );
1942
	}
1943
1944
	/**
1945
	 * @param integer $current_p
1946
	 */
1947
	public static function get_first_record_num( $r_count, $current_p, $p_size ) {
1948
		if ( $current_p == 1 ) {
1949
			return 1;
1950
		} else {
1951
			return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
1952
		}
1953
	}
1954
1955
	/**
1956
	 * @return array
1957
	 */
1958
	public static function json_to_array( $json_vars ) {
1959
		$vars = array();
1960
		foreach ( $json_vars as $jv ) {
1961
			$jv_name = explode( '[', $jv['name'] );
1962
			$last    = count( $jv_name ) - 1;
1963
			foreach ( $jv_name as $p => $n ) {
1964
				$name = trim( $n, ']' );
1965
				if ( ! isset( $l1 ) ) {
1966
					$l1 = $name;
1967
				}
1968
1969
				if ( ! isset( $l2 ) ) {
1970
					$l2 = $name;
1971
				}
1972
1973
				if ( ! isset( $l3 ) ) {
1974
					$l3 = $name;
1975
				}
1976
1977
				$this_val = ( $p == $last ) ? $jv['value'] : array();
1978
1979
				switch ( $p ) {
1980
					case 0:
1981
						$l1 = $name;
1982
						self::add_value_to_array( $name, $l1, $this_val, $vars );
1983
						break;
1984
1985
					case 1:
1986
						$l2 = $name;
1987
						self::add_value_to_array( $name, $l2, $this_val, $vars[ $l1 ] );
1988
						break;
1989
1990 View Code Duplication
					case 2:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1991
						$l3 = $name;
1992
						self::add_value_to_array( $name, $l3, $this_val, $vars[ $l1 ][ $l2 ] );
1993
						break;
1994
1995 View Code Duplication
					case 3:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1996
						$l4 = $name;
1997
						self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
1998
				}
1999
2000
				unset( $this_val, $n );
2001
			}
2002
2003
			unset( $last, $jv );
2004
		}
2005
2006
		return $vars;
2007
	}
2008
2009
	/**
2010
	 * @param string $name
2011
	 * @param string $l1
2012
	 */
2013
	public static function add_value_to_array( $name, $l1, $val, &$vars ) {
2014
		if ( $name == '' ) {
2015
			$vars[] = $val;
2016
		} elseif ( ! isset( $vars[ $l1 ] ) ) {
2017
			$vars[ $l1 ] = $val;
2018
		}
2019
	}
2020
2021
	public static function maybe_add_tooltip( $name, $class = 'closed', $form_name = '' ) {
2022
		$tooltips = array(
2023
			'action_title'  => __( 'Give this action a label for easy reference.', 'formidable' ),
2024
			'email_to'      => __( 'Add one or more recipient addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].  [admin_email] is the address set in WP General Settings.', 'formidable' ),
2025
			'cc'            => __( 'Add CC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
2026
			'bcc'           => __( 'Add BCC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
2027
			'reply_to'      => __( 'If you would like a different reply to address than the "from" address, add a single address here.  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
2028
			'from'          => __( 'Enter the name and/or email address of the sender. FORMAT: John Bates <[email protected]> or [email protected].', 'formidable' ),
2029
			/* translators: %1$s: Form name, %2$s: Date */
2030
			'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() ) ),
2031
		);
2032
2033
		if ( ! isset( $tooltips[ $name ] ) ) {
2034
			return;
2035
		}
2036
2037
		if ( 'open' == $class ) {
2038
			echo ' frm_help"';
2039
		} else {
2040
			echo ' class="frm_help"';
2041
		}
2042
2043
		echo ' title="' . esc_attr( $tooltips[ $name ] );
2044
2045
		if ( 'open' != $class ) {
2046
			echo '"';
2047
		}
2048
	}
2049
2050
	/**
2051
	 * Add the current_page class to that page in the form nav
2052
	 */
2053
	public static function select_current_page( $page, $current_page, $action = array() ) {
2054
		if ( $current_page != $page ) {
2055
			return;
2056
		}
2057
2058
		$frm_action = self::simple_get( 'frm_action', 'sanitize_title' );
2059
		if ( empty( $action ) || ( ! empty( $frm_action ) && in_array( $frm_action, $action ) ) ) {
2060
			echo ' class="current_page"';
2061
		}
2062
	}
2063
2064
	/**
2065
	 * Prepare and json_encode post content
2066
	 *
2067
	 * @since 2.0
2068
	 *
2069
	 * @param array $post_content
2070
	 *
2071
	 * @return string $post_content ( json encoded array )
2072
	 */
2073
	public static function prepare_and_encode( $post_content ) {
2074
		// Loop through array to strip slashes and add only the needed ones.
2075
		foreach ( $post_content as $key => $val ) {
2076
			// Replace problematic characters (like &quot;)
2077
			$val = str_replace( '&quot;', '"', $val );
2078
2079
			self::prepare_action_slashes( $val, $key, $post_content );
2080
			unset( $key, $val );
2081
		}
2082
2083
		// json_encode the array.
2084
		$post_content = json_encode( $post_content );
2085
2086
		// Add extra slashes for \r\n since WP strips them.
2087
		$post_content = str_replace( array( '\\r', '\\n', '\\u', '\\t' ), array( '\\\\r', '\\\\n', '\\\\u', '\\\\t' ), $post_content );
2088
2089
		// allow for &quot
2090
		$post_content = str_replace( '&quot;', '\\"', $post_content );
2091
2092
		return $post_content;
2093
	}
2094
2095
	private static function prepare_action_slashes( $val, $key, &$post_content ) {
2096
		if ( ! isset( $post_content[ $key ] ) ) {
2097
			return;
2098
		}
2099
2100
		if ( is_array( $val ) ) {
2101
			foreach ( $val as $k1 => $v1 ) {
2102
				self::prepare_action_slashes( $v1, $k1, $post_content[ $key ] );
2103
				unset( $k1, $v1 );
2104
			}
2105
		} else {
2106
			// Strip all slashes so everything is the same, no matter where the value is coming from
2107
			$val = stripslashes( $val );
2108
2109
			// Add backslashes before double quotes and forward slashes only
2110
			$post_content[ $key ] = addcslashes( $val, '"\\/' );
2111
		}
2112
	}
2113
2114
	/**
2115
	 * Check for either json or serilized data. This is temporary while transitioning
2116
	 * all data to json.
2117
	 *
2118
	 * @since 4.02.03
2119
	 */
2120
	public static function unserialize_or_decode( &$value ) {
2121
		if ( is_array( $value ) ) {
2122
			return;
2123
		}
2124
2125
		if ( is_serialized( $value ) ) {
2126
			$value = maybe_unserialize( $value );
2127
		} else {
2128
			$value = self::maybe_json_decode( $value, false );
2129
		}
2130
	}
2131
2132
	/**
2133
	 * Decode a JSON string.
2134
	 * Do not switch shortcodes like [24] to array unless intentional ie XML values.
2135
	 */
2136
	public static function maybe_json_decode( $string, $single_to_array = true ) {
2137
		if ( is_array( $string ) ) {
2138
			return $string;
2139
		}
2140
2141
		$new_string = json_decode( $string, true );
2142
		if ( function_exists( 'json_last_error' ) ) {
2143
			// php 5.3+
2144
			$single_value = false;
2145
			if ( ! $single_to_array ) {
2146
				$single_value = is_array( $new_string ) && count( $new_string ) === 1 && isset( $new_string[0] );
2147
			}
2148
			if ( json_last_error() == JSON_ERROR_NONE && is_array( $new_string ) && ! $single_value ) {
2149
				$string = $new_string;
2150
			}
2151
		}
2152
2153
		return $string;
2154
	}
2155
2156
	/**
2157
	 * Reformat the json serialized array in name => value array.
2158
	 *
2159
	 * @since 4.02.03
2160
	 */
2161
	public static function format_form_data( &$form ) {
2162
		$formatted = array();
2163
2164
		foreach ( $form as $input ) {
2165
			if ( ! isset( $input['name'] ) ) {
2166
				continue;
2167
			}
2168
			$key = $input['name'];
2169
			if ( isset( $formatted[ $key ] ) ) {
2170
				if ( is_array( $formatted[ $key ] ) ) {
2171
					$formatted[ $key ][] = $input['value'];
2172
				} else {
2173
					$formatted[ $key ] = array( $formatted[ $key ], $input['value'] );
2174
				}
2175
			} else {
2176
				$formatted[ $key ] = $input['value'];
2177
			}
2178
		}
2179
2180
		parse_str( http_build_query( $formatted ), $form );
2181
	}
2182
2183
	/**
2184
	 * @since 4.02.03
2185
	 */
2186
	public static function maybe_json_encode( $value ) {
2187
		if ( is_array( $value ) ) {
2188
			$value = wp_json_encode( $value );
2189
		}
2190
		return $value;
2191
	}
2192
2193
	/**
2194
	 * @since 1.07.10
2195
	 *
2196
	 * @param string $post_type The name of the post type that may need to be highlighted
2197
	 * echo The javascript to open and highlight the Formidable menu
2198
	 */
2199
	public static function maybe_highlight_menu( $post_type ) {
2200
		global $post;
2201
2202
		if ( isset( $_REQUEST['post_type'] ) && $_REQUEST['post_type'] != $post_type ) {
2203
			return;
2204
		}
2205
2206
		if ( is_object( $post ) && $post->post_type != $post_type ) {
2207
			return;
2208
		}
2209
2210
		self::load_admin_wide_js();
2211
		echo '<script type="text/javascript">jQuery(document).ready(function(){frmSelectSubnav();});</script>';
2212
	}
2213
2214
	/**
2215
	 * Load the JS file on non-Formidable pages in the admin area
2216
	 *
2217
	 * @since 2.0
2218
	 */
2219
	public static function load_admin_wide_js( $load = true ) {
2220
		$version = self::plugin_version();
2221
		wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
2222
2223
		$global_strings = array(
2224
			'updating_msg' => __( 'Please wait while your site updates.', 'formidable' ),
2225
			'deauthorize'  => __( 'Are you sure you want to deauthorize Formidable Forms on this site?', 'formidable' ),
2226
			'url'          => self::plugin_url(),
2227
			'app_url'      => 'https://formidableforms.com/',
2228
			'loading'      => __( 'Loading&hellip;', 'formidable' ),
2229
			'nonce'        => wp_create_nonce( 'frm_ajax' ),
2230
		);
2231
		wp_localize_script( 'formidable_admin_global', 'frmGlobal', $global_strings );
2232
2233
		if ( $load ) {
2234
			wp_enqueue_script( 'formidable_admin_global' );
2235
		}
2236
	}
2237
2238
	/**
2239
	 * @since 2.0.9
2240
	 */
2241
	public static function load_font_style() {
2242
		wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
2243
	}
2244
2245
	/**
2246
	 * @param string $location
2247
	 */
2248
	public static function localize_script( $location ) {
2249
		$ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
2250
		$ajax_url = apply_filters( 'frm_ajax_url', $ajax_url );
2251
2252
		$script_strings = array(
2253
			'ajax_url'     => $ajax_url,
2254
			'images_url'   => self::plugin_url() . '/images',
2255
			'loading'      => __( 'Loading&hellip;', 'formidable' ),
2256
			'remove'       => __( 'Remove', 'formidable' ),
2257
			'offset'       => apply_filters( 'frm_scroll_offset', 4 ),
2258
			'nonce'        => wp_create_nonce( 'frm_ajax' ),
2259
			'id'           => __( 'ID', 'formidable' ),
2260
			'no_results'   => __( 'No results match', 'formidable' ),
2261
			'file_spam'    => __( 'That file looks like Spam.', 'formidable' ),
2262
			'calc_error'   => __( 'There is an error in the calculation in the field with key', 'formidable' ),
2263
			'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
2264
		);
2265
		wp_localize_script( 'formidable', 'frm_js', $script_strings );
2266
2267
		if ( $location == 'admin' ) {
2268
			$frm_settings         = self::get_settings();
2269
			$admin_script_strings = array(
2270
				'desc'              => __( '(Click to add description)', 'formidable' ),
2271
				'blank'             => __( '(Blank)', 'formidable' ),
2272
				'no_label'          => __( '(no label)', 'formidable' ),
2273
				'saving'            => esc_attr( __( 'Saving', 'formidable' ) ),
2274
				'saved'             => esc_attr( __( 'Saved', 'formidable' ) ),
2275
				'ok'                => __( 'OK', 'formidable' ),
2276
				'cancel'            => __( 'Cancel', 'formidable' ),
2277
				'default'           => __( 'Default', 'formidable' ),
2278
				'clear_default'     => __( 'Clear default value when typing', 'formidable' ),
2279
				'no_clear_default'  => __( 'Do not clear default value when typing', 'formidable' ),
2280
				'valid_default'     => __( 'Default value will pass form validation', 'formidable' ),
2281
				'no_valid_default'  => __( 'Default value will NOT pass form validation', 'formidable' ),
2282
				'confirm'           => __( 'Are you sure?', 'formidable' ),
2283
				'conf_delete'       => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
2284
				'conf_delete_sec'   => __( 'WARNING: This will delete all fields inside of the section as well.', 'formidable' ),
2285
				'conf_no_repeat'    => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
2286
				'default_unique'    => $frm_settings->unique_msg,
2287
				'default_conf'      => __( 'The entered values do not match', 'formidable' ),
2288
				'enter_email'       => __( 'Enter Email', 'formidable' ),
2289
				'confirm_email'     => __( 'Confirm Email', 'formidable' ),
2290
				'conditional_text'  => __( 'Conditional content here', 'formidable' ),
2291
				'new_option'        => __( 'New Option', 'formidable' ),
2292
				'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' ),
2293
				'enter_password'    => __( 'Enter Password', 'formidable' ),
2294
				'confirm_password'  => __( 'Confirm Password', 'formidable' ),
2295
				'import_complete'   => __( 'Import Complete', 'formidable' ),
2296
				'updating'          => __( 'Please wait while your site updates.', 'formidable' ),
2297
				'no_save_warning'   => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
2298
				'private'           => __( 'Private', 'formidable' ),
2299
				'jquery_ui_url'     => self::jquery_ui_base_url(),
2300
				'pro_url'           => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
2301
				'no_licenses'       => __( 'No new licenses were found', 'formidable' ),
2302
				'unmatched_parens'  => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
2303
				'view_shortcodes'   => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
2304
				'text_shortcodes'   => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
2305
				'repeat_limit_min'  => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
2306
				'checkbox_limit'    => __( 'Please select a limit between 0 and 200.', 'formidable' ),
2307
				'install'           => __( 'Install', 'formidable' ),
2308
				'active'            => __( 'Active', 'formidable' ),
2309
				'no_items_found'    => __( 'No items found.', 'formidable' ),
2310
			);
2311
			wp_localize_script( 'formidable_admin', 'frm_admin_js', $admin_script_strings );
2312
		}
2313
	}
2314
2315
	/**
2316
	 * Echo the message on the plugins listing page
2317
	 *
2318
	 * @since 1.07.10
2319
	 *
2320
	 * @param float $min_version The version the add-on requires
2321
	 */
2322
	public static function min_version_notice( $min_version ) {
2323
		$frm_version = self::plugin_version();
2324
2325
		// Check if Formidable meets minimum requirements.
2326
		if ( version_compare( $frm_version, $min_version, '>=' ) ) {
2327
			return;
2328
		}
2329
2330
		$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
2331
		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">' .
2332
			esc_html__( 'You are running an outdated version of Formidable. This plugin may not work correctly if you do not update Formidable.', 'formidable' ) .
2333
			'</div></td></tr>';
2334
	}
2335
2336
	/**
2337
	 * If Pro is far outdated, show a message.
2338
	 *
2339
	 * @since 4.0.01
2340
	 */
2341
	public static function min_pro_version_notice( $min_version ) {
2342
		if ( ! self::is_formidable_admin() ) {
2343
			// Don't show admin-wide.
2344
			return;
2345
		}
2346
2347
		self::php_version_notice();
2348
2349
		$is_pro = self::pro_is_installed() && class_exists( 'FrmProDb' );
2350
		if ( ! $is_pro || self::meets_min_pro_version( $min_version ) ) {
2351
			return;
2352
		}
2353
2354
		$pro_version = FrmProDb::$plug_version;
0 ignored issues
show
Unused Code introduced by
$pro_version is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2355
		$expired = FrmAddonsController::is_license_expired();
2356
		?>
2357
		<div class="error frm_previous_install">
2358
			<?php
2359
			esc_html_e( 'You are running a version of Formidable Forms that may not be compatible with your version of Formidable Forms Pro.', 'formidable' );
2360
			if ( empty( $expired ) ) {
2361
				echo ' Please <a href="' . esc_url( admin_url( 'plugins.php?s=formidable%20forms%20pro' ) ) . '">update now</a>.';
2362
			} else {
2363
				echo '<br/>Please <a href="https://formidableforms.com/account/downloads/?utm_source=WordPress&utm_medium=outdated">renew now</a> to get the latest Pro version or <a href="https://downloads.wordpress.org/plugin/formidable.<?php echo esc_attr( $pro_version ); ?>.zip">download the previous Lite version</a> to revert.';
2364
			}
2365
			?>
2366
		</div>
2367
		<?php
2368
	}
2369
2370
	/**
2371
	 * If Pro is installed, check the version number.
2372
	 *
2373
	 * @since 4.0.01
2374
	 */
2375
	public static function meets_min_pro_version( $min_version ) {
2376
		return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
2377
	}
2378
2379
	/**
2380
	 * Show a message if the browser or PHP version is below the recommendations.
2381
	 *
2382
	 * @since 4.0.02
2383
	 */
2384
	private static function php_version_notice() {
2385
		$message = array();
2386
		if ( version_compare( phpversion(), '5.6', '<' ) ) {
2387
			$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' );
2388
		}
2389
2390
		$browser = self::get_server_value( 'HTTP_USER_AGENT' );
2391
		$is_ie   = strpos( $browser, 'MSIE' ) !== false;
2392
		if ( $is_ie ) {
2393
			$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' );
2394
		}
2395
2396
		foreach ( $message as $m ) {
2397
			?>
2398
			<div class="error frm_previous_install">
2399
				<?php echo esc_html( $m ); ?>
2400
			</div>
2401
			<?php
2402
		}
2403
	}
2404
2405
	public static function locales( $type = 'date' ) {
2406
		$locales = array(
2407
			'en'     => __( 'English', 'formidable' ),
2408
			'af'     => __( 'Afrikaans', 'formidable' ),
2409
			'sq'     => __( 'Albanian', 'formidable' ),
2410
			'ar'     => __( 'Arabic', 'formidable' ),
2411
			'hy'     => __( 'Armenian', 'formidable' ),
2412
			'az'     => __( 'Azerbaijani', 'formidable' ),
2413
			'eu'     => __( 'Basque', 'formidable' ),
2414
			'bs'     => __( 'Bosnian', 'formidable' ),
2415
			'bg'     => __( 'Bulgarian', 'formidable' ),
2416
			'ca'     => __( 'Catalan', 'formidable' ),
2417
			'zh-HK'  => __( 'Chinese Hong Kong', 'formidable' ),
2418
			'zh-CN'  => __( 'Chinese Simplified', 'formidable' ),
2419
			'zh-TW'  => __( 'Chinese Traditional', 'formidable' ),
2420
			'hr'     => __( 'Croatian', 'formidable' ),
2421
			'cs'     => __( 'Czech', 'formidable' ),
2422
			'da'     => __( 'Danish', 'formidable' ),
2423
			'nl'     => __( 'Dutch', 'formidable' ),
2424
			'en-GB'  => __( 'English/UK', 'formidable' ),
2425
			'eo'     => __( 'Esperanto', 'formidable' ),
2426
			'et'     => __( 'Estonian', 'formidable' ),
2427
			'fo'     => __( 'Faroese', 'formidable' ),
2428
			'fa'     => __( 'Farsi/Persian', 'formidable' ),
2429
			'fil'    => __( 'Filipino', 'formidable' ),
2430
			'fi'     => __( 'Finnish', 'formidable' ),
2431
			'fr'     => __( 'French', 'formidable' ),
2432
			'fr-CA'  => __( 'French/Canadian', 'formidable' ),
2433
			'fr-CH'  => __( 'French/Swiss', 'formidable' ),
2434
			'de'     => __( 'German', 'formidable' ),
2435
			'de-AT'  => __( 'German/Austria', 'formidable' ),
2436
			'de-CH'  => __( 'German/Switzerland', 'formidable' ),
2437
			'el'     => __( 'Greek', 'formidable' ),
2438
			'he'     => __( 'Hebrew', 'formidable' ),
2439
			'iw'     => __( 'Hebrew', 'formidable' ),
2440
			'hi'     => __( 'Hindi', 'formidable' ),
2441
			'hu'     => __( 'Hungarian', 'formidable' ),
2442
			'is'     => __( 'Icelandic', 'formidable' ),
2443
			'id'     => __( 'Indonesian', 'formidable' ),
2444
			'it'     => __( 'Italian', 'formidable' ),
2445
			'ja'     => __( 'Japanese', 'formidable' ),
2446
			'ko'     => __( 'Korean', 'formidable' ),
2447
			'lv'     => __( 'Latvian', 'formidable' ),
2448
			'lt'     => __( 'Lithuanian', 'formidable' ),
2449
			'ms'     => __( 'Malaysian', 'formidable' ),
2450
			'no'     => __( 'Norwegian', 'formidable' ),
2451
			'pl'     => __( 'Polish', 'formidable' ),
2452
			'pt'     => __( 'Portuguese', 'formidable' ),
2453
			'pt-BR'  => __( 'Portuguese/Brazilian', 'formidable' ),
2454
			'pt-PT'  => __( 'Portuguese/Portugal', 'formidable' ),
2455
			'ro'     => __( 'Romanian', 'formidable' ),
2456
			'ru'     => __( 'Russian', 'formidable' ),
2457
			'sr'     => __( 'Serbian', 'formidable' ),
2458
			'sr-SR'  => __( 'Serbian', 'formidable' ),
2459
			'sk'     => __( 'Slovak', 'formidable' ),
2460
			'sl'     => __( 'Slovenian', 'formidable' ),
2461
			'es'     => __( 'Spanish', 'formidable' ),
2462
			'es-419' => __( 'Spanish/Latin America', 'formidable' ),
2463
			'sv'     => __( 'Swedish', 'formidable' ),
2464
			'ta'     => __( 'Tamil', 'formidable' ),
2465
			'th'     => __( 'Thai', 'formidable' ),
2466
			'tu'     => __( 'Turkish', 'formidable' ),
2467
			'tr'     => __( 'Turkish', 'formidable' ),
2468
			'uk'     => __( 'Ukranian', 'formidable' ),
2469
			'vi'     => __( 'Vietnamese', 'formidable' ),
2470
		);
2471
2472
		if ( $type === 'captcha' ) {
2473
			// remove the languages unavailable for the captcha
2474
			$unset = array( 'af', 'sq', 'hy', 'az', 'eu', 'bs', 'zh-HK', 'eo', 'et', 'fo', 'fr-CH', 'he', 'is', 'ms', 'sr-SR', 'ta', 'tu' );
2475
		} else {
2476
			// remove the languages unavailable for the datepicker
2477
			$unset = array( 'fil', 'fr-CA', 'de-AT', 'de-CH', 'iw', 'hi', 'pt', 'pt-PT', 'es-419', 'tr' );
2478
		}
2479
2480
		$locales = array_diff_key( $locales, array_flip( $unset ) );
2481
		$locales = apply_filters( 'frm_locales', $locales );
2482
2483
		return $locales;
2484
	}
2485
2486
	/**
2487
	 * @deprecated 4.0
2488
	 */
2489
	public static function insert_opt_html( $args ) {
2490
		_deprecated_function( __METHOD__, '4.0', 'FrmFormsHelper::insert_opt_html' );
2491
		FrmFormsHelper::insert_opt_html( $args );
2492
	}
2493
2494
	/**
2495
	 * Used to filter shortcode in text widgets
2496
	 *
2497
	 * @deprecated 2.5.4
2498
	 * @codeCoverageIgnore
2499
	 */
2500
	public static function widget_text_filter_callback( $matches ) {
2501
		return FrmDeprecated::widget_text_filter_callback( $matches );
2502
	}
2503
2504
	/**
2505
	 * @deprecated 3.01
2506
	 * @codeCoverageIgnore
2507
	 */
2508
	public static function sanitize_array( &$values ) {
2509
		FrmDeprecated::sanitize_array( $values );
2510
	}
2511
2512
	/**
2513
	 * @param array $settings
2514
	 * @param string $group
2515
	 *
2516
	 * @since 2.0.6
2517
	 * @deprecated 2.05.06
2518
	 * @codeCoverageIgnore
2519
	 */
2520
	public static function save_settings( $settings, $group ) {
2521
		return FrmDeprecated::save_settings( $settings, $group );
2522
	}
2523
2524
	/**
2525
	 * @since 2.0.4
2526
	 * @deprecated 2.05.06
2527
	 * @codeCoverageIgnore
2528
	 */
2529
	public static function save_json_post( $settings ) {
2530
		return FrmDeprecated::save_json_post( $settings );
2531
	}
2532
2533
	/**
2534
	 * @since 2.0
2535
	 * @deprecated 2.05.06
2536
	 * @codeCoverageIgnore
2537
	 *
2538
	 * @param string $cache_key The unique name for this cache
2539
	 * @param string $group The name of the cache group
2540
	 * @param string $query If blank, don't run a db call
2541
	 * @param string $type The wpdb function to use with this query
2542
	 *
2543
	 * @return mixed $results The cache or query results
2544
	 */
2545
	public static function check_cache( $cache_key, $group = '', $query = '', $type = 'get_var', $time = 300 ) {
2546
		return FrmDeprecated::check_cache( $cache_key, $group, $query, $type, $time );
2547
	}
2548
2549
	/**
2550
	 * @deprecated 2.05.06
2551
	 * @codeCoverageIgnore
2552
	 */
2553
	public static function set_cache( $cache_key, $results, $group = '', $time = 300 ) {
2554
		return FrmDeprecated::set_cache( $cache_key, $results, $group, $time );
2555
	}
2556
2557
	/**
2558
	 * @deprecated 2.05.06
2559
	 * @codeCoverageIgnore
2560
	 */
2561
	public static function add_key_to_group_cache( $key, $group ) {
2562
		FrmDeprecated::add_key_to_group_cache( $key, $group );
2563
	}
2564
2565
	/**
2566
	 * @deprecated 2.05.06
2567
	 * @codeCoverageIgnore
2568
	 */
2569
	public static function get_group_cached_keys( $group ) {
2570
		return FrmDeprecated::get_group_cached_keys( $group );
2571
	}
2572
2573
	/**
2574
	 * @since 2.0
2575
	 * @deprecated 2.05.06
2576
	 * @codeCoverageIgnore
2577
	 * @return mixed The cached value or false
2578
	 */
2579
	public static function check_cache_and_transient( $cache_key ) {
2580
		return FrmDeprecated::check_cache( $cache_key );
2581
	}
2582
2583
	/**
2584
	 * @since 2.0
2585
	 * @deprecated 2.05.06
2586
	 * @codeCoverageIgnore
2587
	 *
2588
	 * @param string $cache_key
2589
	 */
2590
	public static function delete_cache_and_transient( $cache_key, $group = 'default' ) {
2591
		FrmDeprecated::delete_cache_and_transient( $cache_key, $group );
2592
	}
2593
2594
	/**
2595
	 * @since 2.0
2596
	 * @deprecated 2.05.06
2597
	 * @codeCoverageIgnore
2598
	 *
2599
	 * @param string $group The name of the cache group
2600
	 */
2601
	public static function cache_delete_group( $group ) {
2602
		FrmDeprecated::cache_delete_group( $group );
2603
	}
2604
2605
	/**
2606
	 * @since 1.07.10
2607
	 * @deprecated 2.05.06
2608
	 * @codeCoverageIgnore
2609
	 *
2610
	 * @param string $term The value to escape
2611
	 *
2612
	 * @return string The escaped value
2613
	 */
2614
	public static function esc_like( $term ) {
2615
		return FrmDeprecated::esc_like( $term );
2616
	}
2617
2618
	/**
2619
	 * @param string $order_query
2620
	 *
2621
	 * @deprecated 2.05.06
2622
	 * @codeCoverageIgnore
2623
	 */
2624
	public static function esc_order( $order_query ) {
2625
		return FrmDeprecated::esc_order( $order_query );
2626
	}
2627
2628
	/**
2629
	 * @deprecated 2.05.06
2630
	 * @codeCoverageIgnore
2631
	 */
2632
	public static function esc_order_by( &$order_by ) {
2633
		FrmDeprecated::esc_order_by( $order_by );
2634
	}
2635
2636
	/**
2637
	 * @param string $limit
2638
	 *
2639
	 * @deprecated 2.05.06
2640
	 * @codeCoverageIgnore
2641
	 */
2642
	public static function esc_limit( $limit ) {
2643
		return FrmDeprecated::esc_limit( $limit );
2644
	}
2645
2646
	/**
2647
	 * @since 2.0
2648
	 * @deprecated 2.05.06
2649
	 * @codeCoverageIgnore
2650
	 */
2651
	public static function prepare_array_values( $array, $type = '%s' ) {
2652
		return FrmDeprecated::prepare_array_values( $array, $type );
2653
	}
2654
2655
	/**
2656
	 * @deprecated 2.05.06
2657
	 * @codeCoverageIgnore
2658
	 */
2659
	public static function prepend_and_or_where( $starts_with = ' WHERE ', $where = '' ) {
2660
		return FrmDeprecated::prepend_and_or_where( $starts_with, $where );
2661
	}
2662
}
2663