Completed
Push — master ( 2980ec...7d021e )
by Stephanie
15s queued 11s
created

FrmAppHelper::esc_order()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 3
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.05.01';
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
			$is_formidable = self::is_view_builder_page();
209
		}
210
211
		return $is_formidable;
212
	}
213
214
	/**
215
	 * Check for certain page in Formidable settings
216
	 *
217
	 * @since 2.0
218
	 *
219
	 * @param string $page The name of the page to check
220
	 *
221
	 * @return boolean
222
	 */
223
	public static function is_admin_page( $page = 'formidable' ) {
224
		global $pagenow;
225
		$get_page = self::simple_get( 'page', 'sanitize_title' );
226
		if ( $pagenow ) {
227
			// allow this to be true during ajax load i.e. ajax form builder loading
228
			$is_page = ( $pagenow == 'admin.php' || $pagenow == 'admin-ajax.php' ) && $get_page == $page;
229
			if ( $is_page ) {
230
				return true;
231
			}
232
		}
233
234
		return is_admin() && $get_page == $page;
235
	}
236
237
	/**
238
	 * If the current page is for editing or creating a view.
239
	 * Returns false for the views listing page.
240
	 *
241
	 * @since 4.0
242
	 */
243
	public static function is_view_builder_page() {
244
		global $pagenow;
245
246
		if ( $pagenow !== 'post.php' && $pagenow !== 'post-new.php' && $pagenow !== 'edit.php' ) {
247
			return false;
248
		}
249
250
		$post_type = self::simple_get( 'post_type', 'sanitize_title' );
251
252
		if ( empty( $post_type ) ) {
253
			$post_id = self::simple_get( 'post', 'absint' );
254
			$post    = get_post( $post_id );
255
			$post_type = $post ? $post->post_type : '';
256
		}
257
258
		return $post_type === 'frm_display';
259
	}
260
261
	/**
262
	 * Check for the form preview page
263
	 *
264
	 * @since 2.0
265
	 *
266
	 * @param None
267
	 *
268
	 * @return boolean
269
	 */
270
	public static function is_preview_page() {
271
		global $pagenow;
272
		$action = self::simple_get( 'action', 'sanitize_title' );
273
274
		return $pagenow && $pagenow == 'admin-ajax.php' && $action == 'frm_forms_preview';
275
	}
276
277
	/**
278
	 * Check for ajax except the form preview page
279
	 *
280
	 * @since 2.0
281
	 *
282
	 * @param None
283
	 *
284
	 * @return boolean
285
	 */
286
	public static function doing_ajax() {
287
		return wp_doing_ajax() && ! self::is_preview_page();
288
	}
289
290
	public static function js_suffix() {
291
		return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
292
	}
293
294
	/**
295
	 * @since 2.0.8
296
	 */
297
	public static function prevent_caching() {
298
		global $frm_vars;
299
300
		return isset( $frm_vars['prevent_caching'] ) && $frm_vars['prevent_caching'];
301
	}
302
303
	/**
304
	 * Check if on an admin page
305
	 *
306
	 * @since 2.0
307
	 *
308
	 * @param None
309
	 *
310
	 * @return boolean
311
	 */
312
	public static function is_admin() {
313
		return is_admin() && ! wp_doing_ajax();
314
	}
315
316
	/**
317
	 * Check if value contains blank value or empty array
318
	 *
319
	 * @since 2.0
320
	 *
321
	 * @param mixed $value - value to check
322
	 * @param string
323
	 *
324
	 * @return boolean
325
	 */
326
	public static function is_empty_value( $value, $empty = '' ) {
327
		return ( is_array( $value ) && empty( $value ) ) || $value === $empty;
328
	}
329
330
	public static function is_not_empty_value( $value, $empty = '' ) {
331
		return ! self::is_empty_value( $value, $empty );
332
	}
333
334
	/**
335
	 * Get any value from the $_SERVER
336
	 *
337
	 * @since 2.0
338
	 *
339
	 * @param string $value
340
	 *
341
	 * @return string
342
	 */
343
	public static function get_server_value( $value ) {
344
		return isset( $_SERVER[ $value ] ) ? wp_strip_all_tags( wp_unslash( $_SERVER[ $value ] ) ) : '';
345
	}
346
347
	/**
348
	 * Check for the IP address in several places
349
	 * Used by [ip] shortcode
350
	 *
351
	 * @return string The IP address of the current user
352
	 */
353
	public static function get_ip_address() {
354
		$ip_options = array(
355
			'HTTP_CLIENT_IP',
356
			'HTTP_CF_CONNECTING_IP',
357
			'HTTP_X_FORWARDED_FOR',
358
			'HTTP_X_FORWARDED',
359
			'HTTP_X_CLUSTER_CLIENT_IP',
360
			'HTTP_X_REAL_IP',
361
			'HTTP_FORWARDED_FOR',
362
			'HTTP_FORWARDED',
363
			'REMOTE_ADDR',
364
		);
365
		$ip = '';
366
		foreach ( $ip_options as $key ) {
367
			if ( ! isset( $_SERVER[ $key ] ) ) {
368
				continue;
369
			}
370
371
			$key = self::get_server_value( $key );
372
			foreach ( explode( ',', $key ) as $ip ) {
373
				$ip = trim( $ip ); // just to be safe.
374
375
				if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
376
					return sanitize_text_field( $ip );
377
				}
378
			}
379
		}
380
381
		return sanitize_text_field( $ip );
382
	}
383
384
	public static function get_param( $param, $default = '', $src = 'get', $sanitize = '' ) {
385
		if ( strpos( $param, '[' ) ) {
386
			$params = explode( '[', $param );
387
			$param  = $params[0];
388
		}
389
390
		if ( $src == 'get' ) {
391
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
392
			$value = isset( $_POST[ $param ] ) ? wp_unslash( $_POST[ $param ] ) : ( isset( $_GET[ $param ] ) ? wp_unslash( $_GET[ $param ] ) : $default );
393
			if ( ! isset( $_POST[ $param ] ) && isset( $_GET[ $param ] ) && ! is_array( $value ) ) {
394
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
395
				$value = htmlspecialchars_decode( wp_unslash( $_GET[ $param ] ) );
396
			}
397
			self::sanitize_value( $sanitize, $value );
398
		} else {
399
			$value = self::get_simple_request(
400
				array(
401
					'type'     => $src,
402
					'param'    => $param,
403
					'default'  => $default,
404
					'sanitize' => $sanitize,
405
				)
406
			);
407
		}
408
409
		if ( isset( $params ) && is_array( $value ) && ! empty( $value ) ) {
410
			foreach ( $params as $k => $p ) {
411
				if ( ! $k || ! is_array( $value ) ) {
412
					continue;
413
				}
414
415
				$p     = trim( $p, ']' );
416
				$value = isset( $value[ $p ] ) ? $value[ $p ] : $default;
417
			}
418
		}
419
420
		return $value;
421
	}
422
423 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...
424
		return self::get_simple_request(
425
			array(
426
				'type'     => 'post',
427
				'param'    => $param,
428
				'default'  => $default,
429
				'sanitize' => $sanitize,
430
				'serialized' => $serialized,
431
			)
432
		);
433
	}
434
435
	/**
436
	 * @since 2.0
437
	 *
438
	 * @param string $param
439
	 * @param string $sanitize
440
	 * @param string $default
441
	 *
442
	 * @return string|array
443
	 */
444 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...
445
		return self::get_simple_request(
446
			array(
447
				'type'     => 'get',
448
				'param'    => $param,
449
				'default'  => $default,
450
				'sanitize' => $sanitize,
451
			)
452
		);
453
	}
454
455
	/**
456
	 * Get a GET/POST/REQUEST value and sanitize it
457
	 *
458
	 * @since 2.0.6
459
	 *
460
	 * @param array $args
461
	 *
462
	 * @return string|array
463
	 */
464
	public static function get_simple_request( $args ) {
465
		$defaults = array(
466
			'param'    => '',
467
			'default'  => '',
468
			'type'     => 'get',
469
			'sanitize' => 'sanitize_text_field',
470
			'serialized' => false,
471
		);
472
		$args     = wp_parse_args( $args, $defaults );
473
474
		$value = $args['default'];
475
		if ( $args['type'] == 'get' ) {
476 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...
477
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
478
				$value = wp_unslash( $_GET[ $args['param'] ] );
479
			}
480
		} elseif ( $args['type'] == 'post' ) {
481
			if ( isset( $_POST[ $args['param'] ] ) ) {
482
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
483
				$value = wp_unslash( $_POST[ $args['param'] ] );
484
				if ( $args['serialized'] === true && is_serialized_string( $value ) && is_serialized( $value ) ) {
485
					self::unserialize_or_decode( $value );
486
				}
487
			}
488 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...
489
			if ( isset( $_REQUEST[ $args['param'] ] ) ) {
490
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
491
				$value = wp_unslash( $_REQUEST[ $args['param'] ] );
492
			}
493
		}
494
495
		self::sanitize_value( $args['sanitize'], $value );
496
497
		return $value;
498
	}
499
500
	/**
501
	 * Preserve backslashes in a value, but make sure value doesn't get compounding slashes
502
	 *
503
	 * @since 2.0.8
504
	 *
505
	 * @param string $value
506
	 *
507
	 * @return string $value
508
	 */
509
	public static function preserve_backslashes( $value ) {
510
		// If backslashes have already been added, don't add them again
511
		if ( strpos( $value, '\\\\' ) === false ) {
512
			$value = addslashes( $value );
513
		}
514
515
		return $value;
516
	}
517
518
	public static function sanitize_value( $sanitize, &$value ) {
519
		if ( ! empty( $sanitize ) ) {
520
			if ( is_array( $value ) ) {
521
				$temp_values = $value;
522
				foreach ( $temp_values as $k => $v ) {
523
					self::sanitize_value( $sanitize, $value[ $k ] );
524
				}
525
			} else {
526
				$value = call_user_func( $sanitize, $value );
527
			}
528
		}
529
	}
530
531
	public static function sanitize_request( $sanitize_method, &$values ) {
532
		$temp_values = $values;
533
		foreach ( $temp_values as $k => $val ) {
534
			if ( isset( $sanitize_method[ $k ] ) ) {
535
				$values[ $k ] = call_user_func( $sanitize_method[ $k ], $val );
536
			}
537
		}
538
	}
539
540
	/**
541
	 * @since 4.0.04
542
	 */
543
	public static function sanitize_with_html( &$value ) {
544
		self::sanitize_value( 'wp_kses_post', $value );
545
		self::decode_specialchars( $value );
546
	}
547
548
	/**
549
	 * Do wp_specialchars_decode to get back '&' that wp_kses_post might have turned to '&amp;'
550
	 * this MUST be done, else we'll be back to the '& entity' problem.
551
	 *
552
	 * @since 4.0.04
553
	 */
554
	public static function decode_specialchars( &$value ) {
555
		if ( is_array( $value ) ) {
556
			$temp_values = $value;
557
			foreach ( $temp_values as $k => $v ) {
558
				self::decode_specialchars( $value[ $k ] );
559
			}
560
		} else {
561
			self::decode_amp( $value );
562
		}
563
	}
564
565
	/**
566
	 * The wp_specialchars_decode function changes too much.
567
	 * This will leave HTML as is, but still convert &.
568
	 * Adapted from wp_specialchars_decode().
569
	 *
570
	 * @since 4.03.01
571
	 *
572
	 * @param string $string The string to prep.
573
	 */
