Completed
Push — master ( 185c12...2d5c51 )
by Jamie
03:34
created

FrmAppHelper::script_version()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 4
nop 2
dl 0
loc 18
rs 8.8571
c 0
b 0
f 0
1
<?php
2
if ( ! defined('ABSPATH') ) {
3
	die( 'You are not allowed to call this page directly.' );
4
}
5
6
class FrmAppHelper {
7
	public static $db_version = 42; //version of the database we are moving to
8
	public static $pro_db_version = 37; //deprecated
9
10
	/**
11
	 * @since 2.0
12
	 */
13
	public static $plug_version = '2.03.03';
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 = self::get_affiliate();
62
		if ( ! empty( $affiliate_id ) ) {
63
			$url = add_query_arg( 'aff', $affiliate_id, $url );
64
		}
65
		return $url;
66
	}
67
68
	public static function get_affiliate() {
69
		return '';
70
		$affiliate_id = apply_filters( 'frm_affiliate_link', get_option('frm_aff') );
0 ignored issues
show
Unused Code introduced by
$affiliate_id = apply_fi...get_option('frm_aff')); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
71
		$affiliate_id = strtolower( $affiliate_id );
72
		$allowed_affiliates = array();
73
		if ( ! in_array( $affiliate_id, $allowed_affiliates ) ) {
74
			$affiliate_id = false;
75
		}
76
		return $affiliate_id;
77
	}
78
79
    /**
80
     * Get the Formidable settings
81
     *
82
     * @since 2.0
83
     *
84
     * @param None
85
     * @return FrmSettings $frm_setings
86
     */
87
    public static function get_settings() {
88
        global $frm_settings;
89
        if ( empty($frm_settings) ) {
90
            $frm_settings = new FrmSettings();
91
        }
92
        return $frm_settings;
93
    }
94
95
	public static function get_menu_name() {
96
		$frm_settings = FrmAppHelper::get_settings();
97
		return $frm_settings->menu;
98
	}
99
100
    /**
101
     * Show a message in place of pro features
102
     *
103
     * @since 2.0
104
     */
105
	public static function update_message() {
106
		_deprecated_function( __FUNCTION__, '2.0.19' );
107
    }
108
109
    public static function pro_is_installed() {
110
        return apply_filters('frm_pro_installed', false);
111
    }
112
113
    /**
114
     * Check for certain page in Formidable settings
115
     *
116
     * @since 2.0
117
     *
118
     * @param string $page The name of the page to check
119
     * @return boolean
120
     */
121
	public static function is_admin_page( $page = 'formidable' ) {
122
        global $pagenow;
123
		$get_page = self::simple_get( 'page', 'sanitize_title' );
124
        if ( $pagenow ) {
125
			return $pagenow == 'admin.php' && $get_page == $page;
126
        }
127
128
		return is_admin() && $get_page == $page;
129
    }
130
131
    /**
132
     * Check for the form preview page
133
     *
134
     * @since 2.0
135
     *
136
     * @param None
137
     * @return boolean
138
     */
139
    public static function is_preview_page() {
140
        global $pagenow;
141
		$action = FrmAppHelper::simple_get( 'action', 'sanitize_title' );
142
		return $pagenow && $pagenow == 'admin-ajax.php' && $action == 'frm_forms_preview';
143
    }
144
145
    /**
146
     * Check for ajax except the form preview page
147
     *
148
     * @since 2.0
149
     *
150
     * @param None
151
     * @return boolean
152
     */
153
    public static function doing_ajax() {
154
        return defined('DOING_AJAX') && DOING_AJAX && ! self::is_preview_page();
155
    }
156
157
	/**
158
	 * @since 2.0.8
159
	 */
160
	public static function prevent_caching() {
161
		global $frm_vars;
162
		return isset( $frm_vars['prevent_caching'] ) && $frm_vars['prevent_caching'];
163
	}
164
165
    /**
166
     * Check if on an admin page
167
     *
168
     * @since 2.0
169
     *
170
     * @param None
171
     * @return boolean
172
     */
173
    public static function is_admin() {
174
        return is_admin() && ( ! defined('DOING_AJAX') || ! DOING_AJAX );
175
    }
176
177
    /**
178
     * Check if value contains blank value or empty array
179
     *
180
     * @since 2.0
181
     * @param mixed $value - value to check
182
	 * @param string
183
     * @return boolean
184
     */
185
    public static function is_empty_value( $value, $empty = '' ) {
186
        return ( is_array( $value ) && empty( $value ) ) || $value == $empty;
187
    }
188
189
    public static function is_not_empty_value( $value, $empty = '' ) {
190
        return ! self::is_empty_value( $value, $empty );
191
    }
192
193
    /**
194
     * Get any value from the $_SERVER
195
     *
196
     * @since 2.0
197
     * @param string $value
198
     * @return string
199
     */
200
	public static function get_server_value( $value ) {
201
        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...
202
    }
203
204
    /**
205
     * Check for the IP address in several places
206
     * Used by [ip] shortcode
207
     *
208
     * @return string The IP address of the current user
209
     */
210
    public static function get_ip_address() {
211
		$ip = '';
212
        foreach ( array(
213
            'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP',
214
            'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR',
215
        ) as $key ) {
216
            if ( ! isset( $_SERVER[ $key ] ) ) {
217
                continue;
218
            }
219
220
            foreach ( explode( ',', $_SERVER[ $key ] ) as $ip ) {
221
                $ip = trim($ip); // just to be safe
222
223
                if ( filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false ) {
224
                    return $ip;
225
                }
226
            }
227
        }
228
229
		return sanitize_text_field( $ip );
230
    }
