Completed
Push — master ( dd640d...c833ab )
by Jamie
08:54 queued 05:29
created

FrmAppHelper::get_time_strings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 11
rs 9.4286
cc 1
eloc 9
nc 1
nop 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 = 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
	 * Gets the time ago in words
1239
	 *
1240
	 * @param int $from in seconds
1241
	 * @param int|string $to in seconds
1242
	 * @return string $time_ago
1243
	 */
1244
	public static function human_time_diff( $from, $to = '' ) {
1245
		if ( empty( $to ) ) {
1246
			$now = new DateTime;
1247
		} else {
1248
			$now = new DateTime( '@' . $to );
1249
		}
1250
		$ago = new DateTime( '@' . $from );
1251
		$diff = $now->diff( $ago );
1252
1253
		$diff->w = floor( $diff->d / 7 );
0 ignored issues
show
Bug introduced by
The property w does not seem to exist in DateInterval.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1254
		$diff->d -= $diff->w * 7;
1255
1256
		$time_strings = self::get_time_strings();
1257
1258
		foreach ( $time_strings as $k => $v ) {
1259
			if ( $diff->$k ) {
1260
				$time_strings[ $k ] = $diff->$k . ' ' . ( $diff->$k > 1 ? $v[1] : $v[0] );
1261
			} else {
1262
				unset( $time_strings[ $k ] );
1263
			}
1264
		}
1265
1266
		$time_strings = array_slice( $time_strings, 0, 1 );
1267
		$time_ago_string = $time_strings ? implode( ', ', $time_strings ) : '0 ' . __( 'seconds', 'formidable' );
1268
1269
		return $time_ago_string;
1270
	}
1271
1272
	/**
1273
	 * Get the translatable time strings
1274
	 *
1275
	 * @since 2.0.20
1276
	 * @return array
1277
	 */
1278
	private static function get_time_strings() {
1279
		return array(
1280
			'y' => array( __( 'year', 'formidable' ), __( 'years', 'formidable' ) ),
1281
			'm' => array( __( 'month', 'formidable' ), __( 'months', 'formidable' ) ),
1282
			'w' => array( __( 'week', 'formidable' ), __( 'weeks', 'formidable' ) ),
1283
			'd' => array( __( 'day', 'formidable' ), __( 'days', 'formidable' ) ),
1284
			'h' => array( __( 'hour', 'formidable' ), __( 'hours', 'formidable' ) ),
1285
			'i' => array( __( 'minute', 'formidable' ), __( 'minutes', 'formidable' ) ),
1286
			's' => array( __( 'second', 'formidable' ), __( 'seconds', 'formidable' ) )
1287
		);
1288
	}
1289
1290
    /**
1291
     * Added for < WP 4.0 compatability
1292
     *
1293
     * @since 1.07.10
1294
     *
1295
     * @param string $term The value to escape
1296
     * @return string The escaped value
1297
     */
1298
	public static function esc_like( $term ) {
1299
        global $wpdb;
1300
        if ( method_exists($wpdb, 'esc_like') ) {
1301
			// WP 4.0
1302
            $term = $wpdb->esc_like( $term );
1303
        } else {
1304
            $term = like_escape( $term );
1305
        }
1306
1307
        return $term;
1308
    }
1309
1310
    /**
1311
     * @param string $order_query
1312
     */
1313
	public static function esc_order( $order_query ) {
1314
        if ( empty($order_query) ) {
1315
            return '';
1316
        }
1317
1318
        // remove ORDER BY before santizing
1319
        $order_query = strtolower($order_query);
1320
        if ( strpos($order_query, 'order by') !== false ) {
1321
            $order_query = str_replace('order by', '', $order_query);
1322
        }
1323
1324
        $order_query = explode(' ', trim($order_query));
1325
1326
        $order_fields = array(
1327
            'id', 'form_key', 'name', 'description',
1328
            'parent_form_id', 'logged_in', 'is_template',
1329
            'default_template', 'status', 'created_at',
1330
        );
1331
1332
        $order = trim(trim(reset($order_query), ','));
1333
        if ( ! in_array($order, $order_fields) ) {
1334
            return '';
1335
        }
1336
1337
        $order_by = '';
1338
        if ( count($order_query) > 1 ) {
1339
			$order_by = end( $order_query );
1340
			self::esc_order_by( $order_by );
1341
        }
1342
1343
        return ' ORDER BY '. $order . ' '. $order_by;
1344
    }
