Completed
Push — master ( 45ba98...c3b0cd )
by Stephanie
04:13
created

FrmAppHelper::preserve_backslashes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4286
cc 2
eloc 4
nc 2
nop 1
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 = 27; //version of the database we are moving to
8
	public static $pro_db_version = 30;
9
10
	/**
11
	 * @since 2.0
12
	 */
13
	public static $plug_version = '2.0.19';
14
15
    /**
16
     * @since 1.07.02
17
     *
18
     * @param none
19
     * @return string The version of this plugin
20
     */
21
    public static function plugin_version() {
22
        return self::$plug_version;
23
    }
24
25
    public static function plugin_folder() {
26
        return basename(self::plugin_path());
27
    }
28
29
    public static function plugin_path() {
30
        return dirname(dirname(dirname(__FILE__)));
31
    }
32
33
    public static function plugin_url() {
34
        //prevously FRM_URL constant
35
        return plugins_url( '', self::plugin_path() .'/formidable.php' );
36
    }
37
38
	public static function relative_plugin_url() {
39
		return str_replace( array( 'https:', 'http:' ), '', self::plugin_url() );
40
	}
41
42
    /**
43
     * @return string Site URL
44
     */
45
    public static function site_url() {
46
        return site_url();
47
    }
48
49
    /**
50
     * Get the name of this site
51
     * Used for [sitename] shortcode
52
     *
53
     * @since 2.0
54
     * @return string
55
     */
56
    public static function site_name() {
57
        return get_option('blogname');
58
    }
59
60
	public static function make_affiliate_url( $url ) {
61
		$affiliate_id = apply_filters( 'frm_affiliate_link', '' );
62
		$allowed_affiliates = array('Mojo');
0 ignored issues
show
introduced by
No space after opening parenthesis of array is bad style
Loading history...
introduced by
No space before closing parenthesis of array is bad style
Loading history...
63
		if ( in_array( $affiliate_id, $allowed_affiliates ) ) {
64
			$url .= '?aff=' . $affiliate_id;
65
		}
66
		return $url;
67
	}
68
69
    /**
70
     * Get the Formidable settings
71
     *
72
     * @since 2.0
73
     *
74
     * @param None
75
     * @return FrmSettings $frm_setings
76
     */
77
    public static function get_settings() {
78
        global $frm_settings;
79
        if ( empty($frm_settings) ) {
80
            $frm_settings = new FrmSettings();
81
        }
82
        return $frm_settings;
83
    }
84
85
    /**
86
     * Show a message in place of pro features
87
     *
88
     * @since 2.0
89
     */
90
	public static function update_message( $features, $class = '' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $features is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $class is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
91
		_deprecated_function( __FUNCTION__, '2.0.19' );
92
    }
93
94
    public static function pro_is_installed() {
95
        return apply_filters('frm_pro_installed', false);
96
    }
97
98
    /**
99
     * Check for certain page in Formidable settings
100
     *
101
     * @since 2.0
102
     *
103
     * @param string $page The name of the page to check
104
     * @return boolean
105
     */
106
	public static function is_admin_page( $page = 'formidable' ) {
107
        global $pagenow;
108
		$get_page = self::simple_get( 'page', 'sanitize_title' );
109
        if ( $pagenow ) {
110
			return $pagenow == 'admin.php' && $get_page == $page;
111
        }
112
113
		return is_admin() && $get_page == $page;
114
    }
115
116
    /**
117
     * Check for the form preview page
118
     *
119
     * @since 2.0
120
     *
121
     * @param None
122
     * @return boolean
123
     */
124
    public static function is_preview_page() {
125
        global $pagenow;
126
		$action = FrmAppHelper::simple_get( 'action', 'sanitize_title' );
127
		return $pagenow && $pagenow == 'admin-ajax.php' && $action == 'frm_forms_preview';
128
    }
129
130
    /**
131
     * Check for ajax except the form preview page
132
     *
133
     * @since 2.0
134
     *
135
     * @param None
136
     * @return boolean
137
     */
138
    public static function doing_ajax() {
139
        return defined('DOING_AJAX') && DOING_AJAX && ! self::is_preview_page();
140
    }
141
142
	/**
143
	 * @since 2.0.8
144
	 */
145
	public static function prevent_caching() {
146
		global $frm_vars;
147
		return isset( $frm_vars['prevent_caching'] ) && $frm_vars['prevent_caching'];
148
	}
149
150
    /**
151
     * Check if on an admin page
152
     *
153
     * @since 2.0
154
     *
155
     * @param None
156
     * @return boolean
157
     */
158
    public static function is_admin() {
159
        return is_admin() && ( ! defined('DOING_AJAX') || ! DOING_AJAX );
160
    }
161
162
    /**
163
     * Check if value contains blank value or empty array
164
     *
165
     * @since 2.0
166
     * @param $value - value to check
167
     * @return boolean
168
     */
169
    public static function is_empty_value( $value, $empty = '' ) {
170
        return ( is_array( $value ) && empty( $value ) ) || $value == $empty;
171
    }
172
173
    public static function is_not_empty_value( $value, $empty = '' ) {
174
        return ! self::is_empty_value( $value, $empty );
175
    }
176
177
    /**
178
     * Get any value from the $_SERVER
179
     *
180
     * @since 2.0
181
     * @param string $value
182
     * @return string
183
     */
184
	public static function get_server_value( $value ) {
185
        return isset( $_SERVER[ $value ] ) ? wp_strip_all_tags( $_SERVER[ $value ] ) : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
186
    }
187
188
    /**
189
     * Check for the IP address in several places
190
     * Used by [ip] shortcode
191
     *
192
     * @return string The IP address of the current user
193
     */
194
    public static function get_ip_address() {
195
		$ip = '';
196
        foreach ( array(
197
            'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP',
198
            'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR',
199
        ) as $key ) {
200
            if ( ! isset( $_SERVER[ $key ] ) ) {
201
                continue;
202
            }
203
204
            foreach ( explode( ',', $_SERVER[ $key ] ) as $ip ) {
205
                $ip = trim($ip); // just to be safe
206
207
                if ( filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false ) {
208
                    return $ip;
209
                }
210
            }
211
        }
212
213
		return sanitize_text_field( $ip );
214
    }
215
216
    public static function get_param( $param, $default = '', $src = 'get', $sanitize = '' ) {
217
        if ( strpos($param, '[') ) {
218
            $params = explode('[', $param);
219
            $param = $params[0];
220
        }
221
222
		if ( $src == 'get' ) {
223
            $value = isset( $_POST[ $param ] ) ? stripslashes_deep( $_POST[ $param ] ) : ( isset( $_GET[ $param ] ) ? stripslashes_deep( $_GET[ $param ] ) : $default );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
224
            if ( ! isset( $_POST[ $param ] ) && isset( $_GET[ $param ] ) && ! is_array( $value ) ) {
225
                $value = stripslashes_deep( htmlspecialchars_decode( urldecode( $_GET[ $param ] ) ) );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
226
            }
227
			self::sanitize_value( $sanitize, $value );
228
		} else {
229
            $value = self::get_simple_request( array( 'type' => $src, 'param' => $param, 'default' => $default, 'sanitize' => $sanitize ) );
230
        }
231
232
		if ( isset( $params ) && is_array( $value ) && ! empty( $value ) ) {
233
            foreach ( $params as $k => $p ) {
234
                if ( ! $k || ! is_array($value) ) {
235
                    continue;
236
                }
237
238
                $p = trim($p, ']');
239
                $value = isset( $value[ $p ] ) ? $value[ $p ] : $default;
240
            }
241
        }
242
243
        return $value;
244
    }
245
246
	/**
247
	 *
248
	 * @param string $param
249
	 * @param mixed $default
250
	 * @param string $sanitize
251
	 */
252
	public static function get_post_param( $param, $default = '', $sanitize = '' ) {
253
		return self::get_simple_request( array( 'type' => 'post', 'param' => $param, 'default' => $default, 'sanitize' => $sanitize ) );
254
	}
255
256
	/**
257
	 * @since 2.0
258
	 *
259
	 * @param string $param
260
	 * @param string $sanitize
261
	 * @param string $default
262
	 */
263
	public static function simple_get( $param, $sanitize = 'sanitize_text_field', $default = '' ) {
264
		return self::get_simple_request( array( 'type' => 'get', 'param' => $param, 'default' => $default, 'sanitize' => $sanitize ) );
265
    }
266
267
	/**
268
	 * Get a GET/POST/REQUEST value and sanitize it
269
	 *
270
	 * @since 2.0.6
271
	 */
