Completed
Push — master ( cbe6b2...d6428c )
by Jamie
03:34
created

FrmField::get_id_by_key()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
if ( ! defined('ABSPATH') ) {
3
	die( 'You are not allowed to call this page directly.' );
4
}
5
6
class FrmField {
7
    static $use_cache = true;
8
	static $transient_size = 200;
9
10
	public static function field_selection() {
11
		$fields = apply_filters('frm_available_fields', array(
12
			'text'      => __( 'Single Line Text', 'formidable' ),
13
			'textarea'  => __( 'Paragraph Text', 'formidable' ),
14
			'checkbox'  => __( 'Checkboxes', 'formidable' ),
15
			'radio'     => __( 'Radio Buttons', 'formidable' ),
16
			'select'    => __( 'Dropdown', 'formidable' ),
17
			'email'     => __( 'Email Address', 'formidable' ),
18
			'url'       => __( 'Website/URL', 'formidable' ),
19
			'captcha'   => __( 'reCAPTCHA', 'formidable' ),
20
		));
21
22
		return $fields;
23
	}
24
25
	public static function pro_field_selection() {
26
		return apply_filters('frm_pro_available_fields', array(
27
			'end_divider' => array(
28
				'name'  => __( 'End Section', 'formidable' ),
29
				'switch_from' => 'divider',
30
			),
31
			'divider'   => __( 'Section', 'formidable' ),
32
			'break'     => __( 'Page Break', 'formidable' ),
33
			'file'      => __( 'File Upload', 'formidable' ),
34
			'rte'       => __( 'Rich Text', 'formidable' ),
35
			'number'    => __( 'Number', 'formidable' ),
36
			'phone'     => __( 'Phone Number', 'formidable' ),
37
			'date'      => __( 'Date', 'formidable' ),
38
			'time'      => __( 'Time', 'formidable' ),
39
			'image'     => __( 'Image URL', 'formidable' ),
40
			'scale'     => __( 'Scale', 'formidable' ),
41
			'data'      => __( 'Dynamic Field', 'formidable' ),
42
			'lookup'	=> __( 'Lookup', 'formidable' ),
43
			'form'      => __( 'Embed Form', 'formidable' ),
44
			'hidden'    => __( 'Hidden Field', 'formidable' ),
45
			'user_id'   => __( 'User ID (hidden)', 'formidable' ),
46
			'password'  => __( 'Password', 'formidable' ),
47
			'html'      => __( 'HTML', 'formidable' ),
48
			'tag'       => __( 'Tags', 'formidable' ),
49
			'credit_card' => __( 'Credit Card', 'formidable' ),
50
			'address'   => __( 'Address', 'formidable' ),
51
		));
52
	}
53
54
    public static function create( $values, $return = true ) {
55
        global $wpdb, $frm_duplicate_ids;
56
57
        $new_values = array();
58
        $key = isset($values['field_key']) ? $values['field_key'] : $values['name'];
59
		$new_values['field_key'] = FrmAppHelper::get_unique_key( $key, $wpdb->prefix . 'frm_fields', 'field_key' );
60
61
		foreach ( array( 'name', 'description', 'type', 'default_value' ) as $col ) {
62
			$new_values[ $col ] = $values[ $col ];
63
        }
64
65
        $new_values['options'] = $values['options'];
66
67
        $new_values['field_order'] = isset($values['field_order']) ? (int) $values['field_order'] : null;
68
        $new_values['required'] = isset($values['required']) ? (int) $values['required'] : 0;
69
        $new_values['form_id'] = isset($values['form_id']) ? (int) $values['form_id'] : null;
70
        $new_values['field_options'] = $values['field_options'];
71
        $new_values['created_at'] = current_time('mysql', 1);
72
73
		if ( isset( $values['id'] ) ) {
74
			$frm_duplicate_ids[ $values['field_key'] ] = $new_values['field_key'];
75
            $new_values = apply_filters('frm_duplicated_field', $new_values);
76
        }
77
78
		foreach ( $new_values as $k => $v ) {
79
            if ( is_array( $v ) ) {
80
				$new_values[ $k ] = serialize( $v );
81
			}
82
            unset( $k, $v );
83
        }
84
85
        //if(isset($values['id']) and is_numeric($values['id']))
86
        //    $new_values['id'] = $values['id'];
87
88
		$query_results = $wpdb->insert( $wpdb->prefix . 'frm_fields', $new_values );
89
		$new_id = 0;
90
		if ( $query_results ) {
91
			self::delete_form_transient( $new_values['form_id'] );
92
			$new_id = $wpdb->insert_id;
93
		}
94
95
		if ( ! $return ) {
96
			return;
97
		}
98
99
		if ( $query_results ) {
100
			if ( isset( $values['id'] ) ) {
101
				$frm_duplicate_ids[ $values['id'] ] = $new_id;
102
			}
103
			return $new_id;
104
		} else {
105
			return false;
106
		}
107
    }
108
109
    public static function duplicate( $old_form_id, $form_id, $copy_keys = false, $blog_id = false ) {
110
        global $frm_duplicate_ids;
111
112
		$where = array( array( 'or' => 1, 'fi.form_id' => $old_form_id, 'fr.parent_form_id' => $old_form_id ) );
113
		$fields = self::getAll( $where, 'field_order', '', $blog_id );
114
115
        foreach ( (array) $fields as $field ) {
116
            $new_key = ($copy_keys) ? $field->field_key : '';
117
            if ( $copy_keys && substr($field->field_key, -1) == 2 ) {
118
                $new_key = rtrim($new_key, 2);
119
            }
120
121
            $values = array();
122
            FrmFieldsHelper::fill_field( $values, $field, $form_id, $new_key );
123
124
			// If this is a repeating section, create new form
125
			if ( self::is_repeating_field( $field ) ) {
126
				// create the repeatable form
127
				$new_repeat_form_id = apply_filters( 'frm_create_repeat_form', 0, array( 'parent_form_id' => $form_id, 'field_name' => $field->name ) );
128
129
				// Save old form_select
130
				$old_repeat_form_id = $field->field_options['form_select'];
131
132
				// Update form_select for repeating field
133
				$values['field_options']['form_select'] = $new_repeat_form_id;
134
			}
135
136
			// If this is a field inside of a repeating section, associate it with the correct form
137
			if ( $field->form_id != $old_form_id && isset( $old_repeat_form_id ) && isset( $new_repeat_form_id ) && $field->form_id == $old_repeat_form_id ) {
138
				$values['form_id'] = $new_repeat_form_id;
139
			}
140
141
            $values = apply_filters('frm_duplicated_field', $values);
142
            $new_id = self::create($values);
143
            $frm_duplicate_ids[ $field->id ] = $new_id;
144
            $frm_duplicate_ids[ $field->field_key ] = $new_id;
145
            unset($field);
146
        }
147
    }
148
149
	public static function update( $id, $values ) {
150
        global $wpdb;
151
152
		$id = absint( $id );
153
154
		if ( isset( $values['field_key'] ) ) {
155
			$values['field_key'] = FrmAppHelper::get_unique_key( $values['field_key'], $wpdb->prefix . 'frm_fields', 'field_key', $id );
156
		}
157
158
        if ( isset($values['required']) ) {
159
            $values['required'] = (int) $values['required'];
160
        }
161
162
		self::preserve_phone_format_backslashes( $values );
163
164
		// serialize array values
165
		foreach ( array( 'default_value', 'field_options', 'options' ) as $opt ) {
166
			if ( isset( $values[ $opt ] ) && is_array( $values[ $opt ] ) ) {
167
				$values[ $opt ] = serialize( $values[ $opt ] );
168
			}
169
		}
170
171
		$query_results = $wpdb->update( $wpdb->prefix . 'frm_fields', $values, array( 'id' => $id ) );
172
173
        $form_id = 0;
174
		if ( isset( $values['form_id'] ) ) {
175
            $form_id = absint( $values['form_id'] );
176
		} else {
177
            $field = self::getOne($id);
178
            if ( $field ) {
179
                $form_id = $field->form_id;
180
            }
181
            unset($field);
182
        }
183
        unset($values);
184
185
		if ( $query_results ) {
186
            wp_cache_delete( $id, 'frm_field' );
187
            if ( $form_id ) {
188
                self::delete_form_transient($form_id);
189
            }
190
        }
191
192
        return $query_results;
193
    }
194
195
	/**
196
	* Keep backslashes in the phone format option
197
	*
198
	* @since 2.0.8
199
	* @param $values array - pass by reference
200
	*/
201
	private static function preserve_phone_format_backslashes( &$values ) {
202
		if ( isset( $values['field_options']['format'] ) ) {
203
			$values['field_options']['format'] = FrmAppHelper::preserve_backslashes( $values['field_options']['format'] );
204
		}
205
	}
206
207
    public static function destroy( $id ) {
208
		global $wpdb;
209
210
		do_action( 'frm_before_destroy_field', $id );
211
212
		wp_cache_delete( $id, 'frm_field' );
213
		$field = self::getOne( $id );
214
		if ( ! $field ) {
215
			return false;
216
		}
217
218
		self::delete_form_transient( $field->form_id );
219
220
		$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_item_metas WHERE field_id=%d', $id ) );
221
		return $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_fields WHERE id=%d', $id ) );
222
    }
223
224
	public static function delete_form_transient( $form_id ) {
225
		$form_id = absint( $form_id );
226
		delete_transient( 'frm_form_fields_' . $form_id . 'excludeinclude' );
227
		delete_transient( 'frm_form_fields_' . $form_id . 'includeinclude' );
228
		delete_transient( 'frm_form_fields_' . $form_id . 'includeexclude' );
229
		delete_transient( 'frm_form_fields_' . $form_id . 'excludeexclude' );
230
231
		global $wpdb;
232
		$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->options . ' WHERE option_name LIKE %s OR option_name LIKE %s OR option_name LIKE %s OR option_name LIKE %s', '_transient_timeout_frm_form_fields_' . $form_id . 'ex%', '_transient_frm_form_fields_' . $form_id . 'ex%', '_transient_timeout_frm_form_fields_' . $form_id . 'in%', '_transient_frm_form_fields_' . $form_id . 'in%' ) );