574
	private static function decode_amp( &$string ) {
575
		// Don't bother if there are no entities - saves a lot of processing
576
		if ( empty( $string ) || strpos( $string, '&' ) === false ) {
577
			return;
578
		}
579
580
		$translation = array(
581
			'&quot;'  => '"',
582
			'&#034;'  => '"',
583
			'&#x22;'  => '"',
584
			'&lt; '   => '< ', // The space preserves the HTML.
585
			'&#060; ' => '< ', // The space preserves the HTML.
586
			'&gt;'    => '>',
587
			'&#062;'  => '>',
588
			'&amp;'   => '&',
589
			'&#038;'  => '&',
590
			'&#x26;'  => '&',
591
		);
592
593
		$translation_preg = array(
594
			'/&#0*34;/'   => '&#034;',
595
			'/&#x0*22;/i' => '&#x22;',
596
			'/&#0*60;/'   => '&#060;',
597
			'/&#0*62;/'   => '&#062;',
598
			'/&#0*38;/'   => '&#038;',
599
			'/&#x0*26;/i' => '&#x26;',
600
		);
601
602
		// Remove zero padding on numeric entities
603
		$string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string );
604
605
		// Replace characters according to translation table
606
		$string = strtr( $string, $translation );
607
	}
608
609
	/**
610
	 * Sanitize the value, and allow some HTML
611
	 *
612
	 * @since 2.0
613
	 *
614
	 * @param string $value
615
	 * @param array|string $allowed 'all' for everything included as defaults
616
	 *
617
	 * @return string
618
	 */
619
	public static function kses( $value, $allowed = array() ) {
620
		$allowed_html = self::allowed_html( $allowed );
621
622
		return wp_kses( $value, $allowed_html );
623
	}
624
625
	/**
626
	 * @since 2.05.03
627
	 */
628
	private static function allowed_html( $allowed ) {
629
		$html         = self::safe_html();
630
		$allowed_html = array();
631
		if ( $allowed == 'all' ) {
632
			$allowed_html = $html;
633
		} elseif ( ! empty( $allowed ) ) {
634
			foreach ( (array) $allowed as $a ) {
635
				$allowed_html[ $a ] = isset( $html[ $a ] ) ? $html[ $a ] : array();
636
			}
637
		}
638
639
		return apply_filters( 'frm_striphtml_allowed_tags', $allowed_html );
640
	}
641
642
	/**
643
	 * @since 2.05.03
644
	 */
645
	private static function safe_html() {
646
		$allow_class = array(
647
			'class' => true,
648
			'id'    => true,
649
		);
650
651
		return array(
652
			'a'          => array(
653
				'class'  => true,
654
				'href'   => true,
655
				'id'     => true,
656
				'rel'    => true,
657
				'target' => true,
658
				'title'  => true,
659
			),
660
			'abbr'       => array(
661
				'title' => true,
662
			),
663
			'aside'      => $allow_class,
664
			'b'          => array(),
665
			'blockquote' => array(
666
				'cite' => true,
667
			),
668
			'br'         => array(),
669
			'cite'       => array(
670
				'title' => true,
671
			),
672
			'code'       => array(),
673
			'defs'       => array(),
674
			'del'        => array(
675
				'datetime' => true,
676
				'title'    => true,
677
			),
678
			'dd'         => array(),
679
			'div'        => array(
680
				'class' => true,
681
				'id'    => true,
682
				'title' => true,
683
				'style' => true,
684
			),
685
			'dl'         => array(),
686
			'dt'         => array(),
687
			'em'         => array(),
688
			'h1'         => $allow_class,
689
			'h2'         => $allow_class,
690
			'h3'         => $allow_class,
691
			'h4'         => $allow_class,
692
			'h5'         => $allow_class,
693
			'h6'         => $allow_class,
694
			'i'          => array(
695
				'class' => true,
696
				'id'    => true,
697
				'icon'  => true,
698
				'style' => true,
699
			),
700
			'img'        => array(
701
				'alt'    => true,
702
				'class'  => true,
703
				'height' => true,
704
				'id'     => true,
705
				'src'    => true,
706
				'width'  => true,
707
			),
708
			'li'         => $allow_class,
709
			'ol'         => $allow_class,
710
			'p'          => $allow_class,
711
			'path'       => array(
712
				'd'    => true,
713
				'fill' => true,
714
			),
715
			'pre'        => array(),
716
			'q'          => array(
717
				'cite'  => true,
718
				'title' => true,
719
			),
720
			'rect'       => array(
721
				'class'  => true,
722
				'fill'   => true,
723
				'height' => true,
724
				'width'  => true,
725
				'x'      => true,
726
				'y'      => true,
727
			),
728
			'section'    => $allow_class,
729
			'span'       => array(
730
				'class' => true,
731
				'id'    => true,
732
				'title' => true,
733
				'style' => true,
734
			),
735
			'strike'     => array(),
736
			'strong'     => array(),
737
			'symbol'     => array(
738
				'class'   => true,
739
				'id'      => true,
740
				'viewbox' => true,
741
			),
742
			'svg'        => array(
743
				'class'   => true,
744
				'id'      => true,
745
				'xmlns'   => true,
746
				'viewbox' => true,
747
				'width'   => true,
748
				'height'  => true,
749
				'style'   => true,
750
			),
751
			'use'        => array(
752
				'href'   => true,
753
				'xlink:href' => true,
754
			),
755
			'ul'         => $allow_class,
756
		);
757
	}
758
759
	/**
760
	 * Used when switching the action for a bulk action
761
	 *
762
	 * @since 2.0
763
	 */
764
	public static function remove_get_action() {
765
		if ( ! isset( $_GET ) ) {
766
			return;
767
		}
768
769
		$action_name = isset( $_GET['action'] ) ? 'action' : ( isset( $_GET['action2'] ) ? 'action2' : '' );
770
		if ( empty( $action_name ) ) {
771
			return;
772
		}
773
774
		$new_action = self::get_param( $action_name, '', 'get', 'sanitize_text_field' );
775
		if ( ! empty( $new_action ) ) {
776
			$_SERVER['REQUEST_URI'] = str_replace( '&action=' . $new_action, '', self::get_server_value( 'REQUEST_URI' ) );
777
		}
778
	}
779
780
	/**
781
	 * Check the WP query for a parameter
782
	 *
783
	 * @since 2.0
784
	 * @return string|array
785
	 */
786
	public static function get_query_var( $value, $param ) {
787
		if ( $value != '' ) {
788
			return $value;
789
		}
790
791
		global $wp_query;
792
		if ( isset( $wp_query->query_vars[ $param ] ) ) {
793
			$value = $wp_query->query_vars[ $param ];
794
		}
795
796
		return $value;
797
	}
798
799
	/**
800
	 * Try to show the SVG if possible. Otherwise, use the font icon.
801
	 *
802
	 * @since 4.0.02
803
	 * @param string $class
804
	 * @param array  $atts
805
	 */
806
	public static function icon_by_class( $class, $atts = array() ) {
807
		$echo = ! isset( $atts['echo'] ) || $atts['echo'];
808
		if ( isset( $atts['echo'] ) ) {
809
			unset( $atts['echo'] );
810
		}
811
812
		$html_atts = self::array_to_html_params( $atts );
813
814
		$icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) );
815
		if ( $icon === $class ) {
816
			$icon = '<i class="' . esc_attr( $class ) . '"' . $html_atts . '></i>';
817
		} else {
818
			$class = strpos( $icon, ' ' ) === false ? '' : ' ' . $icon;
819
			if ( strpos( $icon, ' ' ) ) {
820
				$icon = explode( ' ', $icon );
821
				$icon = reset( $icon );
822
			}
823
			$icon  = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '>
824
				<use xlink:href="#' . esc_attr( $icon ) . '" />
825
			</svg>';
826
		}
827
828
		if ( $echo ) {
829
			echo $icon; // WPCS: XSS ok.
830
		} else {
831
			return $icon;
832
		}
833
	}
834
835
	/**
836
	 * Include svg images.
837
	 *
838
	 * @since 4.0.02
839
	 */
840
	public static function include_svg() {
841
		include_once( self::plugin_path() . '/images/icons.svg' );
842
	}
843
844
	/**
845
	 * Convert an associative array to HTML values.
846
	 *
847
	 * @since 4.0.02
848
	 * @param array $atts
849
	 * @return string
850
	 */
851
	public static function array_to_html_params( $atts ) {
852
		$html = '';
853
		if ( ! empty( $atts ) ) {
854
			foreach ( $atts as $key => $value ) {
855
				$html .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
856
			}
857
		}
858
		return $html;
859
	}
860
861
	/**
862
	 * @since 3.0
863
	 */
864
	public static function get_admin_header( $atts ) {
865
		$has_nav = ( isset( $atts['form'] ) && ! empty( $atts['form'] ) && ( ! isset( $atts['is_template'] ) || ! $atts['is_template'] ) );
866
		if ( ! isset( $atts['close'] ) || empty( $atts['close'] ) ) {
867
			$atts['close'] = admin_url( 'admin.php?page=formidable' );
868
		}
869
		if ( ! isset( $atts['import_link'] ) ) {
870
			$atts['import_link'] = false;
871
		}
872
873
		include( self::plugin_path() . '/classes/views/shared/admin-header.php' );
874
	}
875
876
	/**
877
	 * @since 3.0
878
	 */
879
	public static function add_new_item_link( $atts ) {
880
		if ( isset( $atts['new_link'] ) && ! empty( $atts['new_link'] ) ) { ?>
881
			<a href="<?php echo esc_url( $atts['new_link'] ); ?>" class="button button-primary frm-button-primary frm-with-plus">
882
				<?php self::icon_by_class( 'frmfont frm_plus_icon frm_svg15' ); ?>
883
				<?php esc_html_e( 'Add New', 'formidable' ); ?>
884
			</a>
885
			<?php
886
		} elseif ( isset( $atts['link_hook'] ) ) {
887
			do_action( $atts['link_hook']['hook'], $atts['link_hook']['param'] );
888
		}
889
	}
890
891
	/**
892
	 * @since 3.06
893
	 */
894
	public static function show_search_box( $atts ) {
895
		$defaults = array(
896
			'placeholder' => '',
897
			'tosearch'    => '',
898
			'text'        => __( 'Search', 'formidable' ),
899
			'input_id'    => '',
900
		);
901
		$atts = array_merge( $defaults, $atts );
902
903
		if ( $atts['input_id'] === 'template' && empty( $atts['tosearch'] ) ) {
904
			$atts['tosearch'] = 'frm-card';
905
		}
906
907
		$class = 'frm-search-input';
908
		if ( ! empty( $atts['tosearch'] ) ) {
909
			$class .= ' frm-auto-search';
910
		}
911
912
		$input_id = $atts['input_id'] . '-search-input';
913
914
		?>
915
		<p class="frm-search">
916
			<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>">
917
				<?php echo esc_html( $atts['text'] ); ?>:
918
			</label>
919
			<span class="frmfont frm_search_icon"></span>
920
			<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s"
921
				value="<?php _admin_search_query(); ?>" placeholder="<?php echo esc_attr( $atts['placeholder'] ); ?>"
922
				class="<?php echo esc_attr( $class ); ?>" data-tosearch="<?php echo esc_attr( $atts['tosearch'] ); ?>"
923
				<?php if ( ! empty( $atts['tosearch'] ) ) { ?>
924
				autocomplete="off"
925
				<?php } ?>
926
				/>
927
			<?php
928
			if ( empty( $atts['tosearch'] ) ) {
929
				submit_button( $atts['text'], 'button-secondary', '', false, array( 'id' => 'search-submit' ) );
930
			}
931
			?>
932
		</p>
933
		<?php
934
	}