272
	public static function get_simple_request( $args ) {
273
		$defaults = array(
274
			'param' => '', 'default' => '',
275
			'type' => 'get', 'sanitize' => 'sanitize_text_field',
276
		);
277
		$args = wp_parse_args( $args, $defaults );
278
279
		$value = $args['default'];
280
		if ( $args['type'] == 'get' ) {
281
			if ( $_GET && isset( $_GET[ $args['param'] ] ) ) {
282
				$value = $_GET[ $args['param'] ];
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
283
			}
284
		} else if ( $args['type'] == 'post' ) {
285
			if ( isset( $_POST[ $args['param'] ] ) ) {
286
				$value = stripslashes_deep( maybe_unserialize( $_POST[ $args['param'] ] ) );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
287
			}
288
		} else {
289
			if ( isset( $_REQUEST[ $args['param'] ] ) ) {
290
				$value = $_REQUEST[ $args['param'] ];
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
291
			}
292
		}
293
294
		self::sanitize_value( $args['sanitize'], $value );
295
		return $value;
296
	}
297
298
	/**
299
	* Preserve backslashes in a value, but make sure value doesn't get compounding slashes
300
	*
301
	* @since 2.0.8
302
	* @param string $value
303
	* @return string $value
304
	*/
305
	public static function preserve_backslashes( $value ) {
306
		// If backslashes have already been added, don't add them again
307
		if ( strpos( $value, '\\\\' ) === false ) {
308
			$value = addslashes( $value );
309
		}
310
		return $value;
311
	}
312
313
	public static function sanitize_value( $sanitize, &$value ) {
314
		if ( ! empty( $sanitize ) ) {
315
			if ( is_array( $value ) ) {
316
				$value = array_map( $sanitize, $value );
317
			} else {
318
				$value = call_user_func( $sanitize, $value );
319
			}
320
		}
321
	}
322
323
    public static function sanitize_request( $sanitize_method, &$values ) {
324
        $temp_values = $values;
325
        foreach ( $temp_values as $k => $val ) {
326
            if ( isset( $sanitize_method[ $k ] ) ) {
327
				$values[ $k ] = call_user_func( $sanitize_method[ $k ], $val );
328
            }
329
        }
330
    }
331
332
	public static function sanitize_array( &$values ) {
333
		$temp_values = $values;
334
		foreach ( $temp_values as $k => $val ) {
335
			$values[ $k ] = wp_kses_post( $val );
336
		}
337
	}
338
339
	/**
340
	 * Sanitize the value, and allow some HTML
341
	 * @since 2.0
342
	 */
343
	public static function kses( $value, $allowed = array() ) {
344
		$html = array(
345
		    'a' => array(
346
				'href'  => array(),
347
				'title' => array(),
348
				'id'    => array(),
349
				'class' => array(),
350
		    ),
351
		);
352
353
		$allowed_html = array();
354
		foreach ( $allowed as $a ) {
355
			$allowed_html[ $a ] = isset( $html[ $a ] ) ? $html[ $a ] : array();
356
		}
357
358
		return wp_kses( $value, $allowed_html );
359
	}
360
361
    /**
362
     * Used when switching the action for a bulk action
363
     * @since 2.0
364
     */
365
    public static function remove_get_action() {
366
        if ( ! isset($_GET) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
367
            return;
368
        }
369
370
        $new_action = isset( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : ( isset( $_GET['action2'] ) ? sanitize_text_field( $_GET['action2'] ) : '' );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
371
        if ( ! empty( $new_action ) ) {
372
			$_SERVER['REQUEST_URI'] = str_replace( '&action=' . $new_action, '', FrmAppHelper::get_server_value( 'REQUEST_URI' ) );
373
        }
374
    }
375
376
    /**
377
     * Check the WP query for a parameter
378
     *
379
     * @since 2.0
380
     * @return string|array
381
     */
382
    public static function get_query_var( $value, $param ) {
383
        if ( $value != '' ) {
384
            return $value;
385
        }
386
387
        global $wp_query;
388
        if ( isset( $wp_query->query_vars[ $param ] ) ) {
389
            $value = $wp_query->query_vars[ $param ];
390
        }
391
392
        return $value;
393
    }
394
395
    /**
396
     * @param string $type
397
     */
398
    public static function trigger_hook_load( $type, $object = null ) {
399
        // only load the form hooks once
400
        $hooks_loaded = apply_filters('frm_'. $type .'_hooks_loaded', false, $object);
401
        if ( ! $hooks_loaded ) {
402
            do_action('frm_load_'. $type .'_hooks');
403
        }
404
    }
405
406
    /**
407
     * Check cache before fetching values and saving to cache
408
     *
409
     * @since 2.0
410
     *
411
     * @param string $cache_key The unique name for this cache
412
     * @param string $group The name of the cache group
413
     * @param string $query If blank, don't run a db call
414
     * @param string $type The wpdb function to use with this query
415
     * @return mixed $results The cache or query results
416
     */
417
    public static function check_cache( $cache_key, $group = '', $query = '', $type = 'get_var', $time = 300 ) {
418
        $results = wp_cache_get($cache_key, $group);
419
        if ( ! self::is_empty_value( $results, false ) || empty($query) ) {
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
420
            return $results;
421
        }
422
423
        if ( 'get_posts' == $type ) {
424
            $results = get_posts($query);
425
        } else {
426
            global $wpdb;
427
            $results = $wpdb->{$type}($query);
428
        }
429
430
		if ( ! self::prevent_caching() ) {
431
			wp_cache_set( $cache_key, $results, $group, $time );
432
		}
433
434
        return $results;
435
    }
436
437
    /**
438
     * Data that should be stored for a long time can be stored in a transient.
439
     * First check the cache, then check the transient
440
     * @since 2.0
441
     * @return mixed The cached value or false
442
     */
443
	public static function check_cache_and_transient( $cache_key ) {
444
        // check caching layer first
445
        $results = self::check_cache( $cache_key );
446
        if ( $results ) {
447
            return $results;
448
        }
449
450
        // then check the transient
451
        $results = get_transient($cache_key);
452
        if ( $results ) {
453
            wp_cache_set($cache_key, $results);
454
        }
455
456
        return $results;
457
    }
458
459
    /**
460
     * @since 2.0
461
     * @param string $cache_key
462
     */
463
	public static function delete_cache_and_transient( $cache_key ) {
464
        delete_transient($cache_key);
465
        wp_cache_delete($cache_key);
466
    }
467
468
    /**
469
     * Delete all caching in a single group
470
     *
471
     * @since 2.0
472
     *
473
     * @param string $group The name of the cache group
474
     * @return boolean True or False
475
     */
476
	public static function cache_delete_group( $group ) {
477
    	global $wp_object_cache;
478
479
        if ( isset( $wp_object_cache->cache[ $group ] ) ) {
480
            foreach ( $wp_object_cache->cache[ $group ] as $k => $v ) {
481
                wp_cache_delete($k, $group);
482
            }
483
            return true;
484
        }
485
486
    	return false;
487
    }
488
489
    /**
490
     * Check a value from a shortcode to see if true or false.
491
     * True when value is 1, true, 'true', 'yes'
492
     *
493
     * @since 1.07.10
494
     *
495
     * @param string $value The value to compare
496
     * @return boolean True or False
497
     */
498
	public static function is_true( $value ) {
499
        return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
500
    }
501
502
    /**
503
     * Used to filter shortcode in text widgets
504
     */
505
    public static function widget_text_filter_callback( $matches ) {
506
        return do_shortcode( $matches[0] );
507
    }
508
509
	public static function load_scripts( $scripts ) {
510
        _deprecated_function( __FUNCTION__, '2.0', 'wp_enqueue_script' );
511
        foreach ( (array) $scripts as $s ) {
512
            wp_enqueue_script($s);
513
        }
514
    }
515
516
	public static function load_styles( $styles ) {
517
        _deprecated_function( __FUNCTION__, '2.0', 'wp_enqueue_style' );
518
        foreach ( (array) $styles as $s ) {
519
            wp_enqueue_style($s);
520
        }
521
    }
522
523
    public static function get_pages() {
524
		return get_posts( array( 'post_type' => 'page', 'post_status' => array( 'publish', 'private' ), 'numberposts' => -1, 'orderby' => 'title', 'order' => 'ASC' ) );
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set numberposts to -1 ever.
Loading history...
525
    }
526
527
    public static function wp_pages_dropdown( $field_name, $page_id, $truncate = false ) {
528
        $pages = self::get_pages();
529
		$selected = self::get_post_param( $field_name, $page_id, 'absint' );
530
    ?>
531
        <select name="<?php echo esc_attr($field_name); ?>" id="<?php echo esc_attr($field_name); ?>" class="frm-pages-dropdown">
532
            <option value=""> </option>
533
            <?php foreach ( $pages as $page ) { ?>
534
				<option value="<?php echo esc_attr($page->ID); ?>" <?php selected( $selected, $page->ID ) ?>>
535
					<?php echo esc_html( $truncate ? self::truncate( $page->post_title, $truncate ) : $page->post_title ); ?>
536
				</option>
537
            <?php } ?>
538
        </select>
539
    <?php
540
    }
541
542
	public static function post_edit_link( $post_id ) {
543
        $post = get_post($post_id);
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
544
        if ( $post ) {
545
            return '<a href="'. esc_url(admin_url('post.php') .'?post='. $post_id .'&action=edit') .'">'. self::truncate($post->post_title, 50) .'</a>';
546
        }
547
        return '';
548
    }
549
550
	public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
551
    ?>
552
        <select name="<?php echo esc_attr($field_name); ?>" id="<?php echo esc_attr($field_name); ?>" <?php
553
            echo ( 'multiple' == $multiple ) ? 'multiple="multiple"' : '';
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
554
            ?> class="frm_multiselect">
555
            <?php self::roles_options($capability); ?>
556
        </select>
557
    <?php
558
    }