231
232
    public static function get_param( $param, $default = '', $src = 'get', $sanitize = '' ) {
233
        if ( strpos($param, '[') ) {
234
            $params = explode('[', $param);
235
            $param = $params[0];
236
        }
237
238
		if ( $src == 'get' ) {
239
            $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...
240
            if ( ! isset( $_POST[ $param ] ) && isset( $_GET[ $param ] ) && ! is_array( $value ) ) {
241
                $value = stripslashes_deep( htmlspecialchars_decode( $_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...
242
            }
243
			self::sanitize_value( $sanitize, $value );
244
		} else {
245
            $value = self::get_simple_request( array( 'type' => $src, 'param' => $param, 'default' => $default, 'sanitize' => $sanitize ) );
246
        }
247
248
		if ( isset( $params ) && is_array( $value ) && ! empty( $value ) ) {
249
            foreach ( $params as $k => $p ) {
250
                if ( ! $k || ! is_array($value) ) {
251
                    continue;
252
                }
253
254
                $p = trim($p, ']');
255
                $value = isset( $value[ $p ] ) ? $value[ $p ] : $default;
256
            }
257
        }
258
259
        return $value;
260
    }
261
262
	public static function get_post_param( $param, $default = '', $sanitize = '' ) {
263
		return self::get_simple_request( array( 'type' => 'post', 'param' => $param, 'default' => $default, 'sanitize' => $sanitize ) );
264
	}
265
266
	/**
267
	 * @since 2.0
268
	 *
269
	 * @param string $param
270
	 * @param string $sanitize
271
	 * @param string $default
272
	 * @return string|array
273
	 */
274
	public static function simple_get( $param, $sanitize = 'sanitize_text_field', $default = '' ) {
275
		return self::get_simple_request( array( 'type' => 'get', 'param' => $param, 'default' => $default, 'sanitize' => $sanitize ) );
276
    }
277
278
	/**
279
	 * Get a GET/POST/REQUEST value and sanitize it
280
	 *
281
	 * @since 2.0.6
282
	 * @param array $args
283
	 * @return string|array
284
	 */
285
	public static function get_simple_request( $args ) {
286
		$defaults = array(
287
			'param' => '', 'default' => '',
288
			'type' => 'get', 'sanitize' => 'sanitize_text_field',
289
		);
290
		$args = wp_parse_args( $args, $defaults );
291
292
		$value = $args['default'];
293
		if ( $args['type'] == 'get' ) {
294
			if ( $_GET && isset( $_GET[ $args['param'] ] ) ) {
295
				$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...
296
			}
297
		} else if ( $args['type'] == 'post' ) {
298
			if ( isset( $_POST[ $args['param'] ] ) ) {
299
				$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...
300
			}
301
		} else {
302
			if ( isset( $_REQUEST[ $args['param'] ] ) ) {
303
				$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...
304
			}
305
		}
306
307
		self::sanitize_value( $args['sanitize'], $value );
308
		return $value;
309
	}
310
311
	/**
312
	* Preserve backslashes in a value, but make sure value doesn't get compounding slashes
313
	*
314
	* @since 2.0.8
315
	* @param string $value
316
	* @return string $value
317
	*/
318
	public static function preserve_backslashes( $value ) {
319
		// If backslashes have already been added, don't add them again
320
		if ( strpos( $value, '\\\\' ) === false ) {
321
			$value = addslashes( $value );
322
		}
323
		return $value;
324
	}
325
326
	public static function sanitize_value( $sanitize, &$value ) {
327
		if ( ! empty( $sanitize ) ) {
328
			if ( is_array( $value ) ) {
329
				$temp_values = $value;
330
				foreach ( $temp_values as $k => $v ) {
331
					FrmAppHelper::sanitize_value( $sanitize, $value[ $k ] );
332
				}
333
			} else {
334
				$value = call_user_func( $sanitize, $value );
335
			}
336
		}
337
	}
338
339
    public static function sanitize_request( $sanitize_method, &$values ) {
340
        $temp_values = $values;
341
        foreach ( $temp_values as $k => $val ) {
342
            if ( isset( $sanitize_method[ $k ] ) ) {
343
				$values[ $k ] = call_user_func( $sanitize_method[ $k ], $val );
344
            }
345
        }
346
    }
347
348
	public static function sanitize_array( &$values ) {
349
		$temp_values = $values;
350
		foreach ( $temp_values as $k => $val ) {
351
			$values[ $k ] = wp_kses_post( $val );
352
		}
353
	}
354
355
	/**
356
	 * Sanitize the value, and allow some HTML
357
	 * @since 2.0
358
	 * @param string $value
359
	 * @param array $allowed
360
	 * @return string
361
	 */
362
	public static function kses( $value, $allowed = array() ) {
363
		$html = array(
364
		    'a' => array(
365
				'href'  => array(),
366
				'title' => array(),
367
				'id'    => array(),
368
				'class' => array(),
369
		    ),
370
		);
371
372
		$allowed_html = array();
373
		foreach ( $allowed as $a ) {
374
			$allowed_html[ $a ] = isset( $html[ $a ] ) ? $html[ $a ] : array();
375
		}
376
377
		return wp_kses( $value, $allowed_html );
378
	}
379
380
    /**
381
     * Used when switching the action for a bulk action
382
     * @since 2.0
383
     */
384
    public static function remove_get_action() {
385
        if ( ! isset($_GET) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
386
            return;
387
        }
388
389
        $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...
390
        if ( ! empty( $new_action ) ) {
391
			$_SERVER['REQUEST_URI'] = str_replace( '&action=' . $new_action, '', FrmAppHelper::get_server_value( 'REQUEST_URI' ) );
392
        }
393
    }
394
395
    /**
396
     * Check the WP query for a parameter
397
     *
398
     * @since 2.0
399
     * @return string|array
400
     */
401
    public static function get_query_var( $value, $param ) {
402
        if ( $value != '' ) {
403
            return $value;
404
        }
405
406
        global $wp_query;
407
        if ( isset( $wp_query->query_vars[ $param ] ) ) {
408
            $value = $wp_query->query_vars[ $param ];
409
        }
410
411
        return $value;
412
    }
413
414
    /**
415
     * @param string $type
416
     */
417
    public static function trigger_hook_load( $type, $object = null ) {
418
        // only load the form hooks once
419
		$hooks_loaded = apply_filters( 'frm_' . $type . '_hooks_loaded', false, $object );
420
        if ( ! $hooks_loaded ) {
421
			do_action( 'frm_load_' . $type . '_hooks' );
422
        }
423
    }
424
425
    /**
426
     * Check cache before fetching values and saving to cache
427
     *
428
     * @since 2.0
429
     *
430
     * @param string $cache_key The unique name for this cache
431
     * @param string $group The name of the cache group
432
     * @param string $query If blank, don't run a db call
433
     * @param string $type The wpdb function to use with this query
434
     * @return mixed $results The cache or query results
435
     */
436
    public static function check_cache( $cache_key, $group = '', $query = '', $type = 'get_var', $time = 300 ) {
437
        $results = wp_cache_get($cache_key, $group);
438
        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...
439
            return $results;
440
        }
441
442
        if ( 'get_posts' == $type ) {
443
            $results = get_posts($query);
444
		} else if ( 'get_associative_results' == $type ) {
445
			global $wpdb;
446
			$results = $wpdb->get_results( $query, OBJECT_K );
447
        } else {
448
            global $wpdb;
449
            $results = $wpdb->{$type}($query);
450
        }
451
452
		self::set_cache( $cache_key, $results, $group, $time );
453
454
		return $results;
455
	}
456
457
	public static function set_cache( $cache_key, $results, $group = '', $time = 300 ) {
458
		if ( ! self::prevent_caching() ) {
459
			self::add_key_to_group_cache( $cache_key, $group );
460
			wp_cache_set( $cache_key, $results, $group, $time );
461
		}
462
	}
463
464
	/**
465
	 * Keep track of the keys cached in each group so they can be deleted
466
	 * in Redis and Memcache
467
	 */
468
	public static function add_key_to_group_cache( $key, $group ) {
469
		$cached = self::get_group_cached_keys( $group );
470
		$cached[ $key ] = $key;
471
		wp_cache_set( 'cached_keys', $cached, $group, 300 );
472
	}
473
474
	public static function get_group_cached_keys( $group ) {
475
		$cached = wp_cache_get( 'cached_keys', $group );
476
		if ( ! $cached || ! is_array( $cached ) ) {
477
			$cached = array();
478
		}
479
480
		return $cached;
481
	}
482
483
    /**
484
     * Data that should be stored for a long time can be stored in a transient.
485
     * First check the cache, then check the transient
486
     * @since 2.0
487
     * @return mixed The cached value or false
488
     */
489
	public static function check_cache_and_transient( $cache_key ) {
490
        // check caching layer first
491
        $results = self::check_cache( $cache_key );
492
        if ( $results ) {
493
            return $results;
494
        }
495
496
        // then check the transient
497
        $results = get_transient($cache_key);
498
        if ( $results ) {
499
            wp_cache_set($cache_key, $results);
500
        }
501
502
        return $results;
503
    }
504
505
    /**
506
     * @since 2.0
507
     * @param string $cache_key
508
     */
509
	public static function delete_cache_and_transient( $cache_key, $group = 'default' ) {
510
		delete_transient($cache_key);
511
		wp_cache_delete( $cache_key, $group );
512
	}
513
514
    /**
515
     * Delete all caching in a single group
516
     *
517
     * @since 2.0
518
     *
519
     * @param string $group The name of the cache group
520
     */
521
	public static function cache_delete_group( $group ) {
522
		$cached_keys = self::get_group_cached_keys( $group );
523
524
		if ( ! empty( $cached_keys ) ) {
525
			foreach ( $cached_keys as $key ) {
526
				wp_cache_delete( $key, $group );
527
			}
528
529
			wp_cache_delete( 'cached_keys', $group );
530
		}
531
	}
532
533
    /**
534
     * Check a value from a shortcode to see if true or false.
535
     * True when value is 1, true, 'true', 'yes'
536
     *
537
     * @since 1.07.10
538
     *
539
     * @param string $value The value to compare
540
     * @return boolean True or False
541
     */
542
	public static function is_true( $value ) {
543
        return ( true === $value || 1 == $value || 'true' == $value || 'yes' == $value );
544
    }
545
546
    /**
547
     * Used to filter shortcode in text widgets
548
     */
549
    public static function widget_text_filter_callback( $matches ) {
550
        return do_shortcode( $matches[0] );
551
    }
552
553
    public static function get_pages() {
554
		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...
555
    }
556
557
    public static function wp_pages_dropdown( $field_name, $page_id, $truncate = false ) {
558
        $pages = self::get_pages();
559
		$selected = self::get_post_param( $field_name, $page_id, 'absint' );
560
    ?>
561
        <select name="<?php echo esc_attr($field_name); ?>" id="<?php echo esc_attr($field_name); ?>" class="frm-pages-dropdown">
562
            <option value=""> </option>
563
            <?php foreach ( $pages as $page ) { ?>
564
				<option value="<?php echo esc_attr($page->ID); ?>" <?php selected( $selected, $page->ID ) ?>>
565
					<?php echo esc_html( $truncate ? self::truncate( $page->post_title, $truncate ) : $page->post_title ); ?>
566
				</option>
567
            <?php } ?>
568
        </select>
569
    <?php
570
    }
571
572
	public static function post_edit_link( $post_id ) {
573
        $post = get_post($post_id);
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
574
        if ( $post ) {
575
			$post_url = admin_url( 'post.php?post=' . $post_id . '&action=edit' );
576
			return '<a href="' . esc_url( $post_url ) . '">' . self::truncate( $post->post_title, 50 ) . '</a>';
577
        }
578
        return '';
579
    }
580
581
	public static function wp_roles_dropdown( $field_name, $capability, $multiple = 'single' ) {
582
    ?>
583
        <select name="<?php echo esc_attr($field_name); ?>" id="<?php echo esc_attr($field_name); ?>" <?php
584
            echo ( 'multiple' == $multiple ) ? 'multiple="multiple"' : '';
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
585
            ?> class="frm_multiselect">
586
            <?php self::roles_options($capability); ?>
587
        </select>
588
    <?php
589
    }
590
591
	public static function roles_options( $capability ) {
592
        global $frm_vars;
593
        if ( isset($frm_vars['editable_roles']) ) {
594
            $editable_roles = $frm_vars['editable_roles'];
595
        } else {
596
            $editable_roles = get_editable_roles();
597
            $frm_vars['editable_roles'] = $editable_roles;
598
        }
599
600
        foreach ( $editable_roles as $role => $details ) {
601
            $name = translate_user_role($details['name'] ); ?>
602
        <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...
603
<?php
604
            unset($role, $details);
605
        }
606
    }
607
608
	public static function frm_capabilities( $type = 'auto' ) {
609
        $cap = array(
610
            'frm_view_forms'        => __( 'View Forms and Templates', 'formidable' ),
611
            'frm_edit_forms'        => __( 'Add/Edit Forms and Templates', 'formidable' ),
612
            'frm_delete_forms'      => __( 'Delete Forms and Templates', 'formidable' ),
613
            'frm_change_settings'   => __( 'Access this Settings Page', 'formidable' ),
614
            'frm_view_entries'      => __( 'View Entries from Admin Area', 'formidable' ),
615
            'frm_delete_entries'    => __( 'Delete Entries from Admin Area', 'formidable' ),
616
        );
617
618
		if ( ! self::pro_is_installed() && 'pro' != $type ) {
619
            return $cap;
620
        }
621
622
        $cap['frm_create_entries'] = __( 'Add Entries from Admin Area', 'formidable' );
623
        $cap['frm_edit_entries'] = __( 'Edit Entries from Admin Area', 'formidable' );
624
        $cap['frm_view_reports'] = __( 'View Reports', 'formidable' );
625
        $cap['frm_edit_displays'] = __( 'Add/Edit Views', 'formidable' );
626
627
        return $cap;
628
    }
629
630
	public static function user_has_permission( $needed_role ) {
631
        if ( $needed_role == '-1' ) {
632
            return false;
633
		}
634
635
        // $needed_role will be equal to blank if "Logged-in users" is selected
636
        if ( ( $needed_role == '' && is_user_logged_in() ) || current_user_can( $needed_role ) ) {
637
            return true;
638
        }
639
640
        $roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
641
        foreach ( $roles as $role ) {
642
			if ( current_user_can( $role ) ) {
643
        		return true;
644
			}
645
        	if ( $role == $needed_role ) {
646
        		break;
647
			}
648
        }
649
        return false;
650
    }
651
652
    /**
653
     * Make sure administrators can see Formidable menu
654
     *
655
     * @since 2.0
656
     */
657
    public static function maybe_add_permissions() {
658
		self::force_capability( 'frm_view_entries' );
659
660
        if ( ! current_user_can('administrator') || current_user_can('frm_view_forms') ) {
661
            return;
662
        }
663
664
		$user_id = get_current_user_id();
665
		$user = new WP_User( $user_id );
666
        $frm_roles = self::frm_capabilities();
667
        foreach ( $frm_roles as $frm_role => $frm_role_description ) {
668
			$user->add_cap( $frm_role );
669
            unset($frm_role, $frm_role_description);
670
        }
671
    }
672
673
	/**
674
	 * Make sure admins have permission to see the menu items
675
	 * @since 2.0.6
676
	 */
677
	public static function force_capability( $cap = 'frm_change_settings' ) {
678
		if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) {
679
			$role = get_role( 'administrator' );
680
			$frm_roles = self::frm_capabilities();
681
			foreach ( $frm_roles as $frm_role => $frm_role_description ) {
682
				$role->add_cap( $frm_role );
683
			}
684
		}
685
	}