935
936
	/**
937
	 * @param string $type
938
	 */
939
	public static function trigger_hook_load( $type, $object = null ) {
940
		// Only load the form hooks once.
941
		$hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
942
		if ( ! $hooks_loaded ) {
943
			do_action( 'frm_load_' . $type . '_hooks' );
944
		}
945
	}
946
947
	/**
948
	 * Save all front-end js scripts into a single file
949
	 *
950
	 * @since 3.0
951
	 */
952
	public static function save_combined_js() {
953
		$file_atts = apply_filters(
954
			'frm_js_location',
955
			array(
956
				'file_name'     => 'frm.min.js',
957
				'new_file_path' => self::plugin_path() . '/js',
958
			)
959
		);
960
		$new_file  = new FrmCreateFile( $file_atts );
961
962
		$files = array(
963
			self::plugin_path() . '/js/jquery/jquery.placeholder.min.js',
964
			self::plugin_path() . '/js/formidable.min.js',
965
		);
966
		$files = apply_filters( 'frm_combined_js_files', $files );
967
		$new_file->combine_files( $files );
968
	}
969
970
	/**
971
	 * Check a value from a shortcode to see if true or false.
972
	 * True when value is 1, true, 'true', 'yes'
973
	 *
974
	 * @since 1.07.10
975
	 *
976
	 * @param string $value The value to compare
977
	 *
978
	 * @return boolean True or False
979
	 */
980
	public static function is_true( $value ) {
981
		return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
982
	}
983
984
	public static function get_pages() {
985
		$query = array(
986
			'post_type'   => 'page',
987
			'post_status' => array( 'publish', 'private' ),
988
			'numberposts' => - 1,
989
			'orderby'     => 'title',
990
			'order'       => 'ASC',
991
		);
992
993
		return get_posts( $query );
994
	}
995
996
	/**
997
	 * Renders an autocomplete page selection or a regular dropdown depending on
998
	 * the total page count
999
	 *
1000
	 * @since 4.03.06
1001
	 */
1002
	public static function maybe_autocomplete_pages_options( $args ) {
1003
		$args = self::preformat_selection_args( $args );
1004
1005
		$pages_count = wp_count_posts( 'page' );
1006
1007
		if ( $pages_count->publish <= 50 ) {
1008
			self::wp_pages_dropdown( $args );
1009
			return;
1010
		}
1011
1012
		wp_enqueue_script( 'jquery-ui-autocomplete' );
1013
1014
		$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...
1015
		$title = '';
1016
1017
		if ( $selected ) {
1018
			$title = get_the_title( $selected );
1019
		}
1020
1021
		?>
1022
		<input type="text" class="frm-page-search"
1023
			placeholder="<?php esc_html_e( 'Select a Page', 'formidable' ); ?>"
1024
			value="<?php echo esc_attr( $title ); ?>" />
1025
		<input type="hidden" name="<?php echo esc_attr( $args['field_name'] ); ?>"
1026
			value="<?php echo esc_attr( $selected ); ?>" />
1027
		<?php
1028
	}
1029
1030
	/**
1031
	 * @param array   $args
1032
	 * @param string  $page_id Deprecated.
1033
	 * @param boolean $truncate Deprecated.
1034
	 */
1035
	public static function wp_pages_dropdown( $args = array(), $page_id = '', $truncate = false ) {
1036
		self::prep_page_dropdown_params( $page_id, $truncate, $args );
1037
1038
		$pages    = self::get_pages();
1039
		$selected = self::get_post_param( $args['field_name'], $args['page_id'], 'absint' );
1040
1041
		?>
1042
		<select name="<?php echo esc_attr( $args['field_name'] ); ?>" id="<?php echo esc_attr( $args['field_name'] ); ?>" class="frm-pages-dropdown">
1043
			<option value=""><?php echo esc_html( $args['placeholder'] ); ?></option>
1044
			<?php foreach ( $pages as $page ) { ?>
1045
				<option value="<?php echo esc_attr( $page->ID ); ?>" <?php selected( $selected, $page->ID ); ?>>
1046
					<?php echo esc_html( $args['truncate'] ? self::truncate( $page->post_title, $args['truncate'] ) : $page->post_title ); ?>
1047
				</option>
1048
			<?php } ?>
1049
		</select>
1050
		<?php
1051
	}
1052
1053
	/**
1054
	 * Fill in missing parameters passed to wp_pages_dropdown().
1055
	 * This is for reverse compatibility with switching 3 params to 1.
1056
	 *
1057
	 * @since 4.03.06
1058
	 */
1059
	private static function prep_page_dropdown_params( $page_id, $truncate, &$args ) {
1060
		if ( ! is_array( $args ) ) {
1061
			$args = array(
1062
				'field_name' => $args,
1063
				'page_id'    => $page_id,
1064
				'truncate'   => $truncate,
1065
			);
1066
		}
1067
1068
		$args = self::preformat_selection_args( $args );
1069
	}
1070
1071
	/**
1072
	 * Filter to format args for page dropdown or autocomplete
1073
	 *
1074
	 * @since 4.03.06
1075
	 */
1076
	private static function preformat_selection_args( $args ) {
1077
		$defaults = array(
1078
			'truncate'    => false,
1079
			'placeholder' => ' ',
1080
			'field_name'  => '',
1081
			'page_id'     => '',
1082
		);
1083
1084
		return array_merge( $defaults, $args );
1085
	}
1086
1087
	public static function post_edit_link( $post_id ) {
1088
		$post = get_post( $post_id );
1089
		if ( $post ) {
1090
			$post_url = admin_url( 'post.php?post=' . $post_id . '&action=edit' );
1091
			$post_url = self::maybe_full_screen_link( $post_url );
1092
1093
			return '<a href="' . esc_url( $post_url ) . '">' . self::truncate( $post->post_title, 50 ) . '</a>';
1094
		}
1095
1096
		return '';
1097
	}
1098
1099
	/**
1100
	 * Hide the WordPress menus on some pages.
1101
	 *
1102
	 * @since 4.0
1103
	 */
1104
	public static function is_full_screen() {
1105
		$action       = self::simple_get( 'frm_action', 'sanitize_title' );
1106
		$full_builder = self::is_admin_page( 'formidable' ) && ( $action === 'edit' || $action === 'settings' || $action === 'duplicate' );
1107
		$styler       = self::is_admin_page( 'formidable-styles' ) || self::is_admin_page( 'formidable-styles2' );
1108
		$full_entries = self::simple_get( 'frm-full', 'absint' );
1109
1110
		return $full_builder || $full_entries || $styler || self::is_view_builder_page();
1111
	}
1112
1113
	/**
1114
	 * @since 4.0
1115
	 */
1116
	public static function maybe_full_screen_link( $link ) {
1117
		$is_full = self::simple_get( 'frm-full', 'absint' );
1118
		if ( $is_full && ! empty( $link ) && $link !== '#' ) {
1119
			$link .= '&frm-full=1';
1120
		}
1121
		return $link;
1122
	}
1123
1124
	public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
1125
		?>
1126
		<select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>"
1127
			<?php echo ( 'multiple' === $multiple ) ? 'multiple="multiple"' : ''; ?>
1128
			class="frm_multiselect">
1129
			<?php self::roles_options( $capability ); ?>
1130
		</select>
1131
		<?php
1132
	}
1133
1134
	public static function roles_options( $capability ) {
1135
		global $frm_vars;
1136
		if ( isset( $frm_vars['editable_roles'] ) ) {
1137
			$editable_roles = $frm_vars['editable_roles'];
1138
		} else {
1139
			$editable_roles             = get_editable_roles();
1140
			$frm_vars['editable_roles'] = $editable_roles;
1141
		}
1142
1143
		foreach ( $editable_roles as $role => $details ) {
1144
			$name = translate_user_role( $details['name'] );
1145
			?>
1146
			<option value="<?php echo esc_attr( $role ); ?>" <?php echo in_array( $role, (array) $capability ) ? ' selected="selected"' : ''; ?>><?php echo esc_attr( $name ); ?> </option>
1147
			<?php
1148
			unset( $role, $details );
1149
		}
1150
	}
1151
1152
	public static function frm_capabilities( $type = 'auto' ) {
1153
		$cap = array(
1154
			'frm_view_forms'      => __( 'View Forms', 'formidable' ),
1155
			'frm_edit_forms'      => __( 'Add and Edit Forms', 'formidable' ),
1156
			'frm_delete_forms'    => __( 'Delete Forms', 'formidable' ),
1157
			'frm_change_settings' => __( 'Access this Settings Page', 'formidable' ),
1158
			'frm_view_entries'    => __( 'View Entries from Admin Area', 'formidable' ),
1159
			'frm_delete_entries'  => __( 'Delete Entries from Admin Area', 'formidable' ),
1160
		);
1161
1162
		if ( ! self::pro_is_installed() && 'pro' != $type ) {
1163
			return $cap;
1164
		}
1165
1166
		$cap['frm_create_entries'] = __( 'Add Entries from Admin Area', 'formidable' );
1167
		$cap['frm_edit_entries']   = __( 'Edit Entries from Admin Area', 'formidable' );
1168
		$cap['frm_view_reports']   = __( 'View Reports', 'formidable' );
1169
		$cap['frm_edit_displays']  = __( 'Add/Edit Views', 'formidable' );
1170
1171
		return $cap;
1172
	}
1173
1174
	public static function user_has_permission( $needed_role ) {
1175
		if ( $needed_role == '-1' ) {
1176
			return false;
1177
		}
1178
1179
		// $needed_role will be equal to blank if "Logged-in users" is selected.
1180
		if ( ( $needed_role == '' && is_user_logged_in() ) || current_user_can( $needed_role ) ) {
1181
			return true;
1182
		}
1183
1184
		$roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
1185
		foreach ( $roles as $role ) {
1186
			if ( current_user_can( $role ) ) {
1187
				return true;
1188
			}
1189
			if ( $role == $needed_role ) {
1190
				break;
1191
			}
1192
		}
1193
1194
		return false;
1195
	}
1196
1197
	/**
1198
	 * Make sure administrators can see Formidable menu
1199
	 *
1200
	 * @since 2.0
1201
	 */
1202
	public static function maybe_add_permissions() {
1203
		self::force_capability( 'frm_view_entries' );
1204
1205
		if ( ! current_user_can( 'administrator' ) || current_user_can( 'frm_view_forms' ) ) {
1206
			return;
1207
		}
1208
1209
		$user_id   = get_current_user_id();
1210
		$user      = new WP_User( $user_id );
1211
		$frm_roles = self::frm_capabilities();
1212
		foreach ( $frm_roles as $frm_role => $frm_role_description ) {
1213
			$user->add_cap( $frm_role );
1214
			unset( $frm_role, $frm_role_description );
1215
		}
1216
	}
1217
1218
	/**
1219
	 * Make sure admins have permission to see the menu items
1220
	 *
1221
	 * @since 2.0.6
1222
	 */
1223
	public static function force_capability( $cap = 'frm_change_settings' ) {
1224
		if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
1225
			$role      = get_role( 'administrator' );
1226
			$frm_roles = self::frm_capabilities();
1227
			foreach ( $frm_roles as $frm_role => $frm_role_description ) {
1228
				$role->add_cap( $frm_role );
1229
			}
1230
		}
1231
	}