559
560
	public static function roles_options( $capability ) {
561
        global $frm_vars;
562
        if ( isset($frm_vars['editable_roles']) ) {
563
            $editable_roles = $frm_vars['editable_roles'];
564
        } else {
565
            $editable_roles = get_editable_roles();
566
            $frm_vars['editable_roles'] = $editable_roles;
567
        }
568
569
        foreach ( $editable_roles as $role => $details ) {
570
            $name = translate_user_role($details['name'] ); ?>
571
        <option value="<?php echo esc_attr($role) ?>" <?php echo in_array($role, (array) $capability) ? ' selected="selected"' : ''; ?>><?php echo esc_attr($name) ?> </option>
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'in_array'
Loading history...
572
<?php
573
            unset($role, $details);
574
        }
575
    }
576
577
	public static function frm_capabilities( $type = 'auto' ) {
578
        $cap = array(
579
            'frm_view_forms'        => __( 'View Forms and Templates', 'formidable' ),
580
            'frm_edit_forms'        => __( 'Add/Edit Forms and Templates', 'formidable' ),
581
            'frm_delete_forms'      => __( 'Delete Forms and Templates', 'formidable' ),
582
            'frm_change_settings'   => __( 'Access this Settings Page', 'formidable' ),
583
            'frm_view_entries'      => __( 'View Entries from Admin Area', 'formidable' ),
584
            'frm_delete_entries'    => __( 'Delete Entries from Admin Area', 'formidable' ),
585
        );
586
587
		if ( ! self::pro_is_installed() && 'pro' != $type ) {
588
            return $cap;
589
        }
590
591
        $cap['frm_create_entries'] = __( 'Add Entries from Admin Area', 'formidable' );
592
        $cap['frm_edit_entries'] = __( 'Edit Entries from Admin Area', 'formidable' );
593
        $cap['frm_view_reports'] = __( 'View Reports', 'formidable' );
594
        $cap['frm_edit_displays'] = __( 'Add/Edit Views', 'formidable' );
595
596
        return $cap;
597
    }
598
599
	public static function user_has_permission( $needed_role ) {
600
        if ( $needed_role == '-1' ) {
601
            return false;
602
		}
603
604
        // $needed_role will be equal to blank if "Logged-in users" is selected
605
        if ( ( $needed_role == '' && is_user_logged_in() ) || current_user_can( $needed_role ) ) {
606
            return true;
607
        }
608
609
        $roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
610
        foreach ( $roles as $role ) {
611
			if ( current_user_can( $role ) ) {
612
        		return true;
613
			}
614
        	if ( $role == $needed_role ) {
615
        		break;
616
			}
617
        }
618
        return false;
619
    }
620
621
    /**
622
     * Make sure administrators can see Formidable menu
623
     *
624
     * @since 2.0
625
     */
626
    public static function maybe_add_permissions() {
627
		self::force_capability( 'frm_view_entries' );
628
629
        if ( ! current_user_can('administrator') || current_user_can('frm_view_forms') ) {
630
            return;
631
        }
632
633
		$user_id = get_current_user_id();
634
		$user = new WP_User( $user_id );
635
        $frm_roles = self::frm_capabilities();
636
        foreach ( $frm_roles as $frm_role => $frm_role_description ) {
637
			$user->add_cap( $frm_role );
638
            unset($frm_role, $frm_role_description);
639
        }
640
    }
641
642
	/**
643
	 * Make sure admins have permission to see the menu items
644
	 * @since 2.0.6
645
	 */
646
	public static function force_capability( $cap = 'frm_change_settings' ) {
647
		if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
648
			$role = get_role( 'administrator' );
649
			$frm_roles = self::frm_capabilities();
650
			foreach ( $frm_roles as $frm_role => $frm_role_description ) {
651
				$role->add_cap( $frm_role );
652
			}
653
		}
654
	}
655
656
    /**
657
     * Check if the user has permision for action.
658
     * Return permission message and stop the action if no permission
659
     * @since 2.0
660
     * @param string $permission
661
     */
662
	public static function permission_check( $permission, $show_message = 'show' ) {
663
        $permission_error = self::permission_nonce_error($permission);
664
        if ( $permission_error !== false ) {
665
            if ( 'hide' == $show_message ) {
666
                $permission_error = '';
667
            }
668
            wp_die($permission_error);
669
        }
670
    }
671
672
    /**
673
     * Check user permission and nonce
674
     * @since 2.0
675
     * @param string $permission
676
     * @return false|string The permission message or false if allowed
677
     */
678
	public static function permission_nonce_error( $permission, $nonce_name = '', $nonce = '' ) {
679
		if ( ! empty( $permission ) && ! current_user_can( $permission ) && ! current_user_can( 'administrator' ) ) {
680
			$frm_settings = self::get_settings();
681
			return $frm_settings->admin_permission;
682
		}
683
684
		$error = false;
685
        if ( empty($nonce_name) ) {
686
            return $error;
687
        }
688
689
        if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $_REQUEST[ $nonce_name ], $nonce ) ) ) {
690
            $frm_settings = self::get_settings();
691
            $error = $frm_settings->admin_permission;
692
        }
693
694
        return $error;
695
    }
696
697
    public static function checked( $values, $current ) {
698
		if ( self::check_selected( $values, $current ) ) {
699
            echo ' checked="checked"';
700
		}
701
    }
702
703
	public static function check_selected( $values, $current ) {
704
        $values = self::recursive_function_map( $values, 'trim' );
705
        $current = trim($current);
706
707
        return ( is_array($values) && in_array($current, $values) ) || ( ! is_array($values) && $values == $current );
708
    }
709
710
    /**
711
    * Check if current field option is an "other" option
712
    *
713
    * @since 2.0
714
    *
715
    * @param string $opt_key
716
    * @return boolean Returns true if current field option is an "Other" option
717
    */
718
    public static function is_other_opt( $opt_key ) {
719
        _deprecated_function( __FUNCTION__, '2.0.6', 'FrmFieldsHelper::is_other_opt' );
720
        return FrmFieldsHelper::is_other_opt( $opt_key );
721
    }
722
723
    /**
724
    * Get value that belongs in "Other" text box
725
    *
726
    * @since 2.0
727
    *
728
    * @param string $opt_key
729
    * @param array $field
730
    * @return string $other_val
731
    */
732
    public static function get_other_val( $opt_key, $field, $parent = false, $pointer = false ) {
733
		_deprecated_function( __FUNCTION__, '2.0.6', 'FrmFieldsHelper::get_other_val' );
734
		return FrmFieldsHelper::get_other_val( compact( 'opt_key', 'field', 'parent', 'pointer' ) );
735
    }
736
737
    /**
738
    * Check if there is a saved value for the "Other" text field. If so, set it as the $other_val.
739
    * Intended for front-end use
740
    *
741
    * @since 2.0
742
    *
743
    * @param array $field
744
    * @param boolean $other_opt
745
    * @param string $checked
746
    * @param array $args should include opt_key and field name
747
    * @return string $other_val
748
    */
749
    public static function prepare_other_input( $field, &$other_opt, &$checked, $args = array() ) {
750
		_deprecated_function( __FUNCTION__, '2.0.6', 'FrmFieldsHelper::prepare_other_input' );
751
		$args['field'] = $field;
752
		return FrmFieldsHelper::prepare_other_input( $args, $other_opt, $checked );
753
    }
754
755
	public static function recursive_function_map( $value, $function ) {
756
		if ( is_array( $value ) ) {
757
			$original_function = $function;
758
			if ( count( $value ) ) {
759
				$function = explode( ', ', self::prepare_array_values( $value, $function ) );
760
			} else {
761
				$function = array( $function );
762
			}
763
			if ( ! self::is_assoc( $value ) ) {
764
				$value = array_map( array( 'FrmAppHelper', 'recursive_function_map' ), $value, $function );
765
			} else {
766
				foreach ( $value as $k => $v ) {
767
					if ( ! is_array( $v ) ) {
768
						$value[ $k ] = call_user_func( $original_function, $v );
769
					}
770
				}
771
			}
772
		} else {
773
			$value = call_user_func( $function, $value );
774
		}
775
776
		return $value;
777
	}
778
779
	public static function is_assoc( $array ) {
780
		return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
781
	}
782
783
    /**
784
     * Flatten a multi-dimensional array
785
     */