686
687
    /**
688
     * Check if the user has permision for action.
689
     * Return permission message and stop the action if no permission
690
     * @since 2.0
691
     * @param string $permission
692
     */
693
	public static function permission_check( $permission, $show_message = 'show' ) {
694
        $permission_error = self::permission_nonce_error($permission);
695
        if ( $permission_error !== false ) {
696
            if ( 'hide' == $show_message ) {
697
                $permission_error = '';
698
            }
699
            wp_die($permission_error);
700
        }
701
    }
702
703
    /**
704
     * Check user permission and nonce
705
     * @since 2.0
706
     * @param string $permission
707
     * @return false|string The permission message or false if allowed
708
     */
709
	public static function permission_nonce_error( $permission, $nonce_name = '', $nonce = '' ) {
710
		if ( ! empty( $permission ) && ! current_user_can( $permission ) && ! current_user_can( 'administrator' ) ) {
711
			$frm_settings = self::get_settings();
712
			return $frm_settings->admin_permission;
713
		}
714
715
		$error = false;
716
        if ( empty($nonce_name) ) {
717
            return $error;
718
        }
719
720
        if ( $_REQUEST && ( ! isset( $_REQUEST[ $nonce_name ] ) || ! wp_verify_nonce( $_REQUEST[ $nonce_name ], $nonce ) ) ) {
721
            $frm_settings = self::get_settings();
722
            $error = $frm_settings->admin_permission;
723
        }
724
725
        return $error;
726
    }
727
728
    public static function checked( $values, $current ) {
729
		if ( self::check_selected( $values, $current ) ) {
730
            echo ' checked="checked"';
731
		}
732
    }
733
734
	public static function check_selected( $values, $current ) {
735
		$values = self::recursive_function_map( $values, 'trim' );
736
		$values = self::recursive_function_map( $values, 'htmlspecialchars_decode' );
737
		$current = htmlspecialchars_decode( trim( $current ) );
738
739
		return ( is_array( $values ) && in_array( $current, $values ) ) || ( ! is_array( $values ) && $values == $current );
740
	}
741
742
    /**
743
    * Check if current field option is an "other" option
744
    *
745
    * @since 2.0
746
    *
747
    * @param string $opt_key
748
    * @return boolean Returns true if current field option is an "Other" option
749
    */
750
    public static function is_other_opt( $opt_key ) {
751
        _deprecated_function( __FUNCTION__, '2.0.6', 'FrmFieldsHelper::is_other_opt' );
752
        return FrmFieldsHelper::is_other_opt( $opt_key );
753
    }
754
755
    /**
756
    * Get value that belongs in "Other" text box
757
    *
758
    * @since 2.0
759
    *
760
    * @param string $opt_key
761
    * @param array $field
762
    * @return string $other_val
763
    */
764
    public static function get_other_val( $opt_key, $field, $parent = false, $pointer = false ) {
765
		_deprecated_function( __FUNCTION__, '2.0.6', 'FrmFieldsHelper::get_other_val' );
766
		return FrmFieldsHelper::get_other_val( compact( 'opt_key', 'field', 'parent', 'pointer' ) );
767
    }
768
769
    /**
770
    * Check if there is a saved value for the "Other" text field. If so, set it as the $other_val.
771
    * Intended for front-end use
772
    *
773
    * @since 2.0
774
    *
775
    * @param array $field
776
    * @param boolean $other_opt
777
    * @param string $checked
778
    * @param array $args should include opt_key and field name
779
    * @return string $other_val
780
    */
781
    public static function prepare_other_input( $field, &$other_opt, &$checked, $args = array() ) {
782
		_deprecated_function( __FUNCTION__, '2.0.6', 'FrmFieldsHelper::prepare_other_input' );
783
		$args['field'] = $field;
784
		return FrmFieldsHelper::prepare_other_input( $args, $other_opt, $checked );
785
    }
786
787
	public static function recursive_function_map( $value, $function ) {
788
		if ( is_array( $value ) ) {
789
			$original_function = $function;
790
			if ( count( $value ) ) {
791
				$function = explode( ', ', self::prepare_array_values( $value, $function ) );
792
			} else {
793
				$function = array( $function );
794
			}
795
			if ( ! self::is_assoc( $value ) ) {
796
				$value = array_map( array( 'FrmAppHelper', 'recursive_function_map' ), $value, $function );
797
			} else {
798
				foreach ( $value as $k => $v ) {
799
					if ( ! is_array( $v ) ) {
800
						$value[ $k ] = call_user_func( $original_function, $v );
801
					}
802
				}
803
			}
804
		} else {
805
			$value = call_user_func( $function, $value );
806
		}
807
808
		return $value;
809
	}
810
811
	public static function is_assoc( $array ) {
812
		return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
813
	}
814
815
    /**
816
     * Flatten a multi-dimensional array
817
     */
818
	public static function array_flatten( $array, $keys = 'keep' ) {
819
        $return = array();
820
        foreach ( $array as $key => $value ) {
821
            if ( is_array($value) ) {
822
				$return = array_merge( $return, self::array_flatten( $value, $keys ) );
823
            } else {
824
				if ( $keys == 'keep' ) {
825
					$return[ $key ] = $value;
826
				} else {
827
					$return[] = $value;
828
				}
829
            }
830
        }
831
        return $return;
832
    }