233
234
		$cache_key = serialize( array( 'fi.form_id' => $form_id ) ) . 'field_orderlb';
235
        wp_cache_delete($cache_key, 'frm_field');
236
237
		// this cache key is autogenerated in FrmDb::get_var
238
		wp_cache_delete( '(__fi.form_id=%d_OR_fr.parent_form_id=%d_)__' . $form_id . '_' . $form_id . '_ORDER_BY_field_orderfi.*__fr.name_as_form_name_results', 'frm_field' );
239
240
        $form = FrmForm::getOne($form_id);
241
        if ( $form && $form->parent_form_id ) {
242
            self::delete_form_transient( $form->parent_form_id );
243
        }
244
    }
245
246
	/**
247
	 * If $field is numeric, get the field object
248
	 */
249
	public static function maybe_get_field( &$field ) {
250
		if ( ! is_object( $field ) ) {
251
			$field = self::getOne( $field );
252
		}
253
	}
254
255
	public static function getOne( $id ) {
0 ignored issues
show
Coding Style introduced by
The function name getOne is in camel caps, but expected get_one instead as per the coding standard.
Loading history...
256
		if ( empty( $id ) ) {
257
			return;
258
		}
259
260
        global $wpdb;
261
262
        $where = is_numeric($id) ? 'id=%d' : 'field_key=%s';
263
		$query = $wpdb->prepare( 'SELECT * FROM ' . $wpdb->prefix . 'frm_fields WHERE ' . $where, $id );
264
265
        $results = FrmAppHelper::check_cache( $id, 'frm_field', $query, 'get_row', 0 );
266
267
        if ( empty($results) ) {
268
            return $results;
269
        }
270
271 View Code Duplication
        if ( is_numeric($id) ) {
1 ignored issue
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...
272
            wp_cache_set( $results->field_key, $results, 'frm_field' );
273
        } else if ( $results ) {
274
            wp_cache_set( $results->id, $results, 'frm_field' );
275
        }
276
277
		self::prepare_options( $results );
278
279
        return stripslashes_deep($results);
280
    }
