Completed
Push — master ( 22116b...95cc86 )
by Stephanie
15:20 queued 12:54
created

FrmAppHelper::localize_script()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 85

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 10
nop 1
dl 0
loc 85
rs 7.705
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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