Completed
Push — master ( bc4572...f59cf9 )
by Stephanie
21s queued 11s
created

FrmAppHelper::time_format()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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