1232
1233
	/**
1234
	 * Check if the user has permision for action.
1235
	 * Return permission message and stop the action if no permission
1236
	 *
1237
	 * @since 2.0
1238
	 *
1239
	 * @param string $permission
1240
	 */
1241
	public static function permission_check( $permission, $show_message = 'show' ) {
1242
		$permission_error = self::permission_nonce_error( $permission );
1243
		if ( $permission_error !== false ) {
1244
			if ( 'hide' == $show_message ) {
1245
				$permission_error = '';
1246
			}
1247
			wp_die( esc_html( $permission_error ) );
1248
		}
1249
	}
1250
1251
	/**
1252
	 * Check user permission and nonce
1253
	 *
1254
	 * @since 2.0
1255
	 *
1256
	 * @param string $permission
1257
	 *
1258
	 * @return false|string The permission message or false if allowed
1259
	 */
1260
	public static function permission_nonce_error( $permission, $nonce_name = '', $nonce = '' ) {
1261
		if ( ! empty( $permission ) && ! current_user_can( $permission ) && ! current_user_can( 'administrator' ) ) {
1262
			$frm_settings = self::get_settings();
1263
1264
			return $frm_settings->admin_permission;
1265
		}
1266
1267
		$error = false;
1268
		if ( empty( $nonce_name ) ) {
1269
			return $error;
1270
		}
1271
1272
		$nonce_value = ( $_REQUEST && isset( $_REQUEST[ $nonce_name ] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $nonce_name ] ) ) : '';
1273
		if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $nonce_value, $nonce ) ) ) {
1274
			$frm_settings = self::get_settings();
1275
			$error        = $frm_settings->admin_permission;
1276
		}
1277
1278
		return $error;
1279
	}
1280
1281
	public static function checked( $values, $current ) {
1282
		if ( self::check_selected( $values, $current ) ) {
1283
			echo ' checked="checked"';
1284
		}
1285
	}
1286
1287
	public static function check_selected( $values, $current ) {
1288
		$values  = self::recursive_function_map( $values, 'trim' );
1289
		$values  = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
1290
		$current = htmlspecialchars_decode( trim( $current ) );
1291
1292
		return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
1293
	}
1294
1295
	public static function recursive_function_map( $value, $function ) {
1296
		if ( is_array( $value ) ) {
1297
			$original_function = $function;
1298
			if ( count( $value ) ) {
1299
				$function = explode( ', ', FrmDb::prepare_array_values( $value, $function ) );
1300
			} else {
1301
				$function = array( $function );
1302
			}
1303
			if ( ! self::is_assoc( $value ) ) {
1304
				$value = array_map( array( 'FrmAppHelper', 'recursive_function_map' ), $value, $function );
1305
			} else {
1306
				foreach ( $value as $k => $v ) {
1307
					if ( ! is_array( $v ) ) {
1308
						$value[ $k ] = call_user_func( $original_function, $v );
1309
					}
1310
				}
1311
			}
1312
		} else {
1313
			$value = call_user_func( $function, $value );
1314
		}
1315
1316
		return $value;
1317
	}
1318
1319
	public static function is_assoc( $array ) {
1320
		return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
1321
	}
1322
1323
	/**
1324
	 * Flatten a multi-dimensional array
1325
	 */
1326
	public static function array_flatten( $array, $keys = 'keep' ) {
1327
		$return = array();
1328
		foreach ( $array as $key => $value ) {
1329
			if ( is_array( $value ) ) {
1330
				$return = array_merge( $return, self::array_flatten( $value, $keys ) );
1331
			} else {
1332
				if ( $keys == 'keep' ) {
1333
					$return[ $key ] = $value;
1334
				} else {
1335
					$return[] = $value;
1336
				}
1337
			}
1338
		}
1339
1340
		return $return;
1341
	}
1342
1343
	public static function esc_textarea( $text, $is_rich_text = false ) {
1344
		$safe_text = str_replace( '&quot;', '"', $text );
1345
		if ( ! $is_rich_text ) {
1346
			$safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
1347
		}
1348
		$safe_text = str_replace( '&amp; ', '& ', $safe_text );
1349
1350
		return apply_filters( 'esc_textarea', $safe_text, $text );
1351
	}
1352
1353
	/**
1354
	 * Add auto paragraphs to text areas
1355
	 *
1356
	 * @since 2.0
1357
	 */
1358
	public static function use_wpautop( $content ) {
1359
		if ( apply_filters( 'frm_use_wpautop', true ) && ! is_array( $content ) ) {
1360
			$content = wpautop( str_replace( '<br>', '<br />', $content ) );
1361
		}
1362
1363
		return $content;
1364
	}
1365
1366
	public static function replace_quotes( $val ) {
1367
		// Replace double quotes.
1368
		$val = str_replace( array( '&#8220;', '&#8221;', '&#8243;' ), '"', $val );
1369
1370
		// Replace single quotes.
1371
		$val = str_replace( array( '&#8216;', '&#8217;', '&#8242;', '&prime;', '&rsquo;', '&lsquo;' ), "'", $val );
1372
1373
		return $val;
1374
	}
1375
1376
	/**
1377
	 * @since 2.0
1378
	 * @return string The base Google APIS url for the current version of jQuery UI
1379
	 */
1380
	public static function jquery_ui_base_url() {
1381
		$url = 'http' . ( is_ssl() ? 's' : '' ) . '://ajax.googleapis.com/ajax/libs/jqueryui/' . self::script_version( 'jquery-ui-core', '1.11.4' );
1382
		$url = apply_filters( 'frm_jquery_ui_base_url', $url );
1383
1384
		return $url;
1385
	}
1386
1387
	/**
1388
	 * @param string $handle
1389
	 */
1390
	public static function script_version( $handle, $default = 0 ) {
1391
		global $wp_scripts;
1392
		if ( ! $wp_scripts ) {
1393
			return $default;
1394
		}
1395
1396
		$ver = $default;
1397
		if ( ! isset( $wp_scripts->registered[ $handle ] ) ) {
1398
			return $ver;
1399
		}
1400
1401
		$query = $wp_scripts->registered[ $handle ];
1402
		if ( is_object( $query ) && ! empty( $query->ver ) ) {
1403
			$ver = $query->ver;
1404
		}
1405
1406
		return $ver;
1407
	}
1408
1409
	public static function js_redirect( $url ) {
1410
		return '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
1411
	}
1412
1413
	public static function get_user_id_param( $user_id ) {
1414
		if ( ! $user_id || empty( $user_id ) || is_numeric( $user_id ) ) {
1415
			return $user_id;
1416
		}
1417
1418
		$user_id = sanitize_text_field( $user_id );
1419
		if ( $user_id == 'current' ) {
1420
			$user_id = get_current_user_id();
1421
		} else {
1422
			if ( is_email( $user_id ) ) {
1423
				$user = get_user_by( 'email', $user_id );
1424
			} else {
1425
				$user = get_user_by( 'login', $user_id );
1426
			}
1427
1428
			if ( $user ) {
1429
				$user_id = $user->ID;
1430
			}
1431
			unset( $user );
1432
		}
1433
1434
		return $user_id;
1435
	}
1436
1437
	public static function get_file_contents( $filename, $atts = array() ) {
1438
		if ( ! is_file( $filename ) ) {
1439
			return false;
1440
		}
1441
1442
		extract( $atts );
1443
		ob_start();
1444
		include( $filename );
1445
		$contents = ob_get_contents();
1446
		ob_end_clean();
1447
1448
		return $contents;
1449
	}
1450
1451
	/**
1452
	 * @param string $table_name
1453
	 * @param string $column
1454
	 * @param int $id
1455
	 * @param int $num_chars
1456
	 */
1457
	public static function get_unique_key( $name = '', $table_name, $column, $id = 0, $num_chars = 5 ) {
1458
		$key = '';
1459
1460
		if ( ! empty( $name ) ) {
1461
			$key = sanitize_key( $name );
1462
		}
1463
1464
		if ( empty( $key ) ) {
1465
			$max_slug_value = pow( 36, $num_chars );
1466
			$min_slug_value = 37; // we want to have at least 2 characters in the slug
1467
			$key            = base_convert( rand( $min_slug_value, $max_slug_value ), 10, 36 );
1468
		}
1469
1470
		$not_allowed = array(
1471
			'id',
1472
			'key',
1473
			'created-at',
1474
			'detaillink',
1475
			'editlink',
1476
			'siteurl',
1477
			'evenodd',
1478
		);
1479
1480
		if ( is_numeric( $key ) || in_array( $key, $not_allowed ) ) {
1481
			$key = $key . 'a';
1482
		}
1483
1484
		$key_check = FrmDb::get_var(
1485
			$table_name,
1486
			array(
1487
				$column => $key,
1488
				'ID !'  => $id,
1489
			),
1490
			$column
1491
		);
1492
1493
		if ( $key_check || is_numeric( $key_check ) ) {
1494
			// Create a unique field id if it has already been used.
1495
			$key = $key . substr( md5( microtime() . rand() ), 0, 10 );
1496
		}
1497
1498
		return $key;
1499
	}
1500
1501
	/**
1502
	 * Editing a Form or Entry
1503
	 *
1504
	 * @param string $table
1505
	 *
1506
	 * @return bool|array
1507
	 */
1508
	public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
1509
		if ( ! $record ) {
1510
			return false;
1511
		}
1512
1513
		if ( empty( $post_values ) ) {
1514
			$post_values = wp_unslash( $_POST );
1515
		}
1516
1517
		$values = array(
1518
			'id'     => $record->id,
1519
			'fields' => array(),
1520
		);
1521
1522
		foreach ( array( 'name', 'description' ) as $var ) {
1523
			$default_val    = isset( $record->{$var} ) ? $record->{$var} : '';
1524
			$values[ $var ] = self::get_param( $var, $default_val, 'get', 'wp_kses_post' );
1525
			unset( $var, $default_val );
1526
		}
1527
1528
		$values['description'] = self::use_wpautop( $values['description'] );
1529
1530
		self::fill_form_opts( $record, $table, $post_values, $values );
1531
1532
		self::prepare_field_arrays( $fields, $record, $values, array_merge( $args, compact( 'default', 'post_values' ) ) );
1533
1534
		if ( $table == 'entries' ) {
1535
			$values = FrmEntriesHelper::setup_edit_vars( $values, $record );
1536
		} elseif ( $table == 'forms' ) {
1537
			$values = FrmFormsHelper::setup_edit_vars( $values, $record, $post_values );
1538
		}
1539
1540
		return $values;
1541
	}
1542
1543
	private static function prepare_field_arrays( $fields, $record, array &$values, $args ) {
1544
		if ( ! empty( $fields ) ) {
1545
			foreach ( (array) $fields as $field ) {
1546
				if ( ! self::is_admin_page() ) {
1547
					// Don't prep default values on the form settings page.
1548
					$field->default_value = apply_filters( 'frm_get_default_value', $field->default_value, $field, true );
1549
				}
1550
				$args['parent_form_id'] = isset( $args['parent_form_id'] ) ? $args['parent_form_id'] : $field->form_id;
1551
				self::fill_field_defaults( $field, $record, $values, $args );
1552
			}
1553
		}
1554
	}