281
282
    /**
283
     * Get the field type by key or id
284
     * @param int|string The field id or key
285
	 * @param mixed $col The name of the column in the fields database table
286
     */
287
    public static function &get_type( $id, $col = 'type' ) {
288
        $field = FrmAppHelper::check_cache( $id, 'frm_field' );
289
        if ( $field ) {
290
            $type = $field->{$col};
291
        } else {
292
            $type = FrmDb::get_var( 'frm_fields', array( 'or' => 1, 'id' => $id, 'field_key' => $id ), $col );
293
        }
294
295
        return $type;
296
    }
297
298
	public static function get_all_types_in_form( $form_id, $type, $limit = '', $inc_sub = 'exclude' ) {
299
        if ( ! $form_id ) {
300
            return array();
301
        }
302
303
		$results = self::get_fields_from_transients( $form_id, array( 'inc_embed' => $inc_sub, 'inc_repeat' => $inc_sub ) );
304
		if ( ! empty( $results ) ) {
305
            $fields = array();
306
            $count = 0;
307
            foreach ( $results as $result ) {
308
                if ( $type != $result->type ) {
309
                    continue;
310
                }
311
312
				$fields[ $result->id ] = $result;
313
                $count++;
314
                if ( $limit == 1 ) {
315
                    $fields = $result;
316
                    break;
317
                }
318
319
                if ( ! empty($limit) && $count >= $limit ) {
320
                    break;
321
                }
322
323
                unset($result);
324
            }
325
            return stripslashes_deep($fields);
326
        }
327
328
        self::$use_cache = false;
329
330
		$where = array( 'fi.form_id' => (int) $form_id, 'fi.type' => $type );
331
		self::maybe_include_repeating_fields( $inc_sub, $where );
332
		$results = self::getAll( $where, 'field_order', $limit );
333
        self::$use_cache = true;
334
        self::include_sub_fields($results, $inc_sub, $type);
335
336
        return $results;
337
    }