1345
1346
	/**
1347
	 * Make sure this is ordering by either ASC or DESC
1348
	 */
1349
	public static function esc_order_by( &$order_by ) {
1350
		$sort_options = array( 'asc', 'desc' );
1351
		if ( ! in_array( strtolower( $order_by ), $sort_options ) ) {
1352
			$order_by = 'asc';
1353
		}
1354
	}
1355
1356
    /**
1357
     * @param string $limit
1358
     */
1359
	public static function esc_limit( $limit ) {
1360
        if ( empty($limit) ) {
1361
            return '';
1362
        }
1363
1364
        $limit = trim(str_replace(' limit', '', strtolower($limit)));
1365
        if ( is_numeric($limit) ) {
1366
            return ' LIMIT '. $limit;
1367
        }
1368
1369
        $limit = explode(',', trim($limit));
1370
        foreach ( $limit as $k => $l ) {
1371
            if ( is_numeric( $l ) ) {
1372
                $limit[ $k ] = $l;
1373
            }
1374
        }
1375
1376
        $limit = implode(',', $limit);
1377
        return ' LIMIT '. $limit;
1378
    }
1379
1380
    /**
1381
     * Get an array of values ready to go through $wpdb->prepare
1382
     * @since 2.0
1383
     */
1384
    public static function prepare_array_values( $array, $type = '%s' ) {
1385
        $placeholders = array_fill(0, count($array), $type);
1386
        return implode(', ', $placeholders);
1387
    }
1388
1389
    public static function prepend_and_or_where( $starts_with = ' WHERE ', $where = '' ) {
1390
        if ( empty($where) ) {
1391
            return '';
1392
        }
1393
1394
		if ( is_array( $where ) ) {
1395
            global $wpdb;
1396
            FrmDb::get_where_clause_and_values( $where, $starts_with );
1397
			$where = $wpdb->prepare( $where['where'], $where['values'] );
1398
		} else {
1399
            $where = $starts_with . $where;
1400
        }
1401
1402
        return $where;
1403
    }
1404
1405
    // Pagination Methods
1406
1407
    /**
1408
     * @param integer $current_p
1409
     */
1410
	public static function get_last_record_num( $r_count, $current_p, $p_size ) {
1411
		return ( ( $r_count < ( $current_p * $p_size ) ) ? $r_count : ( $current_p * $p_size ) );
1412
	}
1413
1414
    /**
1415
     * @param integer $current_p
1416
     */
1417
    public static function get_first_record_num( $r_count, $current_p, $p_size ) {
1418
        if ( $current_p == 1 ) {
1419
            return 1;
1420
        } else {
1421
            return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
1422
        }
1423
    }
1424
1425
    /**
1426
     * @param string $table_name
1427
     */
1428
    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...
1429
        _deprecated_function( __FUNCTION__, '2.0', 'FrmDb::get_count' );
1430
        $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...
1431
        return $count;
1432
    }
1433
1434
    public static function get_referer_info() {
1435
        _deprecated_function( __FUNCTION__, '2.0', 'FrmAppHelper::get_server_value' );
1436
        return self::get_server_value('HTTP_REFERER');
1437
    }
1438
1439
	/**
1440
	 * @return array
1441
	 */
1442
	public static function json_to_array( $json_vars ) {
1443
        $vars = array();
1444
        foreach ( $json_vars as $jv ) {
1445
            $jv_name = explode('[', $jv['name']);
1446
            $last = count($jv_name) - 1;
1447
            foreach ( $jv_name as $p => $n ) {
1448
                $name = trim($n, ']');
1449
                if ( ! isset($l1) ) {
1450
                    $l1 = $name;
1451
                }
1452
1453
                if ( ! isset($l2) ) {
1454
                    $l2 = $name;
1455
                }
1456
1457
                if ( ! isset($l3) ) {
1458
                    $l3 = $name;
1459
                }
1460
1461
                $this_val = ( $p == $last ) ? $jv['value'] : array();
1462
1463
                switch ( $p ) {
1464
                    case 0:
1465
                        $l1 = $name;
1466
                        self::add_value_to_array( $name, $l1, $this_val, $vars );
1467
                    break;
1468
1469
                    case 1:
1470
                        $l2 = $name;
1471
                        self::add_value_to_array( $name, $l2, $this_val, $vars[ $l1 ] );
1472
                    break;
1473
1474 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...
1475
                        $l3 = $name;
1476
                        self::add_value_to_array( $name, $l3, $this_val, $vars[ $l1 ][ $l2 ] );
1477
                    break;
1478
1479 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...
1480
                        $l4 = $name;
1481
                        self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
1482
                    break;
1483
                }
1484
1485
                unset($this_val, $n);
1486
            }
1487
1488
            unset($last, $jv);
1489
        }
1490
1491
        return $vars;
1492
    }