833
834
	public static function esc_textarea( $text, $is_rich_text = false ) {
835
		$safe_text = str_replace( '&quot;', '"', $text );
836
		if ( ! $is_rich_text ) {
837
			$safe_text = htmlspecialchars( $safe_text, ENT_NOQUOTES );
838
		}
839
		$safe_text = str_replace( '&amp;', '&', $safe_text );
840
		return apply_filters( 'esc_textarea', $safe_text, $text );
841
	}
842
843
    /**
844
     * Add auto paragraphs to text areas
845
     * @since 2.0
846
     */
847
	public static function use_wpautop( $content ) {
848
        if ( apply_filters('frm_use_wpautop', true) ) {
849
            $content = wpautop(str_replace( '<br>', '<br />', $content));
850
        }
851
        return $content;
852
    }
853
854
	public static function replace_quotes( $val ) {
855
        //Replace double quotes
856
		$val = str_replace( array( '&#8220;', '&#8221;', '&#8243;' ), '"', $val );
857
        //Replace single quotes
858
        $val = str_replace( array( '&#8216;', '&#8217;', '&#8242;', '&prime;', '&rsquo;', '&lsquo;' ), "'", $val );
859
        return $val;
860
    }
861
862
    /**
863
     * @since 2.0
864
     * @return string The base Google APIS url for the current version of jQuery UI
865
     */
866
    public static function jquery_ui_base_url() {
867
		$url = 'http' . ( is_ssl() ? 's' : '' ) . '://ajax.googleapis.com/ajax/libs/jqueryui/' . self::script_version( 'jquery-ui-core', '1.11.4' );
868
        $url = apply_filters('frm_jquery_ui_base_url', $url);
869
        return $url;
870
    }
871
872
    /**
873
     * @param string $handle
874
     */
875
	public static function script_version( $handle, $default = 0 ) {
876
		global $wp_scripts;
877
		if ( ! $wp_scripts ) {
878
			return $default;
879
		}
880
881
		$ver = $default;
882
		if ( ! isset( $wp_scripts->registered[ $handle ] ) ) {
883
			return $ver;
884
		}
885
886
		$query = $wp_scripts->registered[ $handle ];
887
		if ( is_object( $query ) && $query->ver !== '' ) {
888
			$ver = $query->ver;
889
		}
890
891
		return $ver;
892
	}
893
894
	public static function js_redirect( $url ) {
895
		return '<script type="text/javascript">window.location="' . esc_url_raw( $url ) . '"</script>';
896
    }
897
898
	public static function get_user_id_param( $user_id ) {
899
        if ( ! $user_id || empty($user_id) || is_numeric($user_id) ) {
900
            return $user_id;
901
        }
902
903
		if ( $user_id == 'current' ) {
904
			$user_id = get_current_user_id();
905
		} else {
906
            if ( is_email($user_id) ) {
907
                $user = get_user_by('email', $user_id);
908
            } else {
909
                $user = get_user_by('login', $user_id);
910
            }
911
912
            if ( $user ) {
913
                $user_id = $user->ID;
914
            }
915
            unset($user);
916
        }
917
918
        return $user_id;
919
    }
920
921
	public static function get_file_contents( $filename, $atts = array() ) {
922
        if ( ! is_file($filename) ) {
923
            return false;
924
        }
925
926
        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...
927
        ob_start();
928
        include($filename);
929
        $contents = ob_get_contents();
930
        ob_end_clean();
931
        return $contents;
932
    }
933
934
    /**
935
     * @param string $table_name
936
     * @param string $column
937
	 * @param int $id
938
	 * @param int $num_chars
939
     */
940
    public static function get_unique_key( $name = '', $table_name, $column, $id = 0, $num_chars = 5 ) {
941
        $key = '';
942
943
        if ( ! empty( $name ) ) {
944
            $key = sanitize_key($name);
945
        }
946
947
		if ( empty( $key ) ) {
948
            $max_slug_value = pow(36, $num_chars);
949
            $min_slug_value = 37; // we want to have at least 2 characters in the slug
950
            $key = base_convert( rand($min_slug_value, $max_slug_value), 10, 36 );
951
        }
952
953
		if ( is_numeric($key) || in_array( $key, array( 'id', 'key', 'created-at', 'detaillink', 'editlink', 'siteurl', 'evenodd' ) ) ) {
954
			$key = $key . 'a';
955
        }
956
957
		$key_check = FrmDb::get_var( $table_name, array( $column => $key, 'ID !' => $id ), $column );
958
959
        if ( $key_check || is_numeric($key_check) ) {
960
            $suffix = 2;
961
			do {
962
				$alt_post_name = substr( $key, 0, 200 - ( strlen( $suffix ) + 1 ) ) . $suffix;
963
				$key_check = FrmDb::get_var( $table_name, array( $column => $alt_post_name, 'ID !' => $id ), $column );
964
				$suffix++;
965
			} while ( $key_check || is_numeric( $key_check ) );
966
			$key = $alt_post_name;
967
        }
968
        return $key;
969
    }
970
971
    /**
972
     * Editing a Form or Entry
973
     * @param string $table
974
     * @return bool|array
975
     */
976
    public static function setup_edit_vars( $record, $table, $fields = '', $default = false, $post_values = array(), $args = array() ) {
977
        if ( ! $record ) {
978
            return false;
979
        }
980
981
        if ( empty($post_values) ) {
982
            $post_values = stripslashes_deep($_POST);
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
983
        }
984
985
		$values = array( 'id' => $record->id, 'fields' => array() );
986
987
		foreach ( array( 'name', 'description' ) as $var ) {
988
            $default_val = isset($record->{$var}) ? $record->{$var} : '';
989
			$values[ $var ] = self::get_param( $var, $default_val, 'get', 'wp_kses_post' );
990
            unset($var, $default_val);
991
        }
992
993
        $values['description'] = self::use_wpautop($values['description']);
994
        $frm_settings = self::get_settings();
995
        $is_form_builder = self::is_admin_page('formidable' );
996
997
        foreach ( (array) $fields as $field ) {
998
            // Make sure to filter default values (for placeholder text), but not on the form builder page
999
            if ( ! $is_form_builder ) {
1000
                $field->default_value = apply_filters('frm_get_default_value', $field->default_value, $field, true );
1001
            }
1002
			$parent_form_id = isset( $args['parent_form_id'] ) ? $args['parent_form_id'] : $field->form_id;
1003
			self::fill_field_defaults($field, $record, $values, compact('default', 'post_values', 'frm_settings', 'parent_form_id' ) );
1004
        }
1005
1006
        self::fill_form_opts($record, $table, $post_values, $values);
1007
1008
        if ( $table == 'entries' ) {
1009
            $values = FrmEntriesHelper::setup_edit_vars( $values, $record );
1010
        } else if ( $table == 'forms' ) {
1011
            $values = FrmFormsHelper::setup_edit_vars( $values, $record, $post_values );
1012
        }
1013
1014
        return $values;
1015
    }
1016
1017
	private static function fill_field_defaults( $field, $record, array &$values, $args ) {
1018
        $post_values = $args['post_values'];
1019
1020
        if ( $args['default'] ) {
1021
            $meta_value = $field->default_value;
1022
        } else {
1023
            if ( $record->post_id && self::pro_is_installed() && isset($field->field_options['post_field']) && $field->field_options['post_field'] ) {
1024
                if ( ! isset($field->field_options['custom_field']) ) {
1025
                    $field->field_options['custom_field'] = '';
1026
                }
1027
				$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 ) );
1028
            } else {
1029
				$meta_value = FrmEntryMeta::get_meta_value( $record, $field->id );
1030
            }
1031
        }
1032
1033
		$field_type = isset( $post_values['field_options'][ 'type_' . $field->id ] ) ? $post_values['field_options'][ 'type_' . $field->id ] : $field->type;
1034
        $new_value = isset( $post_values['item_meta'][ $field->id ] ) ? maybe_unserialize( $post_values['item_meta'][ $field->id ] ) : $meta_value;
1035
1036
        $field_array = array(
1037
            'id'            => $field->id,
1038
            'value'         => $new_value,
1039
            'default_value' => $field->default_value,
1040
            'name'          => $field->name,
1041
            'description'   => $field->description,
1042
            'type'          => apply_filters('frm_field_type', $field_type, $field, $new_value),
1043
            'options'       => $field->options,
1044
            'required'      => $field->required,
1045
            'field_key'     => $field->field_key,
1046
            'field_order'   => $field->field_order,
1047
            'form_id'       => $field->form_id,
1048
			'parent_form_id' => $args['parent_form_id'],
1049
        );
