Completed
Push — master ( 34a52e...661e23 )
by Stephanie
04:47
created

FrmAppHelper::check_cache()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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