1493
1494
    /**
1495
     * @param string $name
1496
     * @param string $l1
1497
     */
1498
    public static function add_value_to_array( $name, $l1, $val, &$vars ) {
1499
        if ( $name == '' ) {
1500
            $vars[] = $val;
1501
        } else if ( ! isset( $vars[ $l1 ] ) ) {
1502
            $vars[ $l1 ] = $val;
1503
        }
1504
    }
1505
1506
	public static function maybe_add_tooltip( $name, $class = 'closed', $form_name = '' ) {
1507
        $tooltips = array(
1508
            'action_title'  => __( 'Give this action a label for easy reference.', 'formidable' ),
1509
            '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' ),
1510
            'cc'            => __( 'Add CC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
1511
            'bcc'           => __( 'Add BCC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
1512
            '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' ),
1513
            'from'          => __( 'Enter the name and/or email address of the sender. FORMAT: John Bates <[email protected]> or [email protected].', 'formidable' ),
1514
            '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() ) ),
1515
        );
1516
1517
        if ( ! isset( $tooltips[ $name ] ) ) {
1518
            return;
1519
        }
1520
1521
        if ( 'open' == $class ) {
1522
            echo ' frm_help"';
1523
        } else {
1524
            echo ' class="frm_help"';
1525
        }
1526
1527
        echo ' title="'. esc_attr( $tooltips[ $name ] );
1528
1529
        if ( 'open' != $class ) {
1530
            echo '"';
1531
        }
1532
    }
1533
1534
	/**
1535
	 * Add the current_page class to that page in the form nav
1536
	 */
1537
	public static function select_current_page( $page, $current_page, $action = array() ) {
1538
		if ( $current_page != $page ) {
1539
			return;
1540
		}
1541
1542
		$frm_action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
1543
		if ( empty( $action ) || ( ! empty( $frm_action ) && in_array( $frm_action, $action ) ) ) {
1544
			echo ' class="current_page"';
1545
		}
1546
	}
1547
1548
    /**
1549
     * Prepare and json_encode post content
1550
     *
1551
     * @since 2.0
1552
     *
1553
     * @param array $post_content
1554
     * @return string $post_content ( json encoded array )
1555
     */
1556
    public static function prepare_and_encode( $post_content ) {
1557
        //Loop through array to strip slashes and add only the needed ones
1558
		foreach ( $post_content as $key => $val ) {
1559
			// Replace problematic characters (like &quot;)
1560
			$val = str_replace( '&quot;', '"', $val );
1561
1562
			self::prepare_action_slashes( $val, $key, $post_content );
1563
            unset( $key, $val );
1564
        }
1565
1566
        // json_encode the array
1567
        $post_content = json_encode( $post_content );
1568
1569
	    // add extra slashes for \r\n since WP strips them
1570
		$post_content = str_replace( array( '\\r', '\\n', '\\u', '\\t' ), array( '\\\\r', '\\\\n', '\\\\u', '\\\\t' ), $post_content );
1571
1572
        // allow for &quot
1573
	    $post_content = str_replace( '&quot;', '\\"', $post_content );
1574
1575
        return $post_content;
1576
    }
1577
1578
	private static function prepare_action_slashes( $val, $key, &$post_content ) {
1579
		if ( ! isset( $post_content[ $key ] ) ) {
1580
			return;
1581
		}
1582
1583
		if ( is_array( $val ) ) {
1584
			foreach ( $val as $k1 => $v1 ) {
1585
				self::prepare_action_slashes( $v1, $k1, $post_content[ $key ] );
1586
				unset( $k1, $v1 );
1587
			}
1588
		} else {
1589
			// Strip all slashes so everything is the same, no matter where the value is coming from
1590
			$val = stripslashes( $val );
1591
1592
			// Add backslashes before double quotes and forward slashes only
1593
			$post_content[ $key ] = addcslashes( $val, '"\\/' );
1594
		}
1595
	}