1050
1051
        $args['field_type'] = $field_type;
1052
        self::fill_field_opts($field, $field_array, $args);
1053
		// Track the original field's type
1054
		$field_array['original_type'] = isset( $field->field_options['original_type'] ) ? $field->field_options['original_type'] : $field->type;
1055
1056
        $field_array = apply_filters( 'frm_setup_edit_fields_vars', $field_array, $field, $values['id'], array() );
1057
1058
        if ( ! isset($field_array['unique']) || ! $field_array['unique'] ) {
1059
            $field_array['unique_msg'] = '';
1060
        }
1061
1062
        $field_array = array_merge( $field->field_options, $field_array );
1063
1064
        $values['fields'][ $field->id ] = $field_array;
1065
    }
1066
1067
	private static function fill_field_opts( $field, array &$field_array, $args ) {
1068
        $post_values = $args['post_values'];
1069
        $opt_defaults = FrmFieldsHelper::get_default_field_opts($field_array['type'], $field, true);
1070
1071
        foreach ( $opt_defaults as $opt => $default_opt ) {
1072
			$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 );
1073
            if ( $opt == 'blank' && $field_array[ $opt ] == '' ) {
1074
                $field_array[ $opt ] = $args['frm_settings']->blank_msg;
1075
            } else if ( $opt == 'invalid' && $field_array[ $opt ] == '' ) {
1076
                if ( $args['field_type'] == 'captcha' ) {
1077
                    $field_array[ $opt ] = $args['frm_settings']->re_msg;
1078
                } else {
1079
                    $field_array[ $opt ] = sprintf( __( '%s is invalid', 'formidable' ), $field_array['name'] );
1080
                }
1081
            }
1082
        }
1083
1084
        if ( $field_array['custom_html'] == '' ) {
1085
            $field_array['custom_html'] = FrmFieldsHelper::get_default_html($args['field_type']);
1086
        }
1087
    }
1088
1089
    /**
1090
     * @param string $table
1091
     */
1092
	private static function fill_form_opts( $record, $table, $post_values, array &$values ) {
1093
        if ( $table == 'entries' ) {
1094
            $form = $record->form_id;
1095
			FrmForm::maybe_get_form( $form );
1096
        } else {
1097
            $form = $record;
1098
        }
1099
1100
        if ( ! $form ) {
1101
            return;
1102
        }
1103
1104
        $values['form_name'] = isset($record->form_id) ? $form->name : '';
1105
		$values['parent_form_id'] = isset( $record->form_id ) ? $form->parent_form_id : 0;
1106
1107
        if ( ! is_array($form->options) ) {
1108
            return;
1109
        }
1110
1111
        foreach ( $form->options as $opt => $value ) {
1112
            $values[ $opt ] = isset( $post_values[ $opt ] ) ? maybe_unserialize( $post_values[ $opt ] ) : $value;
1113
        }
1114
1115
        self::fill_form_defaults($post_values, $values);
1116
    }
1117
1118
    /**
1119
     * Set to POST value or default
1120
     */
1121
	private static function fill_form_defaults( $post_values, array &$values ) {
1122
        $form_defaults = FrmFormsHelper::get_default_opts();
1123
1124
        foreach ( $form_defaults as $opt => $default ) {
1125
            if ( ! isset( $values[ $opt ] ) || $values[ $opt ] == '' ) {
1126
				$values[ $opt ] = ( $post_values && isset( $post_values['options'][ $opt ] ) ) ? $post_values['options'][ $opt ] : $default;
1127
            }
1128
1129
            unset($opt, $defaut);
1130
        }
1131
1132
		if ( ! isset( $values['custom_style'] ) ) {
1133
			$values['custom_style'] = self::custom_style_value( $post_values );
1134
		}
1135
1136
		foreach ( array( 'before', 'after', 'submit' ) as $h ) {
1137
			if ( ! isset( $values[ $h . '_html' ] ) ) {
1138
				$values[ $h . '_html' ] = ( isset( $post_values['options'][ $h . '_html' ] ) ? $post_values['options'][ $h . '_html' ] : FrmFormsHelper::get_default_html( $h ) );
1139
            }
1140
            unset($h);
1141
        }
1142
    }
1143
1144
	/**
1145
	 * @since 2.2.10
1146
	 * @param array $post_values
1147
	 * @return boolean|int
1148
	 */
1149
	public static function custom_style_value( $post_values ) {
1150
		if ( ! empty( $post_values ) && isset( $post_values['options']['custom_style'] ) ) {
1151
			$custom_style = absint( $post_values['options']['custom_style'] );
1152
		} else {
1153
			$frm_settings = FrmAppHelper::get_settings();
1154
			$custom_style = ( $frm_settings->load_style != 'none' );
1155
		}
1156
		return $custom_style;
1157
	}
1158
1159
	public static function get_meta_value( $field_id, $entry ) {
1160
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryMeta::get_meta_value' );
1161
		return FrmEntryMeta::get_meta_value( $entry, $field_id );
1162
	}
1163
1164
	public static function insert_opt_html( $args ) {
1165
        $class = '';
1166
        if ( in_array( $args['type'], array( 'email', 'user_id', 'hidden', 'select', 'radio', 'checkbox', 'phone', 'text' ) ) ) {
1167
            $class .= 'show_frm_not_email_to';
1168
        }
1169
    ?>
1170
<li>
1171
    <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>
1172
    <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>
1173
    <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>
1174
</li>
1175
    <?php
1176
    }
1177
1178
	public static function truncate( $str, $length, $minword = 3, $continue = '...' ) {
1179
        if ( is_array( $str ) ) {
1180
            return '';
1181
		}
1182
1183
        $length = (int) $length;
1184
		$str = wp_strip_all_tags( $str );
1185
		$original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) );
1186
1187
		if ( $length == 0 ) {
1188
            return '';
1189
        } else if ( $length <= 10 ) {
1190
			$sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) );
1191
            return $sub . (($length < $original_len) ? $continue : '');
1192
        }
1193
1194
        $sub = '';
1195
        $len = 0;
1196
1197
		$words = self::mb_function( array( 'mb_split', 'explode' ), array( ' ', $str ) );
1198
1199
		foreach ( $words as $word ) {
1200
            $part = (($sub != '') ? ' ' : '') . $word;
1201
			$total_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub . $part ) );
1202
            if ( $total_len > $length && str_word_count($sub) ) {
1203
                break;
1204
            }
1205
1206
            $sub .= $part;
1207
			$len += self::mb_function( array( 'mb_strlen', 'strlen' ), array( $part ) );
1208
1209
            if ( str_word_count($sub) > $minword && $total_len >= $length ) {
1210
                break;
1211
            }
1212
1213
            unset($total_len, $word);
1214
        }
1215
1216
        return $sub . (($len < $original_len) ? $continue : '');
1217
    }
1218
1219
	public static function mb_function( $function_names, $args ) {
1220
		$mb_function_name = $function_names[0];
1221
		$function_name = $function_names[1];
1222
		if ( function_exists( $mb_function_name ) ) {
1223
			$function_name = $mb_function_name;
1224
		}
1225
		return call_user_func_array( $function_name, $args );
1226
	}
1227
1228
	public static function get_formatted_time( $date, $date_format = '', $time_format = '' ) {
1229
        if ( empty($date) ) {
1230
            return $date;
1231
        }
1232
1233
        if ( empty($date_format) ) {
1234
            $date_format = get_option('date_format');
1235
        }
1236
1237
        if ( preg_match('/^\d{1-2}\/\d{1-2}\/\d{4}$/', $date) && self::pro_is_installed() ) {
1238
            $frmpro_settings = new FrmProSettings();
1239
            $date = FrmProAppHelper::convert_date($date, $frmpro_settings->date_format, 'Y-m-d');
1240
        }
1241
1242
		$formatted = self::get_localized_date( $date_format, $date );
1243
1244
		$do_time = ( date( 'H:i:s', strtotime( $date ) ) != '00:00:00' );
1245
		if ( $do_time ) {
1246
			$formatted .= self::add_time_to_date( $time_format, $date );
1247
		}
1248
1249
        return $formatted;
1250
    }
1251
1252
	private static function add_time_to_date( $time_format, $date ) {
1253
		if ( empty( $time_format ) ) {
1254
			$time_format = get_option('time_format');
1255
		}
1256
1257
		$trimmed_format = trim( $time_format );
1258
		$time = '';
1259
		if ( $time_format && ! empty( $trimmed_format ) ) {
1260
			$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...
1261
		}
1262
1263
		return $time;
1264
	}
1265
1266
	/**
1267
	 * @since 2.0.8
1268
	 */
1269
	public static function get_localized_date( $date_format, $date ) {
1270
		$date = get_date_from_gmt( $date );
1271
		return date_i18n( $date_format, strtotime( $date ) );
1272
	}