1555
1556
	private static function fill_field_defaults( $field, $record, array &$values, $args ) {
1557
		$post_values = $args['post_values'];
1558
1559
		if ( $args['default'] ) {
1560
			$meta_value = $field->default_value;
1561
		} else {
1562
			if ( $record->post_id && self::pro_is_installed() && isset( $field->field_options['post_field'] ) && $field->field_options['post_field'] ) {
1563
				if ( ! isset( $field->field_options['custom_field'] ) ) {
1564
					$field->field_options['custom_field'] = '';
1565
				}
1566
				$meta_value = FrmProEntryMetaHelper::get_post_value(
1567
					$record->post_id,
1568
					$field->field_options['post_field'],
1569
					$field->field_options['custom_field'],
1570
					array(
1571
						'truncate' => false,
1572
						'type'     => $field->type,
1573
						'form_id'  => $field->form_id,
1574
						'field'    => $field,
1575
					)
1576
				);
1577
			} else {
1578
				$meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
1579
			}
1580
		}
1581
1582
		$field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
1583
		if ( isset( $post_values['item_meta'][ $field->id ] ) ) {
1584
			$new_value = $post_values['item_meta'][ $field->id ];
1585
			self::unserialize_or_decode( $new_value );
1586
		} else {
1587
			$new_value = $meta_value;
1588
		}
1589
1590
		$field_array                   = self::start_field_array( $field );
1591
		$field_array['value']          = $new_value;
1592
		$field_array['type']           = apply_filters( 'frm_field_type', $field_type, $field, $new_value );
1593
		$field_array['parent_form_id'] = $args['parent_form_id'];
1594
1595
		$args['field_type'] = $field_type;
1596
1597
		FrmFieldsHelper::prepare_edit_front_field( $field_array, $field, $values['id'], $args );
1598
1599
		if ( ! isset( $field_array['unique'] ) || ! $field_array['unique'] ) {
1600
			$field_array['unique_msg'] = '';
1601
		}
1602
1603
		$field_array = array_merge( (array) $field->field_options, $field_array );
1604
1605
		$values['fields'][ $field->id ] = $field_array;
1606
	}
1607
1608
	/**
1609
	 * @since 3.0
1610
	 *
1611
	 * @param object $field
1612
	 *
1613
	 * @return array
1614
	 */
1615
	public static function start_field_array( $field ) {
1616
		return array(
1617
			'id'            => $field->id,
1618
			'default_value' => $field->default_value,
1619
			'name'          => $field->name,
1620
			'description'   => $field->description,
1621
			'options'       => $field->options,
1622
			'required'      => $field->required,
1623
			'field_key'     => $field->field_key,
1624
			'field_order'   => $field->field_order,
1625
			'form_id'       => $field->form_id,
1626
		);
1627
	}
1628
1629
	/**
1630
	 * @param string $table
1631
	 */
1632
	private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
1633
		if ( $table == 'entries' ) {
1634
			$form = $record->form_id;
1635
			FrmForm::maybe_get_form( $form );
1636
		} else {
1637
			$form = $record;
1638
		}
1639
1640
		if ( ! $form ) {
1641
			return;
1642
		}
1643
1644
		$values['form_name']      = isset( $record->form_id ) ? $form->name : '';
1645
		$values['parent_form_id'] = isset( $record->form_id ) ? $form->parent_form_id : 0;
1646
1647
		if ( ! is_array( $form->options ) ) {
1648
			return;
1649
		}
1650
1651
		foreach ( $form->options as $opt => $value ) {
1652
			if ( isset( $post_values[ $opt ] ) ) {
1653
				$values[ $opt ] = $post_values[ $opt ];
1654
				self::unserialize_or_decode( $values[ $opt ] );
1655
			} else {
1656
				$values[ $opt ] = $value;
1657
			}
1658
		}
1659
1660
		self::fill_form_defaults( $post_values, $values );
1661
	}
1662
1663
	/**
1664
	 * Set to POST value or default
1665
	 */
1666
	private static function fill_form_defaults( $post_values, array &$values ) {
1667
		$form_defaults = FrmFormsHelper::get_default_opts();
1668
1669
		foreach ( $form_defaults as $opt => $default ) {
1670
			if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
1671
				$values[ $opt ] = ( $post_values && isset( $post_values['options'][ $opt ] ) ) ? $post_values['options'][ $opt ] : $default;
1672
			}
1673
1674
			unset( $opt, $default );
1675
		}
1676
1677
		if ( ! isset( $values['custom_style'] ) ) {
1678
			$values['custom_style'] = self::custom_style_value( $post_values );
1679
		}
1680
1681
		foreach ( array( 'before', 'after', 'submit' ) as $h ) {
1682
			if ( ! isset( $values[ $h . '_html' ] ) ) {
1683
				$values[ $h . '_html' ] = ( isset( $post_values['options'][ $h . '_html' ] ) ? $post_values['options'][ $h . '_html' ] : FrmFormsHelper::get_default_html( $h ) );
1684
			}
1685
			unset( $h );
1686
		}
1687
	}
1688
1689
	/**
1690
	 * @since 2.2.10
1691
	 *
1692
	 * @param array $post_values
1693
	 *
1694
	 * @return boolean|int
1695
	 */
1696
	public static function custom_style_value( $post_values ) {
1697
		if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
1698
			$custom_style = absint( $post_values['options']['custom_style'] );
1699
		} else {
1700
			$frm_settings = self::get_settings();
1701
			$custom_style = ( $frm_settings->load_style != 'none' );
1702
		}
1703
1704
		return $custom_style;
1705
	}
1706
1707
	public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
1708
		if ( is_array( $str ) ) {
1709
			return '';
1710
		}
1711
1712
		$length       = (int) $length;
1713
		$str          = wp_strip_all_tags( $str );
1714
		$original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
1715
1716
		if ( $length == 0 ) {
1717
			return '';
1718
		} elseif ( $length <= 10 ) {
1719
			$sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
1720
1721
			return $sub . ( ( $length < $original_len ) ? $continue : '' );
1722
		}
1723
1724
		$sub = '';
1725
		$len = 0;
1726
1727
		$words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
1728
1729
		foreach ( $words as $word ) {
1730
			$part      = ( ( $sub != '' ) ? ' ' : '' ) . $word;
1731
			$total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
1732
			if ( $total_len > $length && substr_count( $sub, ' ' ) ) {
1733
				break;
1734
			}
1735
1736
			$sub .= $part;
1737
			$len += self::mb_function( array( 'mb_strlen', 'strlen' ), array( $part ) );
1738
1739
			if ( substr_count( $sub, ' ' ) > $minword && $total_len >= $length ) {
1740
				break;
1741
			}
1742
1743
			unset( $total_len, $word );
1744
		}
1745
1746
		return $sub . ( ( $len < $original_len ) ? $continue : '' );
1747
	}
1748
1749
	public static function mb_function( $function_names, $args ) {
1750
		$mb_function_name = $function_names[0];
1751
		$function_name    = $function_names[1];
1752
		if ( function_exists( $mb_function_name ) ) {
1753
			$function_name = $mb_function_name;
1754
		}
1755
1756
		return call_user_func_array( $function_name, $args );
1757
	}
1758
1759
	public static function get_formatted_time( $date, $date_format = '', $time_format = '' ) {
1760
		if ( empty( $date ) ) {
1761
			return $date;
1762
		}
1763
1764
		if ( empty( $date_format ) ) {
1765
			$date_format = get_option( 'date_format' );
1766
		}
1767
1768
		if ( preg_match( '/^\d{1-2}\/\d{1-2}\/\d{4}$/', $date ) && self::pro_is_installed() ) {
1769
			$frmpro_settings = new FrmProSettings();
1770
			$date            = FrmProAppHelper::convert_date( $date, $frmpro_settings->date_format, 'Y-m-d' );
1771
		}
1772
1773
		$formatted = self::get_localized_date( $date_format, $date );
1774
1775
		$do_time = ( gmdate( 'H:i:s', strtotime( $date ) ) != '00:00:00' );
1776
		if ( $do_time ) {
1777
			$formatted .= self::add_time_to_date( $time_format, $date );
1778
		}
1779
1780
		return $formatted;
1781
	}
1782
1783
	private static function add_time_to_date( $time_format, $date ) {
1784
		if ( empty( $time_format ) ) {
1785
			$time_format = get_option( 'time_format' );
1786
		}
1787
1788
		$trimmed_format = trim( $time_format );
1789
		$time           = '';
1790
		if ( $time_format && ! empty( $trimmed_format ) ) {
1791
			$time = ' ' . __( 'at', 'formidable' ) . ' ' . self::get_localized_date( $time_format, $date );
1792
		}
1793
1794
		return $time;
1795
	}
1796
1797
	/**
1798
	 * @since 2.0.8
1799
	 */
1800
	public static function get_localized_date( $date_format, $date ) {
1801
		$date = get_date_from_gmt( $date );
1802
1803
		return date_i18n( $date_format, strtotime( $date ) );
1804
	}
1805
1806
	/**
1807
	 * Gets the time ago in words
1808
	 *
1809
	 * @param int $from in seconds
1810
	 * @param int|string $to in seconds
1811
	 *
1812
	 * @return string $time_ago
1813
	 */
1814
	public static function human_time_diff( $from, $to = '', $levels = 1 ) {
1815
		if ( empty( $to ) ) {
1816
			$now = new DateTime();
1817
		} else {
1818
			$now = new DateTime( '@' . $to );
1819
		}
1820
		$ago = new DateTime( '@' . $from );
1821
1822
		// Get the time difference
1823
		$diff_object = $now->diff( $ago );
1824
		$diff        = get_object_vars( $diff_object );
1825
1826
		// Add week amount and update day amount
1827
		$diff['w'] = floor( $diff['d'] / 7 );
1828
		$diff['d'] -= $diff['w'] * 7;
1829
1830
		$time_strings = self::get_time_strings();
1831
1832
		if ( ! is_numeric( $levels ) ) {
1833
			// Show time in specified unit.
1834
			$levels = self::get_unit( $levels );
1835
			if ( isset( $time_strings[ $levels ] ) ) {
1836
				$diff = array(
1837
					$levels => self::time_format( $levels, $diff ),
1838
				);
1839
				$time_strings = array(
1840
					$levels => $time_strings[ $levels ],
1841
				);
1842
			}
1843
			$levels = 1;
1844
		}
1845
1846
		foreach ( $time_strings as $k => $v ) {
1847
			if ( isset( $diff[ $k ] ) && $diff[ $k ] ) {
1848
				$time_strings[ $k ] = $diff[ $k ] . ' ' . ( $diff[ $k ] > 1 ? $v[1] : $v[0] );
1849
			} elseif ( isset( $diff[ $k ] ) && count( $time_strings ) === 1 ) {
1850
				// Account for 0.
1851
				$time_strings[ $k ] = $diff[ $k ] . ' ' . $v[1];
1852
			} else {
1853
				unset( $time_strings[ $k ] );
1854
			}
1855
		}
1856
1857
		$levels_deep     = apply_filters( 'frm_time_ago_levels', $levels, compact( 'time_strings', 'from', 'to' ) );
1858
		$time_strings    = array_slice( $time_strings, 0, absint( $levels_deep ) );
1859
		$time_ago_string = implode( ' ', $time_strings );
1860
1861
		return $time_ago_string;
1862
	}
1863
1864
	/**
1865
	 * @since 4.05.01
1866
	 */
1867
	private static function time_format( $unit, $diff ) {
1868
		$return = array(
1869
			'y' => 'y',
1870
			'd' => 'days',
1871
		);
1872
		if ( isset( $return[ $unit ] ) ) {
1873
			return $diff[ $return[ $unit ] ];
1874
		}
1875
1876
		$total = $diff['days'] * self::convert_time( 'd', $unit );
1877
1878
		$times = array( 'h', 'i', 's' );
1879
1880
		foreach ( $times as $time ) {
1881
			if ( ! isset( $diff[ $time ] ) ) {
1882
				continue;
1883
			}
1884
1885
			$total += $diff[ $time ] * self::convert_time( $time, $unit );
1886
		}
1887
1888
		return floor( $total );
1889
	}