1596
1597
	/**
1598
	 * Prepare and save settings in styles and actions
1599
	 *
1600
	 * @param array $settings
1601
	 * @param string $group
1602
	 *
1603
	 * @since 2.0.6
1604
	 */
1605
	public static function save_settings( $settings, $group ) {
1606
		$settings = (array) $settings;
1607
		$settings['post_content'] = FrmAppHelper::prepare_and_encode( $settings['post_content'] );
1608
1609
		if ( empty( $settings['ID'] ) ) {
1610
			unset( $settings['ID']);
1611
		}
1612
1613
		// delete all caches for this group
1614
		self::cache_delete_group( $group );
1615
1616
		return self::save_json_post( $settings );
1617
	}
1618
1619
	/**
1620
	 * Since actions are JSON encoded, we don't want any filters messing with it.
1621
	 * Remove the filters and then add them back in case any posts or views are
1622
	 * also being imported.
1623
	 *
1624
	 * Used when saving form actions and styles
1625
	 *
1626
	 * @since 2.0.4
1627
	 */
1628
	public static function save_json_post( $settings ) {
1629
		global $wp_filter;
1630
		$filters = $wp_filter['content_save_pre'];
1631
1632
		// Remove the balanceTags filter in case WordPress is trying to validate the XHTML
1633
		remove_all_filters( 'content_save_pre' );
1634
1635
		$post = wp_insert_post( $settings );
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
1636
1637
		// add the content filters back for views or posts
1638
		$wp_filter['content_save_pre'] = $filters;
1639
1640
		return $post;
1641
	}
1642
1643
	public static function maybe_json_decode( $string ) {
1644
        if ( is_array($string) ) {
1645
            return $string;
1646
        }
1647
1648
        $new_string = json_decode($string, true);
1649
        if ( function_exists('json_last_error') ) {
1650
			// php 5.3+
1651
            if ( json_last_error() == JSON_ERROR_NONE ) {
1652
                $string = $new_string;
1653
            }
1654
        } else if ( isset($new_string) ) {
1655
			// php < 5.3 fallback
1656
            $string = $new_string;
1657
        }
1658
        return $string;
1659
    }
1660
1661
    /**
1662
     * @since 1.07.10
1663
     *
1664
     * @param string $post_type The name of the post type that may need to be highlighted
1665
     * @return echo The javascript to open and highlight the Formidable menu
1666
     */
1667
	public static function maybe_highlight_menu( $post_type ) {
1668
        global $post, $pagenow;
1669
1670
        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...
1671
            return;
1672
        }
1673
1674
        if ( is_object($post) && $post->post_type != $post_type ) {
1675
            return;
1676
        }
1677
1678
        self::load_admin_wide_js();
1679
        echo '<script type="text/javascript">jQuery(document).ready(function(){frmSelectSubnav();});</script>';
1680
    }
1681
1682
    /**
1683
     * Load the JS file on non-Formidable pages in the admin area
1684
     * @since 2.0
1685
     */