1273
1274
	/**
1275
	 * Gets the time ago in words
1276
	 *
1277
	 * @param int $from in seconds
1278
	 * @param int|string $to in seconds
1279
	 * @return string $time_ago
1280
	 */
1281
	public static function human_time_diff( $from, $to = '', $levels = 1 ) {
1282
		if ( empty( $to ) ) {
1283
			$now = new DateTime;
1284
		} else {
1285
			$now = new DateTime( '@' . $to );
1286
		}
1287
		$ago = new DateTime( '@' . $from );
1288
1289
		// Get the time difference
1290
		$diff_object = $now->diff( $ago );
1291
		$diff = get_object_vars( $diff_object );
1292
1293
		// Add week amount and update day amount
1294
		$diff['w'] = floor( $diff['d'] / 7 );
1295
		$diff['d'] -= $diff['w'] * 7;
1296
1297
		$time_strings = self::get_time_strings();
1298
1299
		foreach ( $time_strings as $k => $v ) {
1300
			if ( $diff[ $k ] ) {
1301
				$time_strings[ $k ] = $diff[ $k ] . ' ' . ( $diff[ $k ] > 1 ? $v[1] : $v[0] );
1302
			} else {
1303
				unset( $time_strings[ $k ] );
1304
			}
1305
		}
1306
1307
		$levels_deep = apply_filters( 'frm_time_ago_levels', $levels, compact( 'time_strings', 'from', 'to' ) );
1308
		$time_strings = array_slice( $time_strings, 0, $levels_deep );
1309
		$time_ago_string = $time_strings ? implode( ' ', $time_strings ) : '0 ' . __( 'seconds', 'formidable' );
1310
1311
		return $time_ago_string;
1312
	}
1313
1314
	/**
1315
	 * Get the translatable time strings
1316
	 *
1317
	 * @since 2.0.20
1318
	 * @return array
1319
	 */
1320
	private static function get_time_strings() {
1321
		return array(
1322
			'y' => array( __( 'year', 'formidable' ), __( 'years', 'formidable' ) ),
1323
			'm' => array( __( 'month', 'formidable' ), __( 'months', 'formidable' ) ),
1324
			'w' => array( __( 'week', 'formidable' ), __( 'weeks', 'formidable' ) ),
1325
			'd' => array( __( 'day', 'formidable' ), __( 'days', 'formidable' ) ),
1326
			'h' => array( __( 'hour', 'formidable' ), __( 'hours', 'formidable' ) ),
1327
			'i' => array( __( 'minute', 'formidable' ), __( 'minutes', 'formidable' ) ),
1328
			's' => array( __( 'second', 'formidable' ), __( 'seconds', 'formidable' ) ),
1329
		);
1330
	}
1331
1332
    /**
1333
     * Added for < WP 4.0 compatability
1334
     *
1335
     * @since 1.07.10
1336
     *
1337
     * @param string $term The value to escape
1338
     * @return string The escaped value
1339
     */
1340
	public static function esc_like( $term ) {
1341
        global $wpdb;
1342
        if ( method_exists($wpdb, 'esc_like') ) {
1343
			// WP 4.0
1344
            $term = $wpdb->esc_like( $term );
1345
        } else {
1346
            $term = like_escape( $term );
1347
        }
1348
1349
        return $term;
1350
    }
1351
1352
    /**
1353
     * @param string $order_query
1354
     */
1355
	public static function esc_order( $order_query ) {
1356
        if ( empty($order_query) ) {
1357
            return '';
1358
        }
1359
1360
        // remove ORDER BY before santizing
1361
        $order_query = strtolower($order_query);
1362
        if ( strpos($order_query, 'order by') !== false ) {
1363
            $order_query = str_replace('order by', '', $order_query);
1364
        }
1365
1366
        $order_query = explode(' ', trim($order_query));
1367
1368
        $order_fields = array(
1369
            'id', 'form_key', 'name', 'description',
1370
            'parent_form_id', 'logged_in', 'is_template',
1371
            'default_template', 'status', 'created_at',
1372
        );
1373
1374
        $order = trim(trim(reset($order_query), ','));
1375
        if ( ! in_array($order, $order_fields) ) {
1376
            return '';
1377
        }
1378
1379
        $order_by = '';
1380
        if ( count($order_query) > 1 ) {
1381
			$order_by = end( $order_query );
1382
			self::esc_order_by( $order_by );
1383
        }
1384
1385
		return ' ORDER BY ' . $order . ' ' . $order_by;
1386
    }
1387
1388
	/**
1389
	 * Make sure this is ordering by either ASC or DESC
1390
	 */
1391
	public static function esc_order_by( &$order_by ) {
1392
		$sort_options = array( 'asc', 'desc' );
1393
		if ( ! in_array( strtolower( $order_by ), $sort_options ) ) {
1394
			$order_by = 'asc';
1395
		}
1396
	}
1397
1398
    /**
1399
     * @param string $limit
1400
     */
1401
	public static function esc_limit( $limit ) {
1402
        if ( empty($limit) ) {
1403
            return '';
1404
        }
1405
1406
        $limit = trim(str_replace(' limit', '', strtolower($limit)));
1407
        if ( is_numeric($limit) ) {
1408
			return ' LIMIT ' . $limit;
1409
        }
1410
1411
        $limit = explode(',', trim($limit));
1412
        foreach ( $limit as $k => $l ) {
1413
            if ( is_numeric( $l ) ) {
1414
                $limit[ $k ] = $l;
1415
            }
1416
        }
1417
1418
        $limit = implode(',', $limit);
1419
		return ' LIMIT ' . $limit;
1420
    }
1421
1422
    /**
1423
     * Get an array of values ready to go through $wpdb->prepare
1424
     * @since 2.0
1425
     */
1426
    public static function prepare_array_values( $array, $type = '%s' ) {
1427
        $placeholders = array_fill(0, count($array), $type);
1428
        return implode(', ', $placeholders);
1429
    }
1430
1431
    public static function prepend_and_or_where( $starts_with = ' WHERE ', $where = '' ) {
1432
        if ( empty($where) ) {
1433
            return '';
1434
        }
1435
1436
		if ( is_array( $where ) ) {
1437
            global $wpdb;
1438
            FrmDb::get_where_clause_and_values( $where, $starts_with );
1439
			$where = $wpdb->prepare( $where['where'], $where['values'] );
1440
		} else {
1441
            $where = $starts_with . $where;
1442
        }
1443
1444
        return $where;
1445
    }
1446
1447
    // Pagination Methods
1448
1449
    /**
1450
     * @param integer $current_p
1451
     */
1452
	public static function get_last_record_num( $r_count, $current_p, $p_size ) {
1453
		return ( ( $r_count < ( $current_p * $p_size ) ) ? $r_count : ( $current_p * $p_size ) );
1454
	}
1455
1456
    /**
1457
     * @param integer $current_p
1458
     */
1459
    public static function get_first_record_num( $r_count, $current_p, $p_size ) {
1460
        if ( $current_p == 1 ) {
1461
            return 1;
1462
        } else {
1463
            return ( self::get_last_record_num( $r_count, ( $current_p - 1 ), $p_size ) + 1 );
1464
        }
1465
    }
1466
1467
	/**
1468
	 * @return array
1469
	 */
1470
	public static function json_to_array( $json_vars ) {
1471
        $vars = array();
1472
        foreach ( $json_vars as $jv ) {
1473
            $jv_name = explode('[', $jv['name']);
1474
            $last = count($jv_name) - 1;
1475
            foreach ( $jv_name as $p => $n ) {
1476
                $name = trim($n, ']');
1477
                if ( ! isset($l1) ) {
1478
                    $l1 = $name;
1479
                }
1480
1481
                if ( ! isset($l2) ) {
1482
                    $l2 = $name;
1483
                }
1484
1485
                if ( ! isset($l3) ) {
1486
                    $l3 = $name;
1487
                }
1488
1489
                $this_val = ( $p == $last ) ? $jv['value'] : array();
1490
1491
                switch ( $p ) {
1492
                    case 0:
1493
                        $l1 = $name;
1494
                        self::add_value_to_array( $name, $l1, $this_val, $vars );
1495
                    break;
1496
1497
                    case 1:
1498
                        $l2 = $name;
1499
                        self::add_value_to_array( $name, $l2, $this_val, $vars[ $l1 ] );
1500
                    break;
1501
1502 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...
1503
                        $l3 = $name;
1504
                        self::add_value_to_array( $name, $l3, $this_val, $vars[ $l1 ][ $l2 ] );
1505
                    break;
1506
1507 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...
1508
                        $l4 = $name;
1509
                        self::add_value_to_array( $name, $l4, $this_val, $vars[ $l1 ][ $l2 ][ $l3 ] );
1510
                    break;
1511
                }
1512
1513
                unset($this_val, $n);
1514
            }
1515
1516
            unset($last, $jv);
1517
        }
1518
1519
        return $vars;
1520
    }