338
339
	public static function get_all_for_form( $form_id, $limit = '', $inc_embed = 'exclude', $inc_repeat = 'include' ) {
340
        if ( ! (int) $form_id ) {
341
            return array();
342
        }
343
344
		$results = self::get_fields_from_transients( $form_id, array( 'inc_embed' => $inc_embed, 'inc_repeat' => $inc_repeat ) );
345
		if ( ! empty( $results ) ) {
346
            if ( empty($limit) ) {
347
				return $results;
348
            }
349
350
            $fields = array();
351
            $count = 0;
352
            foreach ( $results as $result ) {
353
				$fields[ $result->id ] = $result;
354
                if ( ! empty($limit) && $count >= $limit ) {
355
                    break;
356
                }
357
            }
358
359
			return $fields;
360
        }
361
362
        self::$use_cache = false;
363
364
		$where = array( 'fi.form_id' => absint( $form_id ) );
365
		self::maybe_include_repeating_fields( $inc_repeat, $where );
366
		$results = self::getAll( $where, 'field_order', $limit );
367
368
        self::$use_cache = true;
369
370
		self::include_sub_fields( $results, $inc_embed, 'all' );
371
372
        if ( empty($limit) ) {
373
			self::set_field_transient( $results, $form_id, 0, array( 'inc_embed' => $inc_embed, 'inc_repeat' => $inc_repeat ) );
374
        }
375
376
		return $results;
377
    }
378
379
	/**
380
	* If repeating fields should be included, adjust $where accordingly
381
	*
382
	* @param string $inc_repeat
383
	* @param array $where - pass by reference
384
	*/
385
	private static function maybe_include_repeating_fields( $inc_repeat, &$where ) {
386
		if ( $inc_repeat == 'include' ) {
387
			$form_id = $where['fi.form_id'];
388
			$where[] = array( 'or' => 1, 'fi.form_id' => $form_id, 'fr.parent_form_id' => $form_id );
389
			unset( $where['fi.form_id'] );
390
		}
391
	}
392
393
	public static function include_sub_fields( &$results, $inc_embed, $type = 'all' ) {
394
		if ( 'include' != $inc_embed ) {
395
            return;
396
        }
397
398
        $form_fields = $results;
399
		$index_offset = 1;
400
        foreach ( $form_fields as $k => $field ) {
401
            if ( 'form' != $field->type || ! isset($field->field_options['form_select']) ) {
402
                continue;
403
            }
404
405
            if ( $type == 'all' ) {
406
                $sub_fields = self::get_all_for_form( $field->field_options['form_select'] );
407
            } else {
408
                $sub_fields = self::get_all_types_in_form($field->form_id, $type);
409
            }
410
411
            if ( ! empty($sub_fields) ) {
412
				$index = $k + $index_offset;
413
				$index_offset += count( $sub_fields );
414
				array_splice($results, $index, 0, $sub_fields);
415
            }
416
            unset($field, $sub_fields);
417
        }
418
    }