786
	public static function array_flatten( $array, $keys = 'keep' ) {
787
        $return = array();
788
        foreach ( $array as $key => $value ) {
789
            if ( is_array($value) ) {
790
				$return = array_merge( $return, self::array_flatten( $value, $keys ) );
791
            } else {
792
				if ( $keys == 'keep' ) {
793
					$return[ $key ] = $value;
794
				} else {
795
					$return[] = $value;
796
				}
797
            }
798
        }
799
        return $return;
800
    }
801
802
    public static function esc_textarea( $text ) {
803
        $safe_text = str_replace('&quot;', '"', $text);
804
        $safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
805
    	return apply_filters( 'esc_textarea', $safe_text, $text );
806
    }
807
808
    /**
809
     * Add auto paragraphs to text areas
810
     * @since 2.0
811
     */
812
	public static function use_wpautop( $content ) {
813
        if ( apply_filters('frm_use_wpautop', true) ) {
814
            $content = wpautop(str_replace( '<br>', '<br />', $content));
815
        }
816
        return $content;
817
    }
818
819
	public static function replace_quotes( $val ) {
820
        //Replace double quotes
821
		$val = str_replace( array( '&#8220;', '&#8221;', '&#8243;' ), '"', $val );
822
        //Replace single quotes
823
        $val = str_replace( array( '&#8216;', '&#8217;', '&#8242;', '&prime;', '&rsquo;', '&lsquo;' ), "'", $val );
824
        return $val;
825
    }
826
827
    /**
828
     * @since 2.0
829
     * @return string The base Google APIS url for the current version of jQuery UI
830
     */
831
    public static function jquery_ui_base_url() {
832
        $url = 'http'. ( is_ssl() ? 's' : '' ) .'://ajax.googleapis.com/ajax/libs/jqueryui/'. self::script_version('jquery-ui-core');
833
        $url = apply_filters('frm_jquery_ui_base_url', $url);
834
        return $url;
835
    }
836
837
    /**
838
     * @param string $handle
839
     */
840
	public static function script_version( $handle ) {
841
        global $wp_scripts;
842
    	if ( ! $wp_scripts ) {
843
    	    return false;
844
    	}
845
846
        $ver = 0;
847
848
        if ( ! isset( $wp_scripts->registered[ $handle ] ) ) {
849
            return $ver;
850
        }
851
852
        $query = $wp_scripts->registered[ $handle ];
853
    	if ( is_object( $query ) ) {
854
    	    $ver = $query->ver;
855
    	}
856
857
    	return $ver;
858
    }
859
860
	public static function js_redirect( $url ) {
861
		return '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
862
    }
863
864
	public static function get_user_id_param( $user_id ) {
865
        if ( ! $user_id || empty($user_id) || is_numeric($user_id) ) {
866
            return $user_id;
867
        }
868
869
		if ( $user_id == 'current' ) {
870
            $user_ID = get_current_user_id();
871
            $user_id = $user_ID;
872
		} else {
873
            if ( is_email($user_id) ) {
874
                $user = get_user_by('email', $user_id);
875
            } else {
876
                $user = get_user_by('login', $user_id);
877
            }
878
879
            if ( $user ) {
880
                $user_id = $user->ID;
881
            }
882
            unset($user);
883
        }
884
885
        return $user_id;
886
    }
887
888
	public static function get_file_contents( $filename, $atts = array() ) {
889
        if ( ! is_file($filename) ) {
890
            return false;
891
        }
892
893
        extract($atts);
0 ignored issues
show
introduced by
extract() usage is highly discouraged, due to the complexity and unintended issues it might cause.
Loading history...
894
        ob_start();
895
        include($filename);
896
        $contents = ob_get_contents();
897
        ob_end_clean();
898
        return $contents;
899
    }
900
901
    /**
902
     * @param string $table_name
903
     * @param string $column
904
     */
905
    public static function get_unique_key( $name = '', $table_name, $column, $id = 0, $num_chars = 6 ) {
906
        global $wpdb;
907
908
        $key = '';
909
910
        if ( ! empty( $name ) ) {
911
            $key = sanitize_key($name);
912
        }
913
914
		if ( empty( $key ) ) {
915
            $max_slug_value = pow(36, $num_chars);
916
            $min_slug_value = 37; // we want to have at least 2 characters in the slug
917
            $key = base_convert( rand($min_slug_value, $max_slug_value), 10, 36 );
918
        }
919
920
		if ( is_numeric($key) || in_array( $key, array( 'id', 'key', 'created-at', 'detaillink', 'editlink', 'siteurl', 'evenodd' ) ) ) {
921
            $key = $key .'a';
922
        }
923
924
		$key_check = FrmDb::get_var( $table_name, array( $column => $key, 'ID !' => $id ), $column );
925
926
        if ( $key_check || is_numeric($key_check) ) {
927
            $suffix = 2;
928
			do {
929
				$alt_post_name = substr( $key, 0, 200 - ( strlen( $suffix ) + 1 ) ) . $suffix;
930
				$key_check = FrmDb::get_var( $table_name, array( $column => $alt_post_name, 'ID !' => $id ), $column );
931
				$suffix++;
932
			} while ($key_check || is_numeric($key_check));
933
			$key = $alt_post_name;
934
        }
935
        return $key;
936
    }
937
938
    /**
939
     * Editing a Form or Entry
940
     * @param string $table
941
     * @return bool|array
942
     */
943
    public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
944
        if ( ! $record ) {
945
            return false;
946
        }
947
948
        global $frm_vars;
949
950
        if ( empty($post_values) ) {
951
            $post_values = stripslashes_deep($_POST);
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
952
        }
953
954
		$values = array( 'id' => $record->id, 'fields' => array() );
955
956
		foreach ( array( 'name', 'description' ) as $var ) {
957
            $default_val = isset($record->{$var}) ? $record->{$var} : '';
958
            $values[ $var ] = self::get_param( $var, $default_val );
959
            unset($var, $default_val);
960
        }
961
962
        $values['description'] = self::use_wpautop($values['description']);
963
        $frm_settings = self::get_settings();
964
        $is_form_builder = self::is_admin_page('formidable' );
965
966
        foreach ( (array) $fields as $field ) {
967
            // Make sure to filter default values (for placeholder text), but not on the form builder page
968
            if ( ! $is_form_builder ) {
969
                $field->default_value = apply_filters('frm_get_default_value', $field->default_value, $field, true );
970
            }
971
			$parent_form_id = isset( $args['parent_form_id'] ) ? $args['parent_form_id'] : $field->form_id;
972
			self::fill_field_defaults($field, $record, $values, compact('default', 'post_values', 'frm_settings', 'parent_form_id' ) );
973
        }
974
975
        self::fill_form_opts($record, $table, $post_values, $values);
976
977
        if ( $table == 'entries' ) {
978
            $values = FrmEntriesHelper::setup_edit_vars( $values, $record );
979
        } else if ( $table == 'forms' ) {
980
            $values = FrmFormsHelper::setup_edit_vars( $values, $record, $post_values );
981
        }
982
983
        return $values;
984
    }
985
986
	private static function fill_field_defaults( $field, $record, array &$values, $args ) {
987
        $post_values = $args['post_values'];
988
989
        if ( $args['default'] ) {
990
            $meta_value = $field->default_value;
991
        } else {
992
            if ( $record->post_id && self::pro_is_installed() && isset($field->field_options['post_field']) && $field->field_options['post_field'] ) {
993
                if ( ! isset($field->field_options['custom_field']) ) {
994
                    $field->field_options['custom_field'] = '';
995
                }
996
				$meta_value = FrmProEntryMetaHelper::get_post_value( $record->post_id, $field->field_options['post_field'], $field->field_options['custom_field'], array( 'truncate' => false, 'type' => $field->type, 'form_id' => $field->form_id, 'field' => $field ) );
997
            } else {
998
				$meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
999
            }
1000
        }
1001
1002
        $field_type = isset( $post_values['field_options'][ 'type_'. $field->id ] ) ? $post_values['field_options'][ 'type_'. $field->id ] : $field->type;
1003
        $new_value = isset( $post_values['item_meta'][ $field->id ] ) ? maybe_unserialize( $post_values['item_meta'][ $field->id ] ) : $meta_value;
1004
1005
        $field_array = array(
1006
            'id'            => $field->id,
1007
            'value'         => $new_value,
1008
            'default_value' => $field->default_value,
1009
            'name'          => $field->name,
1010
            'description'   => $field->description,
1011
            'type'          => apply_filters('frm_field_type', $field_type, $field, $new_value),
1012
            'options'       => $field->options,
1013
            'required'      => $field->required,
1014
            'field_key'     => $field->field_key,
1015
            'field_order'   => $field->field_order,
1016
            'form_id'       => $field->form_id,
1017
			'parent_form_id' => $args['parent_form_id'],
1018
        );
1019
1020
        $args['field_type'] = $field_type;
1021
        self::fill_field_opts($field, $field_array, $args);
1022
1023
        $field_array = apply_filters('frm_setup_edit_fields_vars', $field_array, $field, $values['id']);
1024
1025
        if ( ! isset($field_array['unique']) || ! $field_array['unique'] ) {
1026
            $field_array['unique_msg'] = '';
1027
        }
1028
1029
        $field_array = array_merge( $field->field_options, $field_array );
1030
1031
        $values['fields'][ $field->id ] = $field_array;
1032
    }