1521
1522
    /**
1523
     * @param string $name
1524
     * @param string $l1
1525
     */
1526
    public static function add_value_to_array( $name, $l1, $val, &$vars ) {
1527
        if ( $name == '' ) {
1528
            $vars[] = $val;
1529
        } else if ( ! isset( $vars[ $l1 ] ) ) {
1530
            $vars[ $l1 ] = $val;
1531
        }
1532
    }
1533
1534
	public static function maybe_add_tooltip( $name, $class = 'closed', $form_name = '' ) {
1535
        $tooltips = array(
1536
            'action_title'  => __( 'Give this action a label for easy reference.', 'formidable' ),
1537
            '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' ),
1538
            'cc'            => __( 'Add CC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
1539
            'bcc'           => __( 'Add BCC addresses separated by a ",".  FORMAT: Name <[email protected]> or [email protected].', 'formidable' ),
1540
            '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' ),
1541
            'from'          => __( 'Enter the name and/or email address of the sender. FORMAT: John Bates <[email protected]> or [email protected].', 'formidable' ),
1542
            '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() ) ),
1543
        );
1544
1545
        if ( ! isset( $tooltips[ $name ] ) ) {
1546
            return;
1547
        }
1548
1549
        if ( 'open' == $class ) {
1550
            echo ' frm_help"';
1551
        } else {
1552
            echo ' class="frm_help"';
1553
        }
1554
1555
		echo ' title="' . esc_attr( $tooltips[ $name ] );
1556
1557
        if ( 'open' != $class ) {
1558
            echo '"';
1559
        }
1560
    }
1561
1562
	/**
1563
	 * Add the current_page class to that page in the form nav
1564
	 */
1565
	public static function select_current_page( $page, $current_page, $action = array() ) {
1566
		if ( $current_page != $page ) {
1567
			return;
1568
		}
1569
1570
		$frm_action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
1571
		if ( empty( $action ) || ( ! empty( $frm_action ) && in_array( $frm_action, $action ) ) ) {
1572
			echo ' class="current_page"';
1573
		}
1574
	}
1575
1576
    /**
1577
     * Prepare and json_encode post content
1578
     *
1579
     * @since 2.0
1580
     *
1581
     * @param array $post_content
1582
     * @return string $post_content ( json encoded array )
1583
     */
1584
    public static function prepare_and_encode( $post_content ) {
1585
        //Loop through array to strip slashes and add only the needed ones
1586
		foreach ( $post_content as $key => $val ) {
1587
			// Replace problematic characters (like &quot;)
1588
			$val = str_replace( '&quot;', '"', $val );
1589
1590
			self::prepare_action_slashes( $val, $key, $post_content );
1591
            unset( $key, $val );
1592
        }
1593
1594
        // json_encode the array
1595
        $post_content = json_encode( $post_content );
1596
1597
	    // add extra slashes for \r\n since WP strips them
1598
		$post_content = str_replace( array( '\\r', '\\n', '\\u', '\\t' ), array( '\\\\r', '\\\\n', '\\\\u', '\\\\t' ), $post_content );
1599
1600
        // allow for &quot
1601
	    $post_content = str_replace( '&quot;', '\\"', $post_content );
1602
1603
        return $post_content;
1604
    }
1605
1606
	private static function prepare_action_slashes( $val, $key, &$post_content ) {
1607
		if ( ! isset( $post_content[ $key ] ) ) {
1608
			return;
1609
		}
1610
1611
		if ( is_array( $val ) ) {
1612
			foreach ( $val as $k1 => $v1 ) {
1613
				self::prepare_action_slashes( $v1, $k1, $post_content[ $key ] );
1614
				unset( $k1, $v1 );
1615
			}
1616
		} else {
1617
			// Strip all slashes so everything is the same, no matter where the value is coming from
1618
			$val = stripslashes( $val );
1619
1620
			// Add backslashes before double quotes and forward slashes only
1621
			$post_content[ $key ] = addcslashes( $val, '"\\/' );
1622
		}
1623
	}
1624
1625
	/**
1626
	 * Prepare and save settings in styles and actions
1627
	 *
1628
	 * @param array $settings
1629
	 * @param string $group
1630
	 *
1631
	 * @since 2.0.6
1632
	 */
1633
	public static function save_settings( $settings, $group ) {
1634
		$settings = (array) $settings;
1635
		$settings['post_content'] = FrmAppHelper::prepare_and_encode( $settings['post_content'] );
1636
1637
		if ( empty( $settings['ID'] ) ) {
1638
			unset( $settings['ID']);
1639
		}
1640
1641
		// delete all caches for this group
1642
		self::cache_delete_group( $group );
1643
1644
		return self::save_json_post( $settings );
1645
	}
1646
1647
	/**
1648
	 * Since actions are JSON encoded, we don't want any filters messing with it.
1649
	 * Remove the filters and then add them back in case any posts or views are
1650
	 * also being imported.
1651
	 *
1652
	 * Used when saving form actions and styles
1653
	 *
1654
	 * @since 2.0.4
1655
	 */
1656
	public static function save_json_post( $settings ) {
1657
		global $wp_filter;
1658
		$filters = $wp_filter['content_save_pre'];
1659
1660
		// Remove the balanceTags filter in case WordPress is trying to validate the XHTML
1661
		remove_all_filters( 'content_save_pre' );
1662
1663
		$post = wp_insert_post( $settings );
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
1664
1665
		// add the content filters back for views or posts
1666
		$wp_filter['content_save_pre'] = $filters;
1667
1668
		return $post;
1669
	}
1670
1671
	public static function maybe_json_decode( $string ) {
1672
        if ( is_array($string) ) {
1673
            return $string;
1674
        }
1675
1676
        $new_string = json_decode($string, true);
1677
        if ( function_exists('json_last_error') ) {
1678
			// php 5.3+
1679
            if ( json_last_error() == JSON_ERROR_NONE ) {
1680
                $string = $new_string;
1681
            }
1682
        } else if ( isset($new_string) ) {
1683
			// php < 5.3 fallback
1684
            $string = $new_string;
1685
        }
1686
        return $string;
1687
    }
1688
1689
    /**
1690
     * @since 1.07.10
1691
     *
1692
     * @param string $post_type The name of the post type that may need to be highlighted
1693
     * echo The javascript to open and highlight the Formidable menu
1694
     */
1695
	public static function maybe_highlight_menu( $post_type ) {
1696
        global $post;
1697
1698
        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...
1699
            return;
1700
        }
1701
1702
        if ( is_object($post) && $post->post_type != $post_type ) {
1703
            return;
1704
        }
1705
1706
        self::load_admin_wide_js();
1707
        echo '<script type="text/javascript">jQuery(document).ready(function(){frmSelectSubnav();});</script>';
1708
    }
1709
1710
    /**
1711
     * Load the JS file on non-Formidable pages in the admin area
1712
     * @since 2.0
1713
     */
1714
	public static function load_admin_wide_js( $load = true ) {
1715
        $version = FrmAppHelper::plugin_version();
1716
		wp_register_script( 'formidable_admin_global', FrmAppHelper::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version );
1717
1718
        wp_localize_script( 'formidable_admin_global', 'frmGlobal', array(
1719
			'updating_msg' => __( 'Please wait while your site updates.', 'formidable' ),
1720
            'deauthorize'  => __( 'Are you sure you want to deauthorize Formidable Forms on this site?', 'formidable' ),
1721
			'url'          => FrmAppHelper::plugin_url(),
1722
			'loading'      => __( 'Loading&hellip;' ),
1723
			'nonce'        => wp_create_nonce( 'frm_ajax' ),
1724
        ) );
1725
1726
		if ( $load ) {
1727
			wp_enqueue_script( 'formidable_admin_global' );
1728
		}
1729
    }
1730
1731
	/**
1732
	 * @since 2.0.9
1733
	 */
1734
	public static function load_font_style() {
1735
		wp_enqueue_style( 'frm_fonts', self::plugin_url() . '/css/frm_fonts.css', array(), self::plugin_version() );
1736
	}
1737
1738
    /**
1739
     * @param string $location
1740
     */
