Completed
Push — master ( 078d82...c7b9e4 )
by Stephanie
02:38
created

FrmAppHelper::check_cache_and_transient()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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