1890
1891
	/**
1892
	 * @since 4.05.01
1893
	 */
1894
	private static function convert_time( $from, $to ) {
1895
		$convert = array(
1896
			's' => 1,
1897
			'i' => MINUTE_IN_SECONDS,
1898
			'h' => HOUR_IN_SECONDS,
1899
			'd' => DAY_IN_SECONDS,
1900
			'w' => WEEK_IN_SECONDS,
1901
			'm' => DAY_IN_SECONDS * 30.42,
1902
			'y' => DAY_IN_SECONDS * 365.25,
1903
		);
1904
1905
		return $convert[ $from ] / $convert[ $to ];
1906
	}
1907
1908
	/**
1909
	 * @since 4.05.01
1910
	 */
1911
	private static function get_unit( $unit ) {
1912
		$units = self::get_time_strings();
1913
		if ( isset( $units[ $unit ] ) || is_numeric( $unit ) ) {
1914
			return $unit;
1915
		}
1916
1917
		foreach ( $units as $u => $strings ) {
1918
			if ( in_array( $unit, $strings ) ) {
1919
				return $u;
1920
			}
1921
		}
1922
		return 1;
1923
	}
1924
1925
	/**
1926
	 * Get the translatable time strings. The untranslated version is a failsafe
1927
	 * in case langauges are changing for the unit set in the shortcode.
1928
	 *
1929
	 * @since 2.0.20
1930
	 * @return array
1931
	 */
1932
	private static function get_time_strings() {
1933
		return array(
1934
			'y' => array(
1935
				__( 'year', 'formidable' ),
1936
				__( 'years', 'formidable' ),
1937
				'year',
1938
			),
1939
			'm' => array(
1940
				__( 'month', 'formidable' ),
1941
				__( 'months', 'formidable' ),
1942
				'month',
1943
			),
1944
			'w' => array(
1945
				__( 'week', 'formidable' ),
1946
				__( 'weeks', 'formidable' ),
1947
				'week',
1948
			),
1949
			'd' => array(
1950
				__( 'day', 'formidable' ),
1951
				__( 'days', 'formidable' ),
1952
				'day',
1953
			),
1954
			'h' => array(
1955
				__( 'hour', 'formidable' ),
1956
				__( 'hours', 'formidable' ),
1957
				'hour',
1958
			),
1959
			'i' => array(
1960
				__( 'minute', 'formidable' ),
1961
				__( 'minutes', 'formidable' ),
1962
				'minute',
1963
			),
1964
			's' => array(
1965
				__( 'second', 'formidable' ),
1966
				__( 'seconds', 'formidable' ),
1967
				'second',
1968
			),
1969
		);
1970
	}
1971
1972
	// Pagination Methods.
1973
1974
	/**
1975
	 * @param integer $current_p
1976
	 */
1977
	public static function get_last_record_num( $r_count, $current_p, $p_size ) {
1978
		return ( ( $r_count < ( $current_p * $p_size ) ) ? $r_count : ( $current_p * $p_size ) );
1979
	}
1980
1981
	/**
1982
	 * @param integer $current_p
1983
	 */
1984
	public static function get_first_record_num( $r_count, $current_p, $p_size ) {
1985
		if ( $current_p == 1 ) {
1986
			return 1;
1987
		} else {
1988
			return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
1989
		}
1990
	}
1991
1992
	/**
1993
	 * @return array
1994
	 */
1995
	public static function json_to_array( $json_vars ) {
1996
		$vars = array();
1997
		foreach ( $json_vars as $jv ) {
1998
			$jv_name = explode( '[', $jv['name'] );
1999
			$last    = count( $jv_name ) - 1;
2000
			foreach ( $jv_name as $p => $n ) {
2001
				$name = trim( $n, ']' );
2002
				if ( ! isset( $l1 ) ) {
2003
					$l1 = $name;
2004
				}
2005
2006
				if ( ! isset( $l2 ) ) {
2007
					$l2 = $name;
2008
				}
2009
2010
				if ( ! isset( $l3 ) ) {
2011
					$l3 = $name;
2012
				}
2013
2014
				$this_val = ( $p == $last ) ? $jv['value'] : array();
2015
2016
				switch ( $p ) {
2017
					case 0:
2018
						$l1 = $name;
2019
						self::add_value_to_array( $name, $l1, $this_val, $vars );
2020
						break;
2021
2022
					case 1:
2023
						$l2 = $name;
2024
						self::add_value_to_array( $name, $l2, $this_val, $vars[ $l1 ] );
2025
						break;
2026
2027 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...
2028
						$l3 = $name;
2029
						self::add_value_to_array( $name, $l3, $this_val, $vars[ $l1 ][ $l2 ] );
2030
						break;
2031
2032 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...
2033
						$l4 = $name;
2034
						self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
2035
				}
2036
2037
				unset( $this_val, $n );
2038
			}
2039
2040
			unset( $last, $jv );
2041
		}
2042
2043
		return $vars;
2044
	}
2045
2046
	/**
2047
	 * @param string $name
2048
	 * @param string $l1
2049
	 */
2050
	public static function add_value_to_array( $name, $l1, $val, &$vars ) {
2051
		if ( $name == '' ) {
2052
			$vars[] = $val;
2053
		} elseif ( ! isset( $vars[ $l1 ] ) ) {
2054
			$vars[ $l1 ] = $val;
2055
		}
2056
	}
2057
2058
	public static function maybe_add_tooltip( $name, $class = 'closed', $form_name = '' ) {
2059
		$tooltips = array(
2060
			'action_title'  => __( 'Give this action a label for easy reference.', 'formidable' ),
2061
			'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' ),
2062
			'cc'            => __( 'Add CC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
2063
			'bcc'           => __( 'Add BCC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
2064
			'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' ),
2065
			'from'          => __( 'Enter the name and/or email address of the sender. FORMAT: John Bates <[email protected]> or [email protected].', 'formidable' ),
2066
			/* translators: %1$s: Form name, %2$s: Date */
2067
			'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() ) ),
2068
		);
2069
2070
		if ( ! isset( $tooltips[ $name ] ) ) {
2071
			return;
2072
		}
2073
2074
		if ( 'open' == $class ) {
2075
			echo ' frm_help"';
2076
		} else {
2077
			echo ' class="frm_help"';
2078
		}
2079
2080
		echo ' title="' . esc_attr( $tooltips[ $name ] );
2081
2082
		if ( 'open' != $class ) {
2083
			echo '"';
2084
		}
2085
	}
2086
2087
	/**
2088
	 * Add the current_page class to that page in the form nav
2089
	 */
2090
	public static function select_current_page( $page, $current_page, $action = array() ) {
2091
		if ( $current_page != $page ) {
2092
			return;
2093
		}
2094
2095
		$frm_action = self::simple_get( 'frm_action', 'sanitize_title' );
2096
		if ( empty( $action ) || ( ! empty( $frm_action ) && in_array( $frm_action, $action ) ) ) {
2097
			echo ' class="current_page"';
2098
		}
2099
	}
2100
2101
	/**
2102
	 * Prepare and json_encode post content
2103
	 *
2104
	 * @since 2.0
2105
	 *
2106
	 * @param array $post_content
2107
	 *
2108
	 * @return string $post_content ( json encoded array )
2109
	 */
2110
	public static function prepare_and_encode( $post_content ) {
2111
		// Loop through array to strip slashes and add only the needed ones.
2112
		foreach ( $post_content as $key => $val ) {
2113
			// Replace problematic characters (like &quot;)
2114
			$val = str_replace( '&quot;', '"', $val );
2115
2116
			self::prepare_action_slashes( $val, $key, $post_content );
2117
			unset( $key, $val );
2118
		}
2119
2120
		// json_encode the array.
2121
		$post_content = json_encode( $post_content );
2122
2123
		// Add extra slashes for \r\n since WP strips them.
2124
		$post_content = str_replace( array( '\\r', '\\n', '\\u', '\\t' ), array( '\\\\r', '\\\\n', '\\\\u', '\\\\t' ), $post_content );
2125
2126
		// allow for &quot
2127
		$post_content = str_replace( '&quot;', '\\"', $post_content );
2128
2129
		return $post_content;
2130
	}
2131
2132
	private static function prepare_action_slashes( $val, $key, &$post_content ) {
2133
		if ( ! isset( $post_content[ $key ] ) ) {
2134
			return;
2135
		}
2136
2137
		if ( is_array( $val ) ) {
2138
			foreach ( $val as $k1 => $v1 ) {
2139
				self::prepare_action_slashes( $v1, $k1, $post_content[ $key ] );
2140
				unset( $k1, $v1 );
2141
			}
2142
		} else {
2143
			// Strip all slashes so everything is the same, no matter where the value is coming from
2144
			$val = stripslashes( $val );
2145
2146
			// Add backslashes before double quotes and forward slashes only
2147
			$post_content[ $key ] = addcslashes( $val, '"\\/' );
2148
		}
2149
	}
2150
2151
	/**
2152
	 * Check for either json or serilized data. This is temporary while transitioning
2153
	 * all data to json.
2154
	 *
2155
	 * @since 4.02.03
2156
	 */
2157
	public static function unserialize_or_decode( &$value ) {
2158
		if ( is_array( $value ) ) {
2159
			return;
2160
		}
2161
2162
		if ( is_serialized( $value ) ) {
2163
			$value = maybe_unserialize( $value );
2164
		} else {
2165
			$value = self::maybe_json_decode( $value, false );
2166
		}
2167
	}
2168
2169
	/**
2170
	 * Decode a JSON string.
2171
	 * Do not switch shortcodes like [24] to array unless intentional ie XML values.
2172
	 */
2173
	public static function maybe_json_decode( $string, $single_to_array = true ) {
2174
		if ( is_array( $string ) ) {
2175
			return $string;
2176
		}
2177
2178
		$new_string = json_decode( $string, true );
2179
		if ( function_exists( 'json_last_error' ) ) {
2180
			// php 5.3+
2181
			$single_value = false;
2182
			if ( ! $single_to_array ) {
2183
				$single_value = is_array( $new_string ) && count( $new_string ) === 1 && isset( $new_string[0] );
2184
			}
2185
			if ( json_last_error() == JSON_ERROR_NONE && is_array( $new_string ) && ! $single_value ) {
2186
				$string = $new_string;
2187
			}
2188
		}
2189
2190
		return $string;
2191
	}
2192
2193
	/**
2194
	 * Reformat the json serialized array in name => value array.
2195
	 *
2196
	 * @since 4.02.03
2197
	 */
2198
	public static function format_form_data( &$form ) {
2199
		$formatted = array();
2200
2201
		foreach ( $form as $input ) {
2202
			if ( ! isset( $input['name'] ) ) {
2203
				continue;
2204
			}
2205
			$key = $input['name'];
2206
			if ( isset( $formatted[ $key ] ) ) {
2207
				if ( is_array( $formatted[ $key ] ) ) {
2208
					$formatted[ $key ][] = $input['value'];
2209
				} else {
2210
					$formatted[ $key ] = array( $formatted[ $key ], $input['value'] );
2211
				}
2212
			} else {
2213
				$formatted[ $key ] = $input['value'];
2214
			}
2215
		}
2216
2217
		parse_str( http_build_query( $formatted ), $form );
2218
	}
2219
2220
	/**
2221
	 * @since 4.02.03
2222
	 */