1741
	public static function localize_script( $location ) {
1742
		$ajax_url = admin_url( 'admin-ajax.php', is_ssl() ? 'admin' : 'http' );
1743
		$ajax_url = apply_filters( 'frm_ajax_url', $ajax_url );
1744
1745
		wp_localize_script( 'formidable', 'frm_js', array(
1746
			'ajax_url'  => $ajax_url,
1747
			'images_url' => self::plugin_url() . '/images',
1748
			'loading'   => __( 'Loading&hellip;' ),
1749
			'remove'    => __( 'Remove', 'formidable' ),
1750
			'offset'    => apply_filters( 'frm_scroll_offset', 4 ),
1751
			'nonce'     => wp_create_nonce( 'frm_ajax' ),
1752
			'id'        => __( 'ID', 'formidable' ),
1753
			'no_results' => __( 'No results match', 'formidable' ),
1754
		) );
1755
1756
		if ( $location == 'admin' ) {
1757
			$frm_settings = self::get_settings();
1758
			wp_localize_script( 'formidable_admin', 'frm_admin_js', array(
1759
				'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' ),
1760
				'desc'              => __( '(Click to add description)', 'formidable' ),
1761
				'blank'             => __( '(Blank)', 'formidable' ),
1762
				'no_label'          => __( '(no label)', 'formidable' ),
1763
				'saving'            => esc_attr( __( 'Saving', 'formidable' ) ),
1764
				'saved'             => esc_attr( __( 'Saved', 'formidable' ) ),
1765
				'ok'                => __( 'OK' ),
1766
				'cancel'            => __( 'Cancel', 'formidable' ),
1767
				'default'           => __( 'Default', 'formidable' ),
1768
				'clear_default'     => __( 'Clear default value when typing', 'formidable' ),
1769
				'no_clear_default'  => __( 'Do not clear default value when typing', 'formidable' ),
1770
				'valid_default'     => __( 'Default value will pass form validation', 'formidable' ),
1771
				'no_valid_default'  => __( 'Default value will NOT pass form validation', 'formidable' ),
1772
				'confirm'           => __( 'Are you sure?', 'formidable' ),
1773
				'conf_delete'       => __( 'Are you sure you want to delete this field and all data associated with it?', 'formidable' ),
1774
				'conf_delete_sec'   => __( 'WARNING: This will delete all fields inside of the section as well.', 'formidable' ),
1775
				'conf_no_repeat'    => __( 'Warning: If you have entries with multiple rows, all but the first row will be lost.', 'formidable' ),
1776
				'default_unique'    => $frm_settings->unique_msg,
1777
				'default_conf'      => __( 'The entered values do not match', 'formidable' ),
1778
				'enter_email'       => __( 'Enter Email', 'formidable' ),
1779
				'confirm_email'     => __( 'Confirm Email', 'formidable' ),
1780
				'css_invalid_size'  => __( 'In certain browsers (e.g. Firefox) text will not display correctly if the field height is too small relative to the field padding and text size. Please increase your field height or decrease your field padding.', 'formidable' ),
1781
				'enter_password'    => __( 'Enter Password', 'formidable' ),
1782
				'confirm_password'  => __( 'Confirm Password', 'formidable' ),
1783
				'import_complete'   => __( 'Import Complete', 'formidable' ),
1784
				'updating'          => __( 'Please wait while your site updates.', 'formidable' ),
1785
				'no_save_warning'   => __( 'Warning: There is no way to retrieve unsaved entries.', 'formidable' ),
1786
				'private'           => __( 'Private' ),
1787
				'jquery_ui_url'     => self::jquery_ui_base_url(),
1788
				'no_licenses'       => __( 'No new licenses were found', 'formidable' ),
1789
			) );
1790
		}
1791
	}
1792
1793
    /**
1794
	 * echo the message on the plugins listing page
1795
     * @since 1.07.10
1796
     *
1797
     * @param float $min_version The version the add-on requires
1798
     */
1799
	public static function min_version_notice( $min_version ) {
1800
        $frm_version = self::plugin_version();
1801
1802
        // check if Formidable meets minimum requirements
1803
        if ( version_compare($frm_version, $min_version, '>=') ) {
1804
            return;
1805
        }
1806
1807
        $wp_list_table = _get_list_table('WP_Plugins_List_Table');
1808
		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">' .
1809
        __( '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...
1810
        '</div></td></tr>';
1811
    }
1812
1813
    public static function locales( $type = 'date' ) {
1814
        $locales = array(
1815
            'en' => __( 'English', 'formidable' ),    '' => __( 'English/Western', 'formidable' ),
1816
            'af' => __( 'Afrikaans', 'formidable' ),  'sq' => __( 'Albanian', 'formidable' ),
1817
            'ar' => __( 'Arabic', 'formidable' ),     'hy' => __( 'Armenian', 'formidable' ),
1818
            'az' => __( 'Azerbaijani', 'formidable' ), 'eu' => __( 'Basque', 'formidable' ),
1819
            'bs' => __( 'Bosnian', 'formidable' ),    'bg' => __( 'Bulgarian', 'formidable' ),
1820
            'ca' => __( 'Catalan', 'formidable' ),    'zh-HK' => __( 'Chinese Hong Kong', 'formidable' ),
1821
            'zh-CN' => __( 'Chinese Simplified', 'formidable' ), 'zh-TW' => __( 'Chinese Traditional', 'formidable' ),
1822
            'hr' => __( 'Croatian', 'formidable' ),   'cs' => __( 'Czech', 'formidable' ),
1823
            'da' => __( 'Danish', 'formidable' ),     'nl' => __( 'Dutch', 'formidable' ),
1824
            'en-GB' => __( 'English/UK', 'formidable' ), 'eo' => __( 'Esperanto', 'formidable' ),
1825
            'et' => __( 'Estonian', 'formidable' ),   'fo' => __( 'Faroese', 'formidable' ),
1826
            'fa' => __( 'Farsi/Persian', 'formidable' ), 'fil' => __( 'Filipino', 'formidable' ),
1827
            'fi' => __( 'Finnish', 'formidable' ),    'fr' => __( 'French', 'formidable' ),
1828
            'fr-CA' => __( 'French/Canadian', 'formidable' ), 'fr-CH' => __( 'French/Swiss', 'formidable' ),
1829
            'de' => __( 'German', 'formidable' ),     'de-AT' => __( 'German/Austria', 'formidable' ),
1830
            'de-CH' => __( 'German/Switzerland', 'formidable' ), 'el' => __( 'Greek', 'formidable' ),
1831
            'he' => __( 'Hebrew', 'formidable' ),     'iw' => __( 'Hebrew', 'formidable' ),
1832
            'hi' => __( 'Hindi', 'formidable' ),      'hu' => __( 'Hungarian', 'formidable' ),
1833
            'is' => __( 'Icelandic', 'formidable' ),  'id' => __( 'Indonesian', 'formidable' ),
1834
            'it' => __( 'Italian', 'formidable' ),    'ja' => __( 'Japanese', 'formidable' ),
1835
            'ko' => __( 'Korean', 'formidable' ),     'lv' => __( 'Latvian', 'formidable' ),
1836
            'lt' => __( 'Lithuanian', 'formidable' ), 'ms' => __( 'Malaysian', 'formidable' ),
1837
            'no' => __( 'Norwegian', 'formidable' ),  'pl' => __( 'Polish', 'formidable' ),
1838
            'pt' => __( 'Portuguese', 'formidable' ), 'pt-BR' => __( 'Portuguese/Brazilian', 'formidable' ),
1839
            'pt-PT' => __( 'Portuguese/Portugal', 'formidable' ), 'ro' => __( 'Romanian', 'formidable' ),
1840
            'ru' => __( 'Russian', 'formidable' ),    'sr' => __( 'Serbian', 'formidable' ),
1841
            'sr-SR' => __( 'Serbian', 'formidable' ), 'sk' => __( 'Slovak', 'formidable' ),
1842
            'sl' => __( 'Slovenian', 'formidable' ),  'es' => __( 'Spanish', 'formidable' ),
1843
            'es-419' => __( 'Spanish/Latin America', 'formidable' ), 'sv' => __( 'Swedish', 'formidable' ),
1844
            'ta' => __( 'Tamil', 'formidable' ),      'th' => __( 'Thai', 'formidable' ),
1845
            'tu' => __( 'Turkish', 'formidable' ),    'tr' => __( 'Turkish', 'formidable' ),
1846
            'uk' => __( 'Ukranian', 'formidable' ),   'vi' => __( 'Vietnamese', 'formidable' ),
1847
        );
1848
1849
        if ( $type == 'captcha' ) {
1850
            // remove the languages unavailable for the captcha
1851
            $unset = array(
1852
                '', 'af', 'sq', 'hy', 'az', 'eu', 'bs',
1853
                'zh-HK', 'eo', 'et', 'fo', 'fr-CH',
1854
                'he', 'is', 'ms', 'sr-SR', 'ta', 'tu',
1855
            );
1856
        } else {
1857
            // remove the languages unavailable for the datepicker
1858
            $unset = array(
1859
                'en', 'fil', 'fr-CA', 'de-AT', 'de-AT',
1860
                'de-CH', 'iw', 'hi', 'pt', 'pt-PT',
1861
                'es-419', 'tr',
1862
            );
1863
        }
1864
1865
        $locales = array_diff_key($locales, array_flip($unset));
1866
        $locales = apply_filters('frm_locales', $locales);
1867
1868
        return $locales;
1869
    }
1870
}
1871