1033
1034
	private static function fill_field_opts( $field, array &$field_array, $args ) {
1035
        $post_values = $args['post_values'];
1036
        $opt_defaults = FrmFieldsHelper::get_default_field_opts($field_array['type'], $field, true);
1037
1038
        foreach ( $opt_defaults as $opt => $default_opt ) {
1039
            $field_array[ $opt ] = ( $post_values && isset( $post_values['field_options'][ $opt .'_'. $field->id ] ) ) ? maybe_unserialize( $post_values['field_options'][ $opt .'_'. $field->id ] ) : ( isset( $field->field_options[ $opt ] ) ? $field->field_options[ $opt ] : $default_opt );
1040
            if ( $opt == 'blank' && $field_array[ $opt ] == '' ) {
1041
                $field_array[ $opt ] = $args['frm_settings']->blank_msg;
1042
            } else if ( $opt == 'invalid' && $field_array[ $opt ] == '' ) {
1043
                if ( $args['field_type'] == 'captcha' ) {
1044
                    $field_array[ $opt ] = $args['frm_settings']->re_msg;
1045
                } else {
1046
                    $field_array[ $opt ] = sprintf( __( '%s is invalid', 'formidable' ), $field_array['name'] );
1047
                }
1048
            }
1049
        }
1050
1051
        if ( $field_array['custom_html'] == '' ) {
1052
            $field_array['custom_html'] = FrmFieldsHelper::get_default_html($args['field_type']);
1053
        }
1054
    }
1055
1056
    /**
1057
     * @param string $table
1058
     */
1059
	private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
1060
        if ( $table == 'entries' ) {
1061
            $form = $record->form_id;
1062
			FrmForm::maybe_get_form( $form );
1063
        } else {
1064
            $form = $record;
1065
        }
1066
1067
        if ( ! $form ) {
1068
            return;
1069
        }
1070
1071
        $values['form_name'] = isset($record->form_id) ? $form->name : '';
1072
		$values['parent_form_id'] = isset( $record->form_id ) ? $form->parent_form_id : 0;
1073
1074
        if ( ! is_array($form->options) ) {
1075
            return;
1076
        }
1077
1078
        foreach ( $form->options as $opt => $value ) {
1079
            $values[ $opt ] = isset( $post_values[ $opt ] ) ? maybe_unserialize( $post_values[ $opt ] ) : $value;
1080
        }
1081
1082
        self::fill_form_defaults($post_values, $values);
1083
    }
1084
1085
    /**
1086
     * Set to POST value or default
1087
     */
1088
	private static function fill_form_defaults( $post_values, array &$values ) {
1089
        $form_defaults = FrmFormsHelper::get_default_opts();
1090
1091
        foreach ( $form_defaults as $opt => $default ) {
1092
            if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
1093
				$values[ $opt ] = ( $post_values && isset( $post_values['options'][ $opt ] ) ) ? $post_values['options'][ $opt ] : $default;
1094
            }
1095
1096
            unset($opt, $defaut);
1097
        }
1098
1099 View Code Duplication
        if ( ! isset($values['custom_style']) ) {
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...
1100
            $frm_settings = self::get_settings();
1101
			$values['custom_style'] = ( $post_values && isset( $post_values['options']['custom_style'] ) ) ? absint( $_POST['options']['custom_style'] ) : ( $frm_settings->load_style != 'none' );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
1102
        }
1103
1104
		foreach ( array( 'before', 'after', 'submit' ) as $h ) {
1105
            if ( ! isset( $values[ $h .'_html' ] ) ) {
1106
                $values[ $h .'_html' ] = ( isset( $post_values['options'][ $h .'_html' ] ) ? $post_values['options'][ $h .'_html' ] : FrmFormsHelper::get_default_html( $h ) );
1107
            }
1108
            unset($h);
1109
        }
1110
    }
1111
1112
	public static function get_meta_value( $field_id, $entry ) {
1113
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryMeta::get_meta_value' );
1114
		return FrmEntryMeta::get_meta_value( $entry, $field_id );
1115
	}
1116
1117
	public static function insert_opt_html( $args ) {
1118
        $class = '';
1119
        if ( in_array( $args['type'], array( 'email', 'user_id', 'hidden', 'select', 'radio', 'checkbox', 'phone', 'text' ) ) ) {
1120
            $class .= 'show_frm_not_email_to';
1121
        }
1122
    ?>
1123
<li>
1124
    <a href="javascript:void(0)" class="frmids frm_insert_code alignright <?php echo esc_attr($class) ?>" data-code="<?php echo esc_attr($args['id']) ?>" >[<?php echo esc_attr( $args['id'] ) ?>]</a>
1125
    <a href="javascript:void(0)" class="frmkeys frm_insert_code alignright <?php echo esc_attr($class) ?>" data-code="<?php echo esc_attr($args['key']) ?>" >[<?php echo esc_attr( self::truncate($args['key'], 10) ) ?>]</a>
1126
    <a href="javascript:void(0)" class="frm_insert_code <?php echo esc_attr( $class ) ?>" data-code="<?php echo esc_attr($args['id']) ?>" ><?php echo esc_attr( self::truncate($args['name'], 60) ) ?></a>
1127
</li>
1128
    <?php
1129
    }
1130
1131
    public static function get_us_states() {
1132
        _deprecated_function( __FUNCTION__, '2.0', 'FrmFieldsHelper::get_us_states' );
1133
        return FrmFieldsHelper::get_us_states();
1134
    }
1135
1136
    public static function get_countries() {
1137
        _deprecated_function( __FUNCTION__, '2.0', 'FrmFieldsHelper::get_countries' );
1138
        return FrmFieldsHelper::get_countries();
1139
    }
1140
1141
	public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
1142
        if ( is_array( $str ) ) {
1143
            return;
1144
		}
1145
1146
        $length = (int) $length;
1147
		$str = wp_strip_all_tags( $str );
1148
		$original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
1149
1150
		if ( $length == 0 ) {
1151
            return '';
1152
        } else if ( $length <= 10 ) {
1153
			$sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
1154
            return $sub . (($length < $original_len) ? $continue : '');
1155
        }
1156
1157
        $sub = '';
1158
        $len = 0;
1159
1160
		$words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
1161
1162
		foreach ( $words as $word ) {
1163
            $part = (($sub != '') ? ' ' : '') . $word;
1164
			$total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
1165
            if ( $total_len > $length && str_word_count($sub) ) {
1166
                break;
1167
            }
1168
1169
            $sub .= $part;
1170
			$len += self::mb_function( array( 'mb_strlen', 'strlen' ), array( $part ) );
1171
1172
            if ( str_word_count($sub) > $minword && $total_len >= $length ) {
1173
                break;
1174
            }
1175
1176
            unset($total_len, $word);
1177
        }
1178
1179
        return $sub . (($len < $original_len) ? $continue : '');
1180
    }
1181
1182
	public static function mb_function( $function_names, $args ) {
1183
		$mb_function_name = $function_names[0];
1184
		$function_name = $function_names[1];
1185
		if ( function_exists( $mb_function_name ) ) {
1186
			$function_name = $mb_function_name;
1187
		}
1188
		return call_user_func_array( $function_name, $args );
1189
	}
1190
1191
	public static function get_formatted_time( $date, $date_format = '', $time_format = '' ) {
1192
        if ( empty($date) ) {
1193
            return $date;
1194
        }
1195
1196
        if ( empty($date_format) ) {
1197
            $date_format = get_option('date_format');
1198
        }
1199
1200
        if ( preg_match('/^\d{1-2}\/\d{1-2}\/\d{4}$/', $date) && self::pro_is_installed() ) {
1201
            $frmpro_settings = new FrmProSettings();
1202
            $date = FrmProAppHelper::convert_date($date, $frmpro_settings->date_format, 'Y-m-d');
1203
        }
1204
1205
		$formatted = self::get_localized_date( $date_format, $date );
1206
1207
		$do_time = ( date( 'H:i:s', strtotime( $date ) ) != '00:00:00' );
1208
		if ( $do_time ) {
1209
			$formatted .= self::add_time_to_date( $time_format, $date );
1210
		}
1211
1212
        return $formatted;
1213
    }
1214
1215
	private static function add_time_to_date( $time_format, $date ) {
1216
		if ( empty( $time_format ) ) {
1217
			$time_format = get_option('time_format');
1218
		}
1219
1220
		$trimmed_format = trim( $time_format );
1221
		$time = '';
1222
		if ( $time_format && ! empty( $trimmed_format ) ) {
1223
			$time = ' ' . __( 'at', 'formidable' ) . ' ' . self::get_localized_date( $time_format, $date );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not 'self'
Loading history...
1224
		}
1225
1226
		return $time;
1227
	}