2223
	public static function maybe_json_encode( $value ) {
2224
		if ( is_array( $value ) ) {
2225
			$value = wp_json_encode( $value );
2226
		}
2227
		return $value;
2228
	}
2229
2230
	/**
2231
	 * @since 1.07.10
2232
	 *
2233
	 * @param string $post_type The name of the post type that may need to be highlighted
2234
	 * echo The javascript to open and highlight the Formidable menu
2235
	 */
2236
	public static function maybe_highlight_menu( $post_type ) {
2237
		global $post;
2238
2239
		if ( isset( $_REQUEST['post_type'] ) && $_REQUEST['post_type'] != $post_type ) {
2240
			return;
2241
		}
2242
2243
		if ( is_object( $post ) && $post->post_type != $post_type ) {
2244
			return;
2245
		}
2246
2247
		self::load_admin_wide_js();
2248
		echo '<script type="text/javascript">jQuery(document).ready(function(){frmSelectSubnav();});</script>';
2249
	}
2250
2251
	/**
2252
	 * Load the JS file on non-Formidable pages in the admin area
2253
	 *
2254
	 * @since 2.0
2255
	 */
2256
	public static function load_admin_wide_js( $load = true ) {
2257
		$version = self::plugin_version();
2258
		wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
2259
2260
		$global_strings = array(
2261
			'updating_msg' => __( 'Please wait while your site updates.', 'formidable' ),
2262
			'deauthorize'  => __( 'Are you sure you want to deauthorize Formidable Forms on this site?', 'formidable' ),
2263
			'url'          => self::plugin_url(),
2264
			'app_url'      => 'https://formidableforms.com/',
2265
			'loading'      => __( 'Loading&hellip;', 'formidable' ),
2266
			'nonce'        => wp_create_nonce( 'frm_ajax' ),
2267
		);
2268
		wp_localize_script( 'formidable_admin_global', 'frmGlobal', $global_strings );
2269
2270
		if ( $load ) {
2271
			wp_enqueue_script( 'formidable_admin_global' );
2272
		}
2273
	}
2274
2275
	/**
2276
	 * @since 2.0.9
2277
	 */
2278
	public static function load_font_style() {
2279
		wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
2280
	}
2281
2282
	/**
2283
	 * @param string $location
2284
	 */
2285
	public static function localize_script( $location ) {
2286
		global $wp_scripts;
2287
2288
		$ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
2289
		$ajax_url = apply_filters( 'frm_ajax_url', $ajax_url );
2290
2291
		$script_strings = array(
2292
			'ajax_url'     => $ajax_url,
2293
			'images_url'   => self::plugin_url() . '/images',
2294
			'loading'      => __( 'Loading&hellip;', 'formidable' ),
2295
			'remove'       => __( 'Remove', 'formidable' ),
2296
			'offset'       => apply_filters( 'frm_scroll_offset', 4 ),
2297
			'nonce'        => wp_create_nonce( 'frm_ajax' ),
2298
			'id'           => __( 'ID', 'formidable' ),
2299
			'no_results'   => __( 'No results match', 'formidable' ),
2300
			'file_spam'    => __( 'That file looks like Spam.', 'formidable' ),
2301
			'calc_error'   => __( 'There is an error in the calculation in the field with key', 'formidable' ),
2302
			'empty_fields' => __( 'Please complete the preceding required fields before uploading a file.', 'formidable' ),
2303
		);
2304
2305
		$data = $wp_scripts->get_data( 'formidable', 'data' );
2306
		if ( empty( $data ) ) {
2307
			wp_localize_script( 'formidable', 'frm_js', $script_strings );
2308
		}
2309
2310
		if ( $location == 'admin' ) {
2311
			$frm_settings         = self::get_settings();
2312
			$admin_script_strings = array(
2313
				'desc'              => __( '(Click to add description)', 'formidable' ),
2314
				'blank'             => __( '(Blank)', 'formidable' ),
2315
				'no_label'          => __( '(no label)', 'formidable' ),
2316
				'saving'            => esc_attr( __( 'Saving', 'formidable' ) ),
2317
				'saved'             => esc_attr( __( 'Saved', 'formidable' ) ),
2318
				'ok'                => __( 'OK', 'formidable' ),
2319
				'cancel'            => __( 'Cancel', 'formidable' ),
2320
				'default_label'     => __( 'Default', 'formidable' ),
2321
				'clear_default'     => __( 'Clear default value when typing', 'formidable' ),
2322
				'no_clear_default'  => __( 'Do not clear default value when typing', 'formidable' ),
2323
				'valid_default'     => __( 'Default value will pass form validation', 'formidable' ),
2324
				'no_valid_default'  => __( 'Default value will NOT pass form validation', 'formidable' ),
2325
				'caution'           => __( 'Heads up', 'formidable' ),
2326
				'confirm'           => __( 'Are you sure?', 'formidable' ),
2327
				'conf_delete'       => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
2328
				'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' ),
2329
				'conf_no_repeat'    => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
2330
				'default_unique'    => $frm_settings->unique_msg,
2331
				'default_conf'      => __( 'The entered values do not match', 'formidable' ),
2332
				'enter_email'       => __( 'Enter Email', 'formidable' ),
2333
				'confirm_email'     => __( 'Confirm Email', 'formidable' ),
2334
				'conditional_text'  => __( 'Conditional content here', 'formidable' ),
2335
				'new_option'        => __( 'New Option', 'formidable' ),
2336
				'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' ),
2337
				'enter_password'    => __( 'Enter Password', 'formidable' ),
2338
				'confirm_password'  => __( 'Confirm Password', 'formidable' ),
2339
				'import_complete'   => __( 'Import Complete', 'formidable' ),
2340
				'updating'          => __( 'Please wait while your site updates.', 'formidable' ),
2341
				'no_save_warning'   => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
2342
				'private_label'     => __( 'Private', 'formidable' ),
2343
				'jquery_ui_url'     => self::jquery_ui_base_url(),
2344
				'pro_url'           => is_callable( 'FrmProAppHelper::plugin_url' ) ? FrmProAppHelper::plugin_url() : '',
2345
				'no_licenses'       => __( 'No new licenses were found', 'formidable' ),
2346
				'unmatched_parens'  => __( 'This calculation has at least one unmatched ( ) { } [ ].', 'formidable' ),
2347
				'view_shortcodes'   => __( 'This calculation may have shortcodes that work in Views but not forms.', 'formidable' ),
2348
				'text_shortcodes'   => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ),
2349
				'only_one_action'   => __( 'This form action is limited to one per form. Please edit the existing form action.', 'formidable' ),
2350
				'unsafe_params'     => FrmFormsHelper::reserved_words(),
2351
				/* Translators: %s is the name of a Detail Page Slug that is a reserved word.*/
2352
				'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ),
2353
				/* 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. */
2354
				'param_is_reserved' => sprintf( __( 'The parameter "%s" is reserved by WordPress. This may cause problems when included in the URL. Is this intentional? ', 'formidable' ), '****' ),
2355
				'reserved_words'    => __( 'See the list of reserved words in WordPress.', 'formidable' ),
2356
				'repeat_limit_min'  => __( 'Please enter a Repeat Limit that is greater than 1.', 'formidable' ),
2357
				'checkbox_limit'    => __( 'Please select a limit between 0 and 200.', 'formidable' ),
2358
				'install'           => __( 'Install', 'formidable' ),
2359
				'active'            => __( 'Active', 'formidable' ),
2360
				'select_a_field'    => __( 'Select a Field', 'formidable' ),
2361
				'no_items_found'    => __( 'No items found.', 'formidable' ),
2362
			);
2363
2364
			$data = $wp_scripts->get_data( 'formidable_admin', 'data' );
2365
			if ( empty( $data ) ) {
2366
				wp_localize_script( 'formidable_admin', 'frm_admin_js', $admin_script_strings );
2367
			}
2368
		}
2369
	}
2370
2371
	/**
2372
	 * Echo the message on the plugins listing page
2373
	 *
2374
	 * @since 1.07.10
2375
	 *
2376
	 * @param float $min_version The version the add-on requires
2377
	 */
2378
	public static function min_version_notice( $min_version ) {
2379
		$frm_version = self::plugin_version();
2380
2381
		// Check if Formidable meets minimum requirements.
2382
		if ( version_compare( $frm_version, $min_version, '>=' ) ) {
2383
			return;
2384
		}
2385
2386
		$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
2387
		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">' .
2388
			esc_html__( 'You are running an outdated version of Formidable. This plugin may not work correctly if you do not update Formidable.', 'formidable' ) .
2389
			'</div></td></tr>';
2390
	}
2391
2392
	/**
2393
	 * If Pro is far outdated, show a message.
2394
	 *
2395
	 * @since 4.0.01
2396
	 */
2397
	public static function min_pro_version_notice( $min_version ) {
2398
		if ( ! self::is_formidable_admin() ) {
2399
			// Don't show admin-wide.
2400
			return;
2401
		}
2402
2403
		self::php_version_notice();
2404
2405
		$is_pro = self::pro_is_installed() && class_exists( 'FrmProDb' );
2406
		if ( ! $is_pro || self::meets_min_pro_version( $min_version ) ) {
2407
			return;
2408
		}
2409
2410
		$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...
2411
		$expired = FrmAddonsController::is_license_expired();
2412
		?>
2413
		<div class="error frm_previous_install">
2414
			<?php
2415
			esc_html_e( 'You are running a version of Formidable Forms that may not be compatible with your version of Formidable Forms Pro.', 'formidable' );
2416
			if ( empty( $expired ) ) {
2417
				echo ' Please <a href="' . esc_url( admin_url( 'plugins.php?s=formidable%20forms%20pro' ) ) . '">update now</a>.';
2418
			} else {
2419
				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.';
2420
			}
2421
			?>
2422
		</div>
2423
		<?php
2424
	}
2425
2426
	/**
2427
	 * If Pro is installed, check the version number.
2428
	 *
2429
	 * @since 4.0.01
2430
	 */
2431
	public static function meets_min_pro_version( $min_version ) {
2432
		return ! class_exists( 'FrmProDb' ) || version_compare( FrmProDb::$plug_version, $min_version, '>=' );
2433
	}
2434
2435
	/**
2436
	 * Show a message if the browser or PHP version is below the recommendations.
2437
	 *
2438
	 * @since 4.0.02
2439
	 */
2440
	private static function php_version_notice() {
2441
		$message = array();
2442
		if ( version_compare( phpversion(), '5.6', '<' ) ) {
2443
			$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' );
2444
		}
2445
2446
		$browser = self::get_server_value( 'HTTP_USER_AGENT' );
2447
		$is_ie   = strpos( $browser, 'MSIE' ) !== false;
2448
		if ( $is_ie ) {
2449
			$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' );
2450
		}
2451
2452
		foreach ( $message as $m ) {
2453
			?>
2454
			<div class="error frm_previous_install">
2455
				<?php echo esc_html( $m ); ?>
2456
			</div>
2457
			<?php
2458
		}
2459
	}