419
420
	public static function getAll( $where = array(), $order_by = '', $limit = '', $blog_id = false ) {
0 ignored issues
show
Coding Style introduced by
The function name getAll is in camel caps, but expected get_all instead as per the coding standard.
Loading history...
421
		$cache_key = maybe_serialize( $where ) . $order_by . 'l' . $limit . 'b' . $blog_id;
422
        if ( self::$use_cache ) {
423
            // make sure old cache doesn't get saved as a transient
424
            $results = wp_cache_get($cache_key, 'frm_field');
425
            if ( false !== $results ) {
426
                return stripslashes_deep($results);
427
            }
428
        }
429
430
        global $wpdb;
431
432
        if ( $blog_id && is_multisite() ) {
433
            global $wpmuBaseTablePrefix;
434
            if ( $wpmuBaseTablePrefix ) {
435
				$prefix = $wpmuBaseTablePrefix . $blog_id . '_';
436
            } else {
437
                $prefix = $wpdb->get_blog_prefix( $blog_id );
438
            }
439
440
			$table_name = $prefix . 'frm_fields';
441
			$form_table_name = $prefix . 'frm_forms';
442
		} else {
443
			$table_name = $wpdb->prefix . 'frm_fields';
444
			$form_table_name = $wpdb->prefix . 'frm_forms';
445
        }
446
447 View Code Duplication
		if ( ! empty( $order_by ) && strpos( $order_by, 'ORDER BY' ) === false ) {
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...
448
			$order_by = ' ORDER BY ' . $order_by;
449
		}
450
451
        $limit = FrmAppHelper::esc_limit($limit);
452
453
        $query = "SELECT fi.*, fr.name as form_name  FROM {$table_name} fi LEFT OUTER JOIN {$form_table_name} fr ON fi.form_id=fr.id";
454
        $query_type = ( $limit == ' LIMIT 1' || $limit == 1 ) ? 'row' : 'results';
455
456
        if ( is_array($where) ) {
457
            $results = FrmDb::get_var( $table_name . ' fi LEFT OUTER JOIN ' . $form_table_name . ' fr ON fi.form_id=fr.id', $where, 'fi.*, fr.name as form_name', array( 'order_by' => $order_by, 'limit' => $limit ), '', $query_type );
458
		} else {
459
			// if the query is not an array, then it has already been prepared
460
            $query .= FrmAppHelper::prepend_and_or_where(' WHERE ', $where) . $order_by . $limit;
461
462
			$function_name = ( $query_type == 'row' ) ? 'get_row' : 'get_results';
463
			$results = $wpdb->$function_name( $query );
464
        }
465
        unset( $where );
466
467
		self::format_field_results( $results );
468
469
		wp_cache_set( $cache_key, $results, 'frm_field', 300 );
470
471
		return stripslashes_deep( $results );
472
	}
473
474
	/**
475
	 * @since 2.0.8
476
	 */
477
	private static function format_field_results( &$results ) {
478
		if ( is_array( $results ) ) {
479
			foreach ( $results as $r_key => $result ) {
480
				wp_cache_set( $result->id, $result, 'frm_field' );
481
				wp_cache_set( $result->field_key, $result, 'frm_field' );
482
483
				$results[ $r_key ]->field_options = maybe_unserialize( $result->field_options );
484
				$results[ $r_key ]->options = maybe_unserialize( $result->options );
485
				$results[ $r_key ]->default_value = maybe_unserialize( $result->default_value );
486
487
				unset( $r_key, $result );
488
			}
489 View Code Duplication
		} else if ( $results ) {
1 ignored issue
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...
490
			wp_cache_set( $results->id, $results, 'frm_field' );
491
			wp_cache_set( $results->field_key, $results, 'frm_field' );
492
493
			self::prepare_options( $results );
494
		}
495
	}
496
497
	/**
498
	 * Unserialize all the serialized field data
499
	 * @since 2.0
500
	 */
501
	private static function prepare_options( &$results ) {
502
		$results->field_options = maybe_unserialize( $results->field_options );
503
504
		$results->options = maybe_unserialize($results->options);
505
		$results->default_value = maybe_unserialize($results->default_value);
506
	}
507
508
	/**
509
	 * If a form has too many fields, thay won't all save into a single transient.
510
	 * We'll break them into groups of 200
511
	 * @since 2.0.1
512
	 */
513
	private static function get_fields_from_transients( $form_id, $args ) {
514
		$fields = array();
515
		self::get_next_transient( $fields, 'frm_form_fields_' . $form_id . $args['inc_embed'] . $args['inc_repeat'] );
516
		return $fields;
517
	}