1228
1229
	/**
1230
	 * @since 2.0.8
1231
	 */
1232
	public static function get_localized_date( $date_format, $date ) {
1233
		$date = get_date_from_gmt( $date );
1234
		return date_i18n( $date_format, strtotime( $date ) );
1235
	}
1236
1237
    /**
1238
     * @return string The time ago in words
1239
     */
1240
    public static function human_time_diff( $from, $to = '' ) {
1241
    	if ( empty($to) ) {
1242
    	    		$to = time();
1243
    	}
1244
1245
    	// Array of time period chunks
1246
    	$chunks = array(
1247
    		array( 60 * 60 * 24 * 365, __( 'year', 'formidable' ), __( 'years', 'formidable' ) ),
1248
    		array( 60 * 60 * 24 * 30, __( 'month', 'formidable' ), __( 'months', 'formidable' ) ),
1249
    		array( 60 * 60 * 24 * 7, __( 'week', 'formidable' ), __( 'weeks', 'formidable' ) ),
1250
    		array( 60 * 60 * 24, __( 'day', 'formidable' ), __( 'days', 'formidable' ) ),
1251
    		array( 60 * 60, __( 'hour', 'formidable' ), __( 'hours', 'formidable' ) ),
1252
    		array( 60, __( 'minute', 'formidable' ), __( 'minutes', 'formidable' ) ),
1253
    		array( 1, __( 'second', 'formidable' ), __( 'seconds', 'formidable' ) ),
1254
    	);
1255
1256
    	// Difference in seconds
1257
    	$diff = (int) ($to - $from);
1258
1259
    	// Something went wrong with date calculation and we ended up with a negative date.
1260
		if ( $diff < 1 ) {
1261
			return '0 ' . __( 'seconds', 'formidable' );
1262
    	}
1263
1264
    	/**
1265
    	 * We only want to output one chunks of time here, eg:
1266
    	 * x years
1267
    	 * xx months
1268
    	 * so there's only one bit of calculation below:
1269
    	 */
1270
1271
        $count = 0;
1272
1273
    	//Step one: the first chunk
1274
		for ( $i = 0, $j = count( $chunks ); $i < $j; $i++ ) {
1275
    		$seconds = $chunks[ $i ][0];
1276
1277
    		// Finding the biggest chunk (if the chunk fits, break)
1278
    		if ( ( $count = floor($diff / $seconds) ) != 0 ) {
1279
    		    			break;
1280
    		}
1281
    	}
1282
1283
    	// Set output var
1284
    	$output = ( 1 == $count ) ? '1 '. $chunks[ $i ][1] : $count . ' ' . $chunks[ $i ][2];
1285
1286
    	if ( ! (int) trim( $output ) ) {
1287
    		$output = '0 ' . __( 'seconds', 'formidable' );
1288
        }
1289
1290
    	return $output;
1291
    }
1292
1293
    /**
1294
     * Added for < WP 4.0 compatability
1295
     *
1296
     * @since 1.07.10
1297
     *
1298
     * @param string $term The value to escape
1299
     * @return string The escaped value
1300
     */
1301
	public static function esc_like( $term ) {
1302
        global $wpdb;
1303
        if ( method_exists($wpdb, 'esc_like') ) {
1304
			// WP 4.0
1305
            $term = $wpdb->esc_like( $term );
1306
        } else {
1307
            $term = like_escape( $term );
1308
        }
1309
1310
        return $term;
1311
    }
1312
1313
    /**
1314
     * @param string $order_query
1315
     */
1316
	public static function esc_order( $order_query ) {
1317
        if ( empty($order_query) ) {
1318
            return '';
1319
        }
1320
1321
        // remove ORDER BY before santizing
1322
        $order_query = strtolower($order_query);
1323
        if ( strpos($order_query, 'order by') !== false ) {
1324
            $order_query = str_replace('order by', '', $order_query);
1325
        }
1326
1327
        $order_query = explode(' ', trim($order_query));
1328
1329
        $order_fields = array(
1330
            'id', 'form_key', 'name', 'description',
1331
            'parent_form_id', 'logged_in', 'is_template',
1332
            'default_template', 'status', 'created_at',
1333
        );
1334
1335
        $order = trim(trim(reset($order_query), ','));
1336
        if ( ! in_array($order, $order_fields) ) {
1337
            return '';
1338
        }
1339
1340
        $order_by = '';
1341
        if ( count($order_query) > 1 ) {
1342
			$order_by = end( $order_query );
1343
			self::esc_order_by( $order_by );
1344
        }
1345
1346
        return ' ORDER BY '. $order . ' '. $order_by;
1347
    }
1348
1349
	/**
1350
	 * Make sure this is ordering by either ASC or DESC
1351
	 */
1352
	public static function esc_order_by( &$order_by ) {
1353
		$sort_options = array( 'asc', 'desc' );
1354
		if ( ! in_array( strtolower( $order_by ), $sort_options ) ) {
1355
			$order_by = 'asc';
1356
		}
1357
	}
1358
1359
    /**
1360
     * @param string $limit
1361
     */
1362
	public static function esc_limit( $limit ) {
1363
        if ( empty($limit) ) {
1364
            return '';
1365
        }
1366
1367
        $limit = trim(str_replace(' limit', '', strtolower($limit)));
1368
        if ( is_numeric($limit) ) {
1369
            return ' LIMIT '. $limit;
1370
        }
1371
1372
        $limit = explode(',', trim($limit));
1373
        foreach ( $limit as $k => $l ) {
1374
            if ( is_numeric( $l ) ) {
1375
                $limit[ $k ] = $l;
1376
            }
1377
        }
1378
1379
        $limit = implode(',', $limit);
1380
        return ' LIMIT '. $limit;
1381
    }
1382
1383
    /**
1384
     * Get an array of values ready to go through $wpdb->prepare
1385
     * @since 2.0
1386
     */
1387
    public static function prepare_array_values( $array, $type = '%s' ) {
1388
        $placeholders = array_fill(0, count($array), $type);
1389
        return implode(', ', $placeholders);
1390
    }
1391
1392
    public static function prepend_and_or_where( $starts_with = ' WHERE ', $where = '' ) {
1393
        if ( empty($where) ) {
1394
            return '';
1395
        }
1396
1397
		if ( is_array( $where ) ) {
1398
            global $wpdb;
1399
            FrmDb::get_where_clause_and_values( $where, $starts_with );
1400
			$where = $wpdb->prepare( $where['where'], $where['values'] );
1401
		} else {
1402
            $where = $starts_with . $where;
1403
        }
1404
1405
        return $where;
1406
    }
1407
1408
    // Pagination Methods
1409
1410
    /**
1411
     * @param integer $current_p
1412
     */
1413
	public static function get_last_record_num( $r_count, $current_p, $p_size ) {
1414
		return ( ( $r_count < ( $current_p * $p_size ) ) ? $r_count : ( $current_p * $p_size ) );
1415
	}
1416
1417
    /**
1418
     * @param integer $current_p
1419
     */
1420
    public static function get_first_record_num( $r_count, $current_p, $p_size ) {
1421
        if ( $current_p == 1 ) {
1422
            return 1;
1423
        } else {
1424
            return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
1425
        }
1426
    }
1427
1428
    /**
1429
     * @param string $table_name
1430
     */
1431
    public static function &getRecordCount( $where = '', $table_name ) {
0 ignored issues
show
Coding Style introduced by
The function name getRecordCount is in camel caps, but expected get_record_count instead as per the coding standard.
Loading history...
1432
        _deprecated_function( __FUNCTION__, '2.0', 'FrmDb::get_count' );
1433
        $count = FrmDb::get_count( $table_name, $where );
0 ignored issues
show
Documentation introduced by
$where is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1434
        return $count;
1435
    }
1436
1437
    public static function get_referer_info() {
1438
        _deprecated_function( __FUNCTION__, '2.0', 'FrmAppHelper::get_server_value' );
1439
        return self::get_server_value('HTTP_REFERER');
1440
    }
1441
1442
	/**
1443
	 * @return array
1444
	 */
