Completed
Push — master ( 532a71...8861ff )
by Jamie
03:25
created

FrmAppHelper::site_url()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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