1686
	public static function load_admin_wide_js( $load = true ) {
1687
        $version = FrmAppHelper::plugin_version();
1688
		wp_register_script( 'formidable_admin_global', FrmAppHelper::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
1689
1690
        wp_localize_script( 'formidable_admin_global', 'frmGlobal', array(
1691
			'updating_msg' => __( 'Please wait while your site updates.', 'formidable' ),
1692
            'deauthorize'  => __( 'Are you sure you want to deauthorize Formidable Forms on this site?', 'formidable' ),
1693
			'url'          => FrmAppHelper::plugin_url(),
1694
			'loading'      => __( 'Loading&hellip;' ),
1695
			'nonce'        => wp_create_nonce( 'frm_ajax' ),
1696
        ) );
1697
1698
		if ( $load ) {
1699
			wp_enqueue_script( 'formidable_admin_global' );
1700
		}
1701
    }
1702
1703
	/**
1704
	 * @since 2.0.9
1705
	 */
1706
	public static function load_font_style() {
1707
		wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
1708
	}
1709
1710
    /**
1711
     * @param string $location
1712
     */
1713
	public static function localize_script( $location ) {
1714
		$ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
1715
		$ajax_url = apply_filters( 'frm_ajax_url', $ajax_url );
1716
1717
		wp_localize_script( 'formidable', 'frm_js', array(
1718
			'ajax_url'  => $ajax_url,
1719
			'images_url' => self::plugin_url() . '/images',
1720
			'loading'   => __( 'Loading&hellip;' ),
1721
			'remove'    => __( 'Remove', 'formidable' ),
1722
			'offset'    => apply_filters( 'frm_scroll_offset', 4 ),
1723
			'nonce'     => wp_create_nonce( 'frm_ajax' ),
1724
			'id'        => __( 'ID', 'formidable' ),
1725
		) );
1726
1727
		if ( $location == 'admin' ) {
1728
			$frm_settings = self::get_settings();
1729
			wp_localize_script( 'formidable_admin', 'frm_admin_js', array(
1730
				'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' ),
1731
				'desc'              => __( '(Click to add description)', 'formidable' ),
1732
				'blank'             => __( '(Blank)', 'formidable' ),
1733
				'no_label'          => __( '(no label)', 'formidable' ),
1734
				'saving'            => esc_attr( __( 'Saving', 'formidable' ) ),
1735
				'saved'             => esc_attr( __( 'Saved', 'formidable' ) ),
1736
				'ok'                => __( 'OK' ),
1737
				'cancel'            => __( 'Cancel', 'formidable' ),
1738
				'default'           => __( 'Default', 'formidable' ),
1739
				'clear_default'     => __( 'Clear default value when typing', 'formidable' ),
1740
				'no_clear_default'  => __( 'Do not clear default value when typing', 'formidable' ),
1741
				'valid_default'     => __( 'Default value will pass form validation', 'formidable' ),
1742
				'no_valid_default'  => __( 'Default value will NOT pass form validation', 'formidable' ),
1743
				'confirm'           => __( 'Are you sure?', 'formidable' ),
1744
				'conf_delete'       => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
1745
				'conf_delete_sec'   => __( 'WARNING: This will delete all fields inside of the section as well.', 'formidable' ),
1746
				'conf_no_repeat'    => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
1747
				'default_unique'    => $frm_settings->unique_msg,
1748
				'default_conf'      => __( 'The entered values do not match', 'formidable' ),
1749
				'enter_email'       => __( 'Enter Email', 'formidable' ),
1750
				'confirm_email'     => __( 'Confirm Email', 'formidable' ),
1751
				'enter_password'    => __( 'Enter Password', 'formidable' ),
1752
				'confirm_password'  => __( 'Confirm Password', 'formidable' ),
1753
				'import_complete'   => __( 'Import Complete', 'formidable' ),
1754
				'updating'          => __( 'Please wait while your site updates.', 'formidable' ),
1755
				'no_save_warning'   => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
1756
				'private'           => __( 'Private' ),
1757
				'jquery_ui_url'     => self::jquery_ui_base_url(),
1758
			) );
1759
		}
1760
	}
1761
1762
    /**
1763
     * @since 1.07.10
1764
     *
1765
     * @param float $min_version The version the add-on requires
1766
     * @return echo The message on the plugins listing page
1767
     */