1445
	public static function json_to_array( $json_vars ) {
1446
        $vars = array();
1447
        foreach ( $json_vars as $jv ) {
1448
            $jv_name = explode('[', $jv['name']);
1449
            $last = count($jv_name) - 1;
1450
            foreach ( $jv_name as $p => $n ) {
1451
                $name = trim($n, ']');
1452
                if ( ! isset($l1) ) {
1453
                    $l1 = $name;
1454
                }
1455
1456
                if ( ! isset($l2) ) {
1457
                    $l2 = $name;
1458
                }
1459
1460
                if ( ! isset($l3) ) {
1461
                    $l3 = $name;
1462
                }
1463
1464
                $this_val = ( $p == $last ) ? $jv['value'] : array();
1465
1466
                switch ( $p ) {
1467
                    case 0:
1468
                        $l1 = $name;
1469
                        self::add_value_to_array( $name, $l1, $this_val, $vars );
1470
                    break;
1471
1472
                    case 1:
1473
                        $l2 = $name;
1474
                        self::add_value_to_array( $name, $l2, $this_val, $vars[ $l1 ] );
1475
                    break;
1476
1477 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...
1478
                        $l3 = $name;
1479
                        self::add_value_to_array( $name, $l3, $this_val, $vars[ $l1 ][ $l2 ] );
1480
                    break;
1481
1482 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...
1483
                        $l4 = $name;
1484
                        self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
1485
                    break;
1486
                }
1487
1488
                unset($this_val, $n);
1489
            }
1490
1491
            unset($last, $jv);
1492
        }
1493
1494
        return $vars;
1495
    }
1496
1497
    /**
1498
     * @param string $name
1499
     * @param string $l1
1500
     */
1501
    public static function add_value_to_array( $name, $l1, $val, &$vars ) {
1502
        if ( $name == '' ) {
1503
            $vars[] = $val;
1504
        } else if ( ! isset( $vars[ $l1 ] ) ) {
1505
            $vars[ $l1 ] = $val;
1506
        }
1507
    }
1508
1509
	public static function maybe_add_tooltip( $name, $class = 'closed', $form_name = '' ) {
1510
        $tooltips = array(
1511
            'action_title'  => __( 'Give this action a label for easy reference.', 'formidable' ),
1512
            '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' ),
1513
            'cc'            => __( 'Add CC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
1514
            'bcc'           => __( 'Add BCC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
1515
            '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' ),
1516
            'from'          => __( 'Enter the name and/or email address of the sender. FORMAT: John Bates <[email protected]> or [email protected].', 'formidable' ),
1517
            '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() ) ),
1518
        );
1519
1520
        if ( ! isset( $tooltips[ $name ] ) ) {
1521
            return;
1522
        }
1523
1524
        if ( 'open' == $class ) {
1525
            echo ' frm_help"';
1526
        } else {
1527
            echo ' class="frm_help"';
1528
        }
1529
1530
        echo ' title="'. esc_attr( $tooltips[ $name ] );
1531
1532
        if ( 'open' != $class ) {
1533
            echo '"';
1534
        }
1535
    }
1536
1537
	/**
1538
	 * Add the current_page class to that page in the form nav
1539
	 */
1540
	public static function select_current_page( $page, $current_page, $action = array() ) {
1541
		if ( $current_page != $page ) {
1542
			return;
1543
		}
1544
1545
		$frm_action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
1546
		if ( empty( $action ) || ( ! empty( $frm_action ) && in_array( $frm_action, $action ) ) ) {
1547
			echo ' class="current_page"';
1548
		}
1549
	}
1550
1551
    /**
1552
     * Prepare and json_encode post content
1553
     *
1554
     * @since 2.0
1555
     *
1556
     * @param array $post_content
1557
     * @return string $post_content ( json encoded array )
1558
     */
1559
    public static function prepare_and_encode( $post_content ) {
1560
        //Loop through array to strip slashes and add only the needed ones
1561
		foreach ( $post_content as $key => $val ) {
1562
			// Replace problematic characters (like &quot;)
1563
			$val = str_replace( '&quot;', '"', $val );
1564
1565
			self::prepare_action_slashes( $val, $key, $post_content );
1566
            unset( $key, $val );
1567
        }
1568
1569
        // json_encode the array
1570
        $post_content = json_encode( $post_content );
1571
1572
	    // add extra slashes for \r\n since WP strips them
1573
		$post_content = str_replace( array( '\\r', '\\n', '\\u', '\\t' ), array( '\\\\r', '\\\\n', '\\\\u', '\\\\t' ), $post_content );
1574
1575
        // allow for &quot
1576
	    $post_content = str_replace( '&quot;', '\\"', $post_content );
1577
1578
        return $post_content;
1579
    }
1580
1581
	private static function prepare_action_slashes( $val, $key, &$post_content ) {
1582
		if ( ! isset( $post_content[ $key ] ) ) {
1583
			return;
1584
		}
1585
1586
		if ( is_array( $val ) ) {
1587
			foreach ( $val as $k1 => $v1 ) {
1588
				self::prepare_action_slashes( $v1, $k1, $post_content[ $key ] );
1589
				unset( $k1, $v1 );
1590
			}
1591
		} else {
1592
			// Strip all slashes so everything is the same, no matter where the value is coming from
1593
			$val = stripslashes( $val );
1594
1595
			// Add backslashes before double quotes and forward slashes only
1596
			$post_content[ $key ] = addcslashes( $val, '"\\/' );
1597
		}
1598
	}
1599
1600
	/**
1601
	 * Prepare and save settings in styles and actions
1602
	 *
1603
	 * @param array $settings
1604
	 * @param string $group
1605
	 *
1606
	 * @since 2.0.6
1607
	 */
1608
	public static function save_settings( $settings, $group ) {
1609
		$settings = (array) $settings;
1610
		$settings['post_content'] = FrmAppHelper::prepare_and_encode( $settings['post_content'] );
1611
1612
		if ( empty( $settings['ID'] ) ) {
1613
			unset( $settings['ID']);
1614
		}
1615
1616
		// delete all caches for this group
1617
		self::cache_delete_group( $group );
1618
1619
		return self::save_json_post( $settings );
1620
	}
1621
1622
	/**
1623
	 * Since actions are JSON encoded, we don't want any filters messing with it.
1624
	 * Remove the filters and then add them back in case any posts or views are
1625
	 * also being imported.
1626
	 *
1627
	 * Used when saving form actions and styles
1628
	 *
1629
	 * @since 2.0.4
1630
	 */
1631
	public static function save_json_post( $settings ) {
1632
		global $wp_filter;
1633
		$filters = $wp_filter['content_save_pre'];
1634
1635
		// Remove the balanceTags filter in case WordPress is trying to validate the XHTML
1636
		remove_all_filters( 'content_save_pre' );
1637
1638
		$post = wp_insert_post( $settings );
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
1639
1640
		// add the content filters back for views or posts
1641
		$wp_filter['content_save_pre'] = $filters;
1642
1643
		return $post;
1644
	}
1645
1646
	public static function maybe_json_decode( $string ) {
1647
        if ( is_array($string) ) {
1648
            return $string;
1649
        }
1650
1651
        $new_string = json_decode($string, true);
1652
        if ( function_exists('json_last_error') ) {
1653
			// php 5.3+
1654
            if ( json_last_error() == JSON_ERROR_NONE ) {
1655
                $string = $new_string;
1656
            }
1657
        } else if ( isset($new_string) ) {
1658
			// php < 5.3 fallback
1659
            $string = $new_string;
1660
        }
1661
        return $string;
1662
    }
1663
1664
    /**
1665
     * @since 1.07.10
1666
     *
1667
     * @param string $post_type The name of the post type that may need to be highlighted
1668
     * @return echo The javascript to open and highlight the Formidable menu
1669
     */
1670
	public static function maybe_highlight_menu( $post_type ) {
1671
        global $post, $pagenow;
1672
1673
        if ( isset($_REQUEST['post_type']) && $_REQUEST['post_type'] != $post_type ) {
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
1674
            return;
1675
        }
1676
1677
        if ( is_object($post) && $post->post_type != $post_type ) {
1678
            return;
1679
        }
1680
1681
        self::load_admin_wide_js();
1682
        echo '<script type="text/javascript">jQuery(document).ready(function(){frmSelectSubnav();});</script>';
1683
    }
1684
1685
    /**
1686
     * Load the JS file on non-Formidable pages in the admin area
1687
     * @since 2.0
1688
     */