518
519
	/**
520
	 * Called by get_fields_from_transients
521
	 * @since 2.0.1
522
	 */
523
	private static function get_next_transient( &$fields, $base_name, $next = 0 ) {
524
		$name = $next ? $base_name . $next : $base_name;
525
		$next_fields = get_transient( $name );
526
527
		if ( $next_fields ) {
528
			$fields = array_merge( $fields, $next_fields );
529
530
			if ( count( $next_fields ) >= self::$transient_size ) {
531
				// if this transient is full, check for another
532
				$next++;
533
				self::get_next_transient( $fields, $base_name, $next );
534
			}
535
		}
536
	}
537
538
	/**
539
	 * Save the transients in chunks for large forms
540
	 * @since 2.0.1
541
	 */
542
	private static function set_field_transient( &$fields, $form_id, $next = 0, $args = array() ) {
543
		$base_name = 'frm_form_fields_' . $form_id . $args['inc_embed'] . $args['inc_repeat'];
544
		$field_chunks = array_chunk( $fields, self::$transient_size );
545
546
		foreach ( $field_chunks as $field ) {
547
			$name = $next ? $base_name . $next : $base_name;
548
			$set = set_transient( $name, $field, 60 * 60 * 6 );
549
			if ( ! $set ) {
550
				// the transient didn't save
551
				if ( $name != $base_name ) {
552
					// if the first saved an others fail, this will show an incmoplete form
553
					self::delete_form_transient( $form_id );
554
				}
555
				return;
556
			}
557
558
			$next++;
559
		}
560
	}
561
562
	public static function getIds( $where = '', $order_by = '', $limit = '' ) {
0 ignored issues
show
Coding Style introduced by
The function name getIds is in camel caps, but expected get_ids instead as per the coding standard.
Loading history...
563
		_deprecated_function( __FUNCTION__, '2.0' );
564
        global $wpdb;
565 View Code Duplication
        if ( ! empty($order_by) && ! strpos($order_by, 'ORDER BY') !== false ) {
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...
566
			$order_by = ' ORDER BY ' . $order_by;
567
        }
568
569
		$query = 'SELECT fi.id  FROM ' . $wpdb->prefix . 'frm_fields fi ' .
570
			'LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_forms fr ON fi.form_id=fr.id' .
571
			FrmAppHelper::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
572
573
        $method = ( $limit == ' LIMIT 1' || $limit == 1 ) ? 'get_var' : 'get_col';
574
		$cache_key = 'getIds_' . maybe_serialize( $where ) . $order_by . $limit;
575
        $results = FrmAppHelper::check_cache($cache_key, 'frm_field', $query, $method);
576
577
        return $results;
578
    }
579
580
	public static function is_no_save_field( $type ) {
581
		return in_array( $type, self::no_save_fields() );
582
	}
583
584
	public static function no_save_fields() {
585
		return array( 'divider', 'end_divider', 'captcha', 'break', 'html', 'form' );
586
	}
587
588
	/**
589
	 * Check if this field can hold an array of values
590
	 *
591
	 * @since 2.0.9
592
	 *
593
	 * @param array|object $field
594
	 * @return boolean
595
	 */
596
	public static function is_field_with_multiple_values( $field ) {
597
		if ( ! $field ) {
598
			return false;
599
		}
600
601
		if ( is_array( $field ) ) {
602
603
			$is_multi_value_field = (
604
				$field['type'] == 'checkbox' ||
605
				$field['type'] == 'address' ||
606
				( $field['type'] == 'data' && isset($field['data_type']) && $field['data_type'] == 'checkbox' ) ||
607
				self::is_multiple_select( $field )
608
			);
609
610
		} else {
611
			$is_multi_value_field = (
612
				$field->type == 'checkbox' ||
613
				$field->type == 'address' ||
614
				( $field->type == 'data' && isset( $field->field_options['data_type'] ) && $field->field_options['data_type'] == 'checkbox' ) ||
615
				self::is_multiple_select( $field )
616
			);
617
		}
618
619
		return $is_multi_value_field;
620
	}
621
622
	/**
623
	 * Check if this is a multiselect dropdown field
624
	 *
625
	 * @since 2.0.9
626
	 * @return boolean
627
	 */