1768
	public static function min_version_notice( $min_version ) {
1769
        $frm_version = self::plugin_version();
1770
1771
        // check if Formidable meets minimum requirements
1772
        if ( version_compare($frm_version, $min_version, '>=') ) {
1773
            return;
1774
        }
1775
1776
        $wp_list_table = _get_list_table('WP_Plugins_List_Table');
1777
		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">' .
1778
        __( '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...
1779
        '</div></td></tr>';
1780
    }
1781
1782
    public static function locales( $type = 'date' ) {
1783
        $locales = array(
1784
            'en' => __( 'English', 'formidable' ),    '' => __( 'English/Western', 'formidable' ),
1785
            'af' => __( 'Afrikaans', 'formidable' ),  'sq' => __( 'Albanian', 'formidable' ),
1786
            'ar' => __( 'Arabic', 'formidable' ),     'hy' => __( 'Armenian', 'formidable' ),
1787
            'az' => __( 'Azerbaijani', 'formidable' ), 'eu' => __( 'Basque', 'formidable' ),
1788
            'bs' => __( 'Bosnian', 'formidable' ),    'bg' => __( 'Bulgarian', 'formidable' ),
1789
            'ca' => __( 'Catalan', 'formidable' ),    'zh-HK' => __( 'Chinese Hong Kong', 'formidable' ),
1790
            'zh-CN' => __( 'Chinese Simplified', 'formidable' ), 'zh-TW' => __( 'Chinese Traditional', 'formidable' ),
1791
            'hr' => __( 'Croatian', 'formidable' ),   'cs' => __( 'Czech', 'formidable' ),
1792
            'da' => __( 'Danish', 'formidable' ),     'nl' => __( 'Dutch', 'formidable' ),
1793
            'en-GB' => __( 'English/UK', 'formidable' ), 'eo' => __( 'Esperanto', 'formidable' ),
1794
            'et' => __( 'Estonian', 'formidable' ),   'fo' => __( 'Faroese', 'formidable' ),
1795
            'fa' => __( 'Farsi/Persian', 'formidable' ), 'fil' => __( 'Filipino', 'formidable' ),
1796
            'fi' => __( 'Finnish', 'formidable' ),    'fr' => __( 'French', 'formidable' ),
1797
            'fr-CA' => __( 'French/Canadian', 'formidable' ), 'fr-CH' => __( 'French/Swiss', 'formidable' ),
1798
            'de' => __( 'German', 'formidable' ),     'de-AT' => __( 'German/Austria', 'formidable' ),
1799
            'de-CH' => __( 'German/Switzerland', 'formidable' ), 'el' => __( 'Greek', 'formidable' ),
1800
            'he' => __( 'Hebrew', 'formidable' ),     'iw' => __( 'Hebrew', 'formidable' ),
1801
            'hi' => __( 'Hindi', 'formidable' ),      'hu' => __( 'Hungarian', 'formidable' ),
1802
            'is' => __( 'Icelandic', 'formidable' ),  'id' => __( 'Indonesian', 'formidable' ),
1803
            'it' => __( 'Italian', 'formidable' ),    'ja' => __( 'Japanese', 'formidable' ),
1804
            'ko' => __( 'Korean', 'formidable' ),     'lv' => __( 'Latvian', 'formidable' ),
1805
            'lt' => __( 'Lithuanian', 'formidable' ), 'ms' => __( 'Malaysian', 'formidable' ),
1806
            'no' => __( 'Norwegian', 'formidable' ),  'pl' => __( 'Polish', 'formidable' ),
1807
            'pt' => __( 'Portuguese', 'formidable' ), 'pt-BR' => __( 'Portuguese/Brazilian', 'formidable' ),
1808
            'pt-PT' => __( 'Portuguese/Portugal', 'formidable' ), 'ro' => __( 'Romanian', 'formidable' ),
1809
            'ru' => __( 'Russian', 'formidable' ),    'sr' => __( 'Serbian', 'formidable' ),
1810
            'sr-SR' => __( 'Serbian', 'formidable' ), 'sk' => __( 'Slovak', 'formidable' ),
1811
            'sl' => __( 'Slovenian', 'formidable' ),  'es' => __( 'Spanish', 'formidable' ),
1812
            'es-419' => __( 'Spanish/Latin America', 'formidable' ), 'sv' => __( 'Swedish', 'formidable' ),
1813
            'ta' => __( 'Tamil', 'formidable' ),      'th' => __( 'Thai', 'formidable' ),
1814
            'tu' => __( 'Turkish', 'formidable' ),    'tr' => __( 'Turkish', 'formidable' ),
1815
            'uk' => __( 'Ukranian', 'formidable' ),   'vi' => __( 'Vietnamese', 'formidable' ),
1816
        );
1817
1818
        if ( $type == 'captcha' ) {
1819
            // remove the languages unavailable for the captcha
1820
            $unset = array(
1821
                '', 'af', 'sq', 'hy', 'az', 'eu', 'bs',
1822
                'zh-HK', 'eo', 'et', 'fo', 'fr-CH',
1823
                'he', 'is', 'ms', 'sr-SR', 'ta', 'tu',
1824
            );
1825
        } else {
1826
            // remove the languages unavailable for the datepicker
1827
            $unset = array(
1828
                'en', 'fil', 'fr-CA', 'de-AT', 'de-AT',
1829
                'de-CH', 'iw', 'hi', 'pt', 'pt-PT',
1830
                'es-419', 'tr',
1831
            );
1832
        }
1833
1834
        $locales = array_diff_key($locales, array_flip($unset));
1835
        $locales = apply_filters('frm_locales', $locales);
1836
1837
        return $locales;
1838
    }
1839
}
1840