1689
	public static function load_admin_wide_js( $load = true ) {
1690
        $version = FrmAppHelper::plugin_version();
1691
		wp_register_script( 'formidable_admin_global', FrmAppHelper::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
1692
1693
        wp_localize_script( 'formidable_admin_global', 'frmGlobal', array(
1694
			'updating_msg' => __( 'Please wait while your site updates.', 'formidable' ),
1695
            'deauthorize'  => __( 'Are you sure you want to deauthorize Formidable Forms on this site?', 'formidable' ),
1696
			'url'          => FrmAppHelper::plugin_url(),
1697
			'loading'      => __( 'Loading&hellip;' ),
1698
			'nonce'        => wp_create_nonce( 'frm_ajax' ),
1699
        ) );
1700
1701
		if ( $load ) {
1702
			wp_enqueue_script( 'formidable_admin_global' );
1703
		}
1704
    }
1705
1706
	/**
1707
	 * @since 2.0.9
1708
	 */
1709
	public static function load_font_style() {
1710
		wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
1711
	}
1712
1713
    /**
1714
     * @param string $location
1715
     */
1716
	public static function localize_script( $location ) {
1717
		$ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
1718
		$ajax_url = apply_filters( 'frm_ajax_url', $ajax_url );
1719
1720
		wp_localize_script( 'formidable', 'frm_js', array(
1721
			'ajax_url'  => $ajax_url,
1722
			'images_url' => self::plugin_url() . '/images',
1723
			'loading'   => __( 'Loading&hellip;' ),
1724
			'remove'    => __( 'Remove', 'formidable' ),
1725
			'offset'    => apply_filters( 'frm_scroll_offset', 4 ),
1726
			'nonce'     => wp_create_nonce( 'frm_ajax' ),
1727
			'id'        => __( 'ID', 'formidable' ),
1728
		) );
1729
1730
		if ( $location == 'admin' ) {
1731
			$frm_settings = self::get_settings();
1732
			wp_localize_script( 'formidable_admin', 'frm_admin_js', array(
1733
				'confirm_uninstall' => __( 'Are you sure you want to do this? Clicking OK will delete all forms, form data, and all other Formidable data. There is no Undo.', 'formidable' ),
1734
				'desc'              => __( '(Click to add description)', 'formidable' ),
1735
				'blank'             => __( '(Blank)', 'formidable' ),
1736
				'no_label'          => __( '(no label)', 'formidable' ),
1737
				'saving'            => esc_attr( __( 'Saving', 'formidable' ) ),
1738
				'saved'             => esc_attr( __( 'Saved', 'formidable' ) ),
1739
				'ok'                => __( 'OK' ),
1740
				'cancel'            => __( 'Cancel', 'formidable' ),
1741
				'default'           => __( 'Default', 'formidable' ),
1742
				'clear_default'     => __( 'Clear default value when typing', 'formidable' ),
1743
				'no_clear_default'  => __( 'Do not clear default value when typing', 'formidable' ),
1744
				'valid_default'     => __( 'Default value will pass form validation', 'formidable' ),
1745
				'no_valid_default'  => __( 'Default value will NOT pass form validation', 'formidable' ),
1746
				'confirm'           => __( 'Are you sure?', 'formidable' ),
1747
				'conf_delete'       => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
1748
				'conf_delete_sec'   => __( 'WARNING: This will delete all fields inside of the section as well.', 'formidable' ),
1749
				'conf_no_repeat'    => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
1750
				'default_unique'    => $frm_settings->unique_msg,
1751
				'default_conf'      => __( 'The entered values do not match', 'formidable' ),
1752
				'enter_email'       => __( 'Enter Email', 'formidable' ),
1753
				'confirm_email'     => __( 'Confirm Email', 'formidable' ),
1754
				'enter_password'    => __( 'Enter Password', 'formidable' ),
1755
				'confirm_password'  => __( 'Confirm Password', 'formidable' ),
1756
				'import_complete'   => __( 'Import Complete', 'formidable' ),
1757
				'updating'          => __( 'Please wait while your site updates.', 'formidable' ),
1758
				'no_save_warning'   => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
1759
				'private'           => __( 'Private' ),
1760
				'jquery_ui_url'     => self::jquery_ui_base_url(),
1761
			) );
1762
		}
1763
	}
1764
1765
    /**
1766
     * @since 1.07.10
1767
     *
1768
     * @param float $min_version The version the add-on requires
1769
     * @return echo The message on the plugins listing page
1770
     */
1771
	public static function min_version_notice( $min_version ) {
1772
        $frm_version = self::plugin_version();
1773
1774
        // check if Formidable meets minimum requirements
1775
        if ( version_compare($frm_version, $min_version, '>=') ) {
1776
            return;
1777
        }
1778
1779
        $wp_list_table = _get_list_table('WP_Plugins_List_Table');
1780
		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">' .
1781
        __( 'You are running an outdated version of Formidable. This plugin may not work correctly if you do not update Formidable.', 'formidable' ) .
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw '__'
Loading history...
1782
        '</div></td></tr>';
1783
    }
1784
1785
    public static function locales( $type = 'date' ) {
1786
        $locales = array(
1787
            'en' => __( 'English', 'formidable' ),    '' => __( 'English/Western', 'formidable' ),
1788
            'af' => __( 'Afrikaans', 'formidable' ),  'sq' => __( 'Albanian', 'formidable' ),
1789
            'ar' => __( 'Arabic', 'formidable' ),     'hy' => __( 'Armenian', 'formidable' ),
1790
            'az' => __( 'Azerbaijani', 'formidable' ), 'eu' => __( 'Basque', 'formidable' ),
1791
            'bs' => __( 'Bosnian', 'formidable' ),    'bg' => __( 'Bulgarian', 'formidable' ),
1792
            'ca' => __( 'Catalan', 'formidable' ),    'zh-HK' => __( 'Chinese Hong Kong', 'formidable' ),
1793
            'zh-CN' => __( 'Chinese Simplified', 'formidable' ), 'zh-TW' => __( 'Chinese Traditional', 'formidable' ),
1794
            'hr' => __( 'Croatian', 'formidable' ),   'cs' => __( 'Czech', 'formidable' ),
1795
            'da' => __( 'Danish', 'formidable' ),     'nl' => __( 'Dutch', 'formidable' ),
1796
            'en-GB' => __( 'English/UK', 'formidable' ), 'eo' => __( 'Esperanto', 'formidable' ),
1797
            'et' => __( 'Estonian', 'formidable' ),   'fo' => __( 'Faroese', 'formidable' ),
1798
            'fa' => __( 'Farsi/Persian', 'formidable' ), 'fil' => __( 'Filipino', 'formidable' ),
1799
            'fi' => __( 'Finnish', 'formidable' ),    'fr' => __( 'French', 'formidable' ),
1800
            'fr-CA' => __( 'French/Canadian', 'formidable' ), 'fr-CH' => __( 'French/Swiss', 'formidable' ),
1801
            'de' => __( 'German', 'formidable' ),     'de-AT' => __( 'German/Austria', 'formidable' ),
1802
            'de-CH' => __( 'German/Switzerland', 'formidable' ), 'el' => __( 'Greek', 'formidable' ),
1803
            'he' => __( 'Hebrew', 'formidable' ),     'iw' => __( 'Hebrew', 'formidable' ),
1804
            'hi' => __( 'Hindi', 'formidable' ),      'hu' => __( 'Hungarian', 'formidable' ),
1805
            'is' => __( 'Icelandic', 'formidable' ),  'id' => __( 'Indonesian', 'formidable' ),
1806
            'it' => __( 'Italian', 'formidable' ),    'ja' => __( 'Japanese', 'formidable' ),
1807
            'ko' => __( 'Korean', 'formidable' ),     'lv' => __( 'Latvian', 'formidable' ),
1808
            'lt' => __( 'Lithuanian', 'formidable' ), 'ms' => __( 'Malaysian', 'formidable' ),
1809
            'no' => __( 'Norwegian', 'formidable' ),  'pl' => __( 'Polish', 'formidable' ),
1810
            'pt' => __( 'Portuguese', 'formidable' ), 'pt-BR' => __( 'Portuguese/Brazilian', 'formidable' ),
1811
            'pt-PT' => __( 'Portuguese/Portugal', 'formidable' ), 'ro' => __( 'Romanian', 'formidable' ),
1812
            'ru' => __( 'Russian', 'formidable' ),    'sr' => __( 'Serbian', 'formidable' ),
1813
            'sr-SR' => __( 'Serbian', 'formidable' ), 'sk' => __( 'Slovak', 'formidable' ),
1814
            'sl' => __( 'Slovenian', 'formidable' ),  'es' => __( 'Spanish', 'formidable' ),
1815
            'es-419' => __( 'Spanish/Latin America', 'formidable' ), 'sv' => __( 'Swedish', 'formidable' ),
1816
            'ta' => __( 'Tamil', 'formidable' ),      'th' => __( 'Thai', 'formidable' ),
1817
            'tu' => __( 'Turkish', 'formidable' ),    'tr' => __( 'Turkish', 'formidable' ),
1818
            'uk' => __( 'Ukranian', 'formidable' ),   'vi' => __( 'Vietnamese', 'formidable' ),
1819
        );
1820
1821
        if ( $type == 'captcha' ) {
1822
            // remove the languages unavailable for the captcha
1823
            $unset = array(
1824
                '', 'af', 'sq', 'hy', 'az', 'eu', 'bs',
1825
                'zh-HK', 'eo', 'et', 'fo', 'fr-CH',
1826
                'he', 'is', 'ms', 'sr-SR', 'ta', 'tu',
1827
            );
1828
        } else {
1829
            // remove the languages unavailable for the datepicker
1830
            $unset = array(
1831
                'en', 'fil', 'fr-CA', 'de-AT', 'de-AT',
1832
                'de-CH', 'iw', 'hi', 'pt', 'pt-PT',
1833
                'es-419', 'tr',
1834
            );
1835
        }
1836
1837
        $locales = array_diff_key($locales, array_flip($unset));
1838
        $locales = apply_filters('frm_locales', $locales);
1839
1840
        return $locales;
1841
    }
1842
}
1843