628
	public static function is_multiple_select( $field ) {
629
		if ( is_array( $field ) ) {
630
			return self::is_option_true( $field, 'multiple' ) && ( ( $field['type'] == 'select' || ( $field['type'] == 'data' && isset( $field['data_type'] ) && $field['data_type'] == 'select') ) );
631
		} else {
632
			return self::is_option_true( $field, 'multiple' ) && ( ( $field->type == 'select' || ( $field->type == 'data' && isset($field->field_options['data_type'] ) && $field->field_options['data_type'] == 'select') ) );
633
		}
634
	}
635
636
	/**
637
	 * Check if a field is read only. Read only can be set in the field options,
638
	 * but disabled with the shortcode options
639
	 *
640
	 * @since 2.0.9
641
	 */
642
	public static function is_read_only( $field ) {
643
		global $frm_vars;
644
		return ( self::is_option_true( $field, 'read_only' ) && ( ! isset( $frm_vars['readonly'] ) || $frm_vars['readonly'] != 'disabled' ) );
645
	}
646
647
	/**
648
	 * @since 2.0.9
649
	 */
650
	public static function is_required( $field ) {
651
		$required = ( $field['required'] != '0' );
652
		$required = apply_filters( 'frm_is_field_required', $required, $field );
653
		return $required;
654
	}
655
656
	/**
657
	 * @since 2.0.9
658
	 */
659
	public static function is_option_true( $field, $option ) {
660
		if ( is_array( $field ) ) {
661
			return self::is_option_true_in_array( $field, $option );
662
		} else {
663
			return self::is_option_true_in_object( $field, $option );
664
		}
665
	}
666
667
	/**
668
	 * @since 2.0.9
669
	 */
670
	public static function is_option_empty( $field, $option ) {
671
		if ( is_array( $field ) ) {
672
			return self::is_option_empty_in_array( $field, $option );
673
		} else {
674
			return self::is_option_empty_in_object( $field, $option );
675
		}
676
	}
677
678
	public static function is_option_true_in_array( $field, $option ) {
679
		return isset( $field[ $option ] ) && $field[ $option ];
680
	}
681
682
	public static function is_option_true_in_object( $field, $option ) {
683
		return isset( $field->field_options[ $option ] ) && $field->field_options[ $option ];
684
	}
685
686
	public static function is_option_empty_in_array( $field, $option ) {
687
		return ! isset( $field[ $option ] ) || empty( $field[ $option ] );
688
	}
689
690
	public static function is_option_empty_in_object( $field, $option ) {
691
		return ! isset( $field->field_options[ $option ] ) || empty( $field->field_options[ $option ] );
692
	}
693
694
	public static function is_option_value_in_object( $field, $option ) {
695
		return isset( $field->field_options[ $option ] ) && $field->field_options[ $option ] != '';
696
	}
697
698
	/**
699
	 * @since 2.0.18
700
	 */
701
	public static function get_option( $field, $option ) {
702
		if ( is_array( $field ) ) {
703
			$option = self::get_option_in_array( $field, $option );
704
		} else {
705
			$option = self::get_option_in_object( $field, $option );
706
		}
707
		return $option;
708
	}
709
710
	public static function get_option_in_array( $field, $option ) {
711
		return $field[ $option ];
712
	}
713
714
	public static function get_option_in_object( $field, $option ) {
715
		return isset( $field->field_options[ $option ] ) ? $field->field_options[ $option ] : '';
716
	}
717
718
	/**
719
	* @since 2.0.09
720
	*/
721
	public static function is_repeating_field( $field ) {
722
		if ( is_array( $field ) ) {
723
			$is_repeating_field = ( 'divider' == $field['type'] );
724
		} else {
725
			$is_repeating_field = ( 'divider' == $field->type );
726
		}
727
		return ( $is_repeating_field && self::is_option_true( $field, 'repeat' ) );
728
	}
729
730
    /**
731
     * @param string $key
732
     * @return int field id
733
     */
734
	public static function get_id_by_key( $key ) {
735
        $id = FrmDb::get_var( 'frm_fields', array( 'field_key' => sanitize_title( $key ) ) );
736
        return $id;
737
    }
738
739
	/**
740
	 * @param string $id
741
	 * @return string
742
	 */
743
	public static function get_key_by_id( $id ) {
744
		return FrmDb::get_var( 'frm_fields', array( 'id' => $id ), 'field_key' );
745
	}
746
}
747