2460
2461
	public static function locales( $type = 'date' ) {
2462
		$locales = array(
2463
			'en'     => __( 'English', 'formidable' ),
2464
			'af'     => __( 'Afrikaans', 'formidable' ),
2465
			'sq'     => __( 'Albanian', 'formidable' ),
2466
			'ar'     => __( 'Arabic', 'formidable' ),
2467
			'hy'     => __( 'Armenian', 'formidable' ),
2468
			'az'     => __( 'Azerbaijani', 'formidable' ),
2469
			'eu'     => __( 'Basque', 'formidable' ),
2470
			'bs'     => __( 'Bosnian', 'formidable' ),
2471
			'bg'     => __( 'Bulgarian', 'formidable' ),
2472
			'ca'     => __( 'Catalan', 'formidable' ),
2473
			'zh-HK'  => __( 'Chinese Hong Kong', 'formidable' ),
2474
			'zh-CN'  => __( 'Chinese Simplified', 'formidable' ),
2475
			'zh-TW'  => __( 'Chinese Traditional', 'formidable' ),
2476
			'hr'     => __( 'Croatian', 'formidable' ),
2477
			'cs'     => __( 'Czech', 'formidable' ),
2478
			'da'     => __( 'Danish', 'formidable' ),
2479
			'nl'     => __( 'Dutch', 'formidable' ),
2480
			'en-GB'  => __( 'English/UK', 'formidable' ),
2481
			'eo'     => __( 'Esperanto', 'formidable' ),
2482
			'et'     => __( 'Estonian', 'formidable' ),
2483
			'fo'     => __( 'Faroese', 'formidable' ),
2484
			'fa'     => __( 'Farsi/Persian', 'formidable' ),
2485
			'fil'    => __( 'Filipino', 'formidable' ),
2486
			'fi'     => __( 'Finnish', 'formidable' ),
2487
			'fr'     => __( 'French', 'formidable' ),
2488
			'fr-CA'  => __( 'French/Canadian', 'formidable' ),
2489
			'fr-CH'  => __( 'French/Swiss', 'formidable' ),
2490
			'de'     => __( 'German', 'formidable' ),
2491
			'de-AT'  => __( 'German/Austria', 'formidable' ),
2492
			'de-CH'  => __( 'German/Switzerland', 'formidable' ),
2493
			'el'     => __( 'Greek', 'formidable' ),
2494
			'he'     => __( 'Hebrew', 'formidable' ),
2495
			'iw'     => __( 'Hebrew', 'formidable' ),
2496
			'hi'     => __( 'Hindi', 'formidable' ),
2497
			'hu'     => __( 'Hungarian', 'formidable' ),
2498
			'is'     => __( 'Icelandic', 'formidable' ),
2499
			'id'     => __( 'Indonesian', 'formidable' ),
2500
			'it'     => __( 'Italian', 'formidable' ),
2501
			'ja'     => __( 'Japanese', 'formidable' ),
2502
			'ko'     => __( 'Korean', 'formidable' ),
2503
			'lv'     => __( 'Latvian', 'formidable' ),
2504
			'lt'     => __( 'Lithuanian', 'formidable' ),
2505
			'ms'     => __( 'Malaysian', 'formidable' ),
2506
			'no'     => __( 'Norwegian', 'formidable' ),
2507
			'pl'     => __( 'Polish', 'formidable' ),
2508
			'pt'     => __( 'Portuguese', 'formidable' ),
2509
			'pt-BR'  => __( 'Portuguese/Brazilian', 'formidable' ),
2510
			'pt-PT'  => __( 'Portuguese/Portugal', 'formidable' ),
2511
			'ro'     => __( 'Romanian', 'formidable' ),
2512
			'ru'     => __( 'Russian', 'formidable' ),
2513
			'sr'     => __( 'Serbian', 'formidable' ),
2514
			'sr-SR'  => __( 'Serbian', 'formidable' ),
2515
			'sk'     => __( 'Slovak', 'formidable' ),
2516
			'sl'     => __( 'Slovenian', 'formidable' ),
2517
			'es'     => __( 'Spanish', 'formidable' ),
2518
			'es-419' => __( 'Spanish/Latin America', 'formidable' ),
2519
			'sv'     => __( 'Swedish', 'formidable' ),
2520
			'ta'     => __( 'Tamil', 'formidable' ),
2521
			'th'     => __( 'Thai', 'formidable' ),
2522
			'tu'     => __( 'Turkish', 'formidable' ),
2523
			'tr'     => __( 'Turkish', 'formidable' ),
2524
			'uk'     => __( 'Ukranian', 'formidable' ),
2525
			'vi'     => __( 'Vietnamese', 'formidable' ),
2526
		);
2527
2528
		if ( $type === 'captcha' ) {
2529
			// remove the languages unavailable for the captcha
2530
			$unset = array( 'af', 'sq', 'hy', 'az', 'eu', 'bs', 'zh-HK', 'eo', 'et', 'fo', 'fr-CH', 'he', 'is', 'ms', 'sr-SR', 'ta', 'tu' );
2531
		} else {
2532
			// remove the languages unavailable for the datepicker
2533
			$unset = array( 'fil', 'fr-CA', 'de-AT', 'de-CH', 'iw', 'hi', 'pt', 'pt-PT', 'es-419', 'tr' );
2534
		}
2535
2536
		$locales = array_diff_key( $locales, array_flip( $unset ) );
2537
		$locales = apply_filters( 'frm_locales', $locales );
2538
2539
		return $locales;
2540
	}
2541
2542
	/**
2543
	 * Use the WP 4.7 wp_doing_ajax function
2544
	 *
2545
	 * @since 2.05.07
2546
	 * @deprecated 4.04.04
2547
	 */
2548
	public static function wp_doing_ajax() {
2549
		_deprecated_function( __METHOD__, '4.04.04', 'wp_doing_ajax' );
2550
		return wp_doing_ajax();
2551
	}
2552
2553
	/**
2554
	 * @deprecated 4.0
2555
	 */
2556
	public static function insert_opt_html( $args ) {
2557
		_deprecated_function( __METHOD__, '4.0', 'FrmFormsHelper::insert_opt_html' );
2558
		FrmFormsHelper::insert_opt_html( $args );
2559
	}
2560
2561
	/**
2562
	 * Used to filter shortcode in text widgets
2563
	 *
2564
	 * @deprecated 2.5.4
2565
	 * @codeCoverageIgnore
2566
	 */
2567
	public static function widget_text_filter_callback( $matches ) {
2568
		return FrmDeprecated::widget_text_filter_callback( $matches );
2569
	}
2570
2571
	/**
2572
	 * @deprecated 3.01
2573
	 * @codeCoverageIgnore
2574
	 */
2575
	public static function sanitize_array( &$values ) {
2576
		FrmDeprecated::sanitize_array( $values );
2577
	}
2578
2579
	/**
2580
	 * @param array $settings
2581
	 * @param string $group
2582
	 *
2583
	 * @since 2.0.6
2584
	 * @deprecated 2.05.06
2585
	 * @codeCoverageIgnore
2586
	 */
2587
	public static function save_settings( $settings, $group ) {
2588
		return FrmDeprecated::save_settings( $settings, $group );
2589
	}
2590
2591
	/**
2592
	 * @since 2.0.4
2593
	 * @deprecated 2.05.06
2594
	 * @codeCoverageIgnore
2595
	 */
2596
	public static function save_json_post( $settings ) {
2597
		return FrmDeprecated::save_json_post( $settings );
2598
	}
2599
2600
	/**
2601
	 * @since 2.0
2602
	 * @deprecated 2.05.06
2603
	 * @codeCoverageIgnore
2604
	 *
2605
	 * @param string $cache_key The unique name for this cache
2606
	 * @param string $group The name of the cache group
2607
	 * @param string $query If blank, don't run a db call
2608
	 * @param string $type The wpdb function to use with this query
2609
	 *
2610
	 * @return mixed $results The cache or query results
2611
	 */
2612
	public static function check_cache( $cache_key, $group = '', $query = '', $type = 'get_var', $time = 300 ) {
2613
		return FrmDeprecated::check_cache( $cache_key, $group, $query, $type, $time );
2614
	}
2615
2616
	/**
2617
	 * @deprecated 2.05.06
2618
	 * @codeCoverageIgnore
2619
	 */
2620
	public static function set_cache( $cache_key, $results, $group = '', $time = 300 ) {
2621
		return FrmDeprecated::set_cache( $cache_key, $results, $group, $time );
2622
	}
2623
2624
	/**
2625
	 * @deprecated 2.05.06
2626
	 * @codeCoverageIgnore
2627
	 */
2628
	public static function add_key_to_group_cache( $key, $group ) {
2629
		FrmDeprecated::add_key_to_group_cache( $key, $group );
2630
	}
2631
2632
	/**
2633
	 * @deprecated 2.05.06
2634
	 * @codeCoverageIgnore
2635
	 */
2636
	public static function get_group_cached_keys( $group ) {
2637
		return FrmDeprecated::get_group_cached_keys( $group );
2638
	}
2639
2640
	/**
2641
	 * @since 2.0
2642
	 * @deprecated 2.05.06
2643
	 * @codeCoverageIgnore
2644
	 * @return mixed The cached value or false
2645
	 */
2646
	public static function check_cache_and_transient( $cache_key ) {
2647
		return FrmDeprecated::check_cache( $cache_key );
2648
	}
2649
2650
	/**
2651
	 * @since 2.0
2652
	 * @deprecated 2.05.06
2653
	 * @codeCoverageIgnore
2654
	 *
2655
	 * @param string $cache_key
2656
	 */
2657
	public static function delete_cache_and_transient( $cache_key, $group = 'default' ) {
2658
		FrmDeprecated::delete_cache_and_transient( $cache_key, $group );
2659
	}
2660
2661
	/**
2662
	 * @since 2.0
2663
	 * @deprecated 2.05.06
2664
	 * @codeCoverageIgnore
2665
	 *
2666
	 * @param string $group The name of the cache group
2667
	 */
2668
	public static function cache_delete_group( $group ) {
2669
		FrmDeprecated::cache_delete_group( $group );
2670
	}
2671
2672
	/**
2673
	 * @since 1.07.10
2674
	 * @deprecated 2.05.06
2675
	 * @codeCoverageIgnore
2676
	 *
2677
	 * @param string $term The value to escape
2678
	 *
2679
	 * @return string The escaped value
2680
	 */
2681
	public static function esc_like( $term ) {
2682
		return FrmDeprecated::esc_like( $term );
2683
	}
2684
2685
	/**
2686
	 * @param string $order_query
2687
	 *
2688
	 * @deprecated 2.05.06
2689
	 * @codeCoverageIgnore
2690
	 */
2691
	public static function esc_order( $order_query ) {
2692
		return FrmDeprecated::esc_order( $order_query );
2693
	}
2694
2695
	/**
2696
	 * @deprecated 2.05.06
2697
	 * @codeCoverageIgnore
2698
	 */
2699
	public static function esc_order_by( &$order_by ) {
2700
		FrmDeprecated::esc_order_by( $order_by );
2701
	}
2702
2703
	/**
2704
	 * @param string $limit
2705
	 *
2706
	 * @deprecated 2.05.06
2707
	 * @codeCoverageIgnore
2708
	 */
2709
	public static function esc_limit( $limit ) {
2710
		return FrmDeprecated::esc_limit( $limit );
2711
	}
2712
2713
	/**
2714
	 * @since 2.0
2715
	 * @deprecated 2.05.06
2716
	 * @codeCoverageIgnore
2717
	 */
2718
	public static function prepare_array_values( $array, $type = '%s' ) {
2719
		return FrmDeprecated::prepare_array_values( $array, $type );
2720
	}
2721
2722
	/**
2723
	 * @deprecated 2.05.06
2724
	 * @codeCoverageIgnore
2725
	 */
2726
	public static function prepend_and_or_where( $starts_with = ' WHERE ', $where = '' ) {
2727
		return FrmDeprecated::prepend_and_or_where( $starts_with, $where );
2728
	}
2729
}
2730