Passed
Push — master ( ec16eb...0357f3 )
by Stephanie
03:05
created

FrmField::duplicate()   D

Complexity

Conditions 10
Paths 17

Size

Total Lines 46
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 26
nc 17
nop 4
dl 0
loc 46
rs 4.983
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
if ( ! defined('ABSPATH') ) {
3
	die( 'You are not allowed to call this page directly.' );
4
}
5
6
class FrmField {
7
8
    static $use_cache = true;
9
	static $transient_size = 200;
10
11
	public static function field_selection() {
12
		$fields = apply_filters('frm_available_fields', array(
0 ignored issues
show
Bug introduced by
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

12
		$fields = /** @scrutinizer ignore-call */ apply_filters('frm_available_fields', array(
Loading history...
13
			'text'      => array(
14
				'name'  => __( 'Text', 'formidable' ),
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

14
				'name'  => /** @scrutinizer ignore-call */ __( 'Text', 'formidable' ),
Loading history...
15
				'icon'  => 'frm_css_icon frm_text_icon',
16
			),
17
			'textarea'  => array(
18
				'name'  => __( 'Paragraph', 'formidable' ),
19
				'icon'  => 'frm_icon_font frm_paragraph_icon',
20
			),
21
			'checkbox'  => array(
22
				'name'  => __( 'Checkboxes', 'formidable' ),
23
				'icon'  => 'frm_icon_font frm_check-square_icon',
24
			),
25
			'radio'     => array(
26
				'name'  => __( 'Radio Button', 'formidable' ),
27
				'icon'  => 'frm_icon_font frm_radio-checked_icon',
28
			),
29
			'select'    => array(
30
				'name'  => __( 'Dropdown', 'formidable' ),
31
				'icon'  => 'frm_icon_font frm_caret-square-down_icon',
32
			),
33
			'email'     => array(
34
				'name'  => __( 'Email', 'formidable' ),
35
				'icon'  => 'frm_icon_font frm_envelope_icon',
36
			),
37
			'url'       => array(
38
				'name'  => __( 'Website/URL', 'formidable' ),
39
				'icon'  => 'dashicons dashicons-admin-links',
40
			),
41
			'number'    => array(
42
				'name'  => __( 'Number', 'formidable' ),
43
				'icon'  => 'frm_css_icon frm_number_icon',
44
			),
45
			'phone'     => array(
46
				'name'  => __( 'Phone', 'formidable' ),
47
				'icon'  => 'frm_icon_font frm_phone_icon',
48
			),
49
			'html'      => array(
50
				'name'  => __( 'HTML', 'formidable' ),
51
				'icon'  => 'frm_icon_font frm_embed2_icon',
52
			),
53
			'hidden'    => array(
54
				'name'  => __( 'Hidden Field', 'formidable' ),
55
				'icon'  => 'frm_icon_font frm_eye-slash_icon',
56
			),
57
			'user_id'   => array(
58
				'name'  => __( 'User ID', 'formidable' ),
59
				'icon'  => 'frm_icon_font frm_user_icon',
60
			),
61
			'captcha'   => array(
62
				'name'  => __( 'reCAPTCHA', 'formidable' ),
63
				'icon'  => 'frm_icon_font frm_shield-check_icon',
64
			),
65
		));
66
67
		return $fields;
68
	}
69
70
	public static function pro_field_selection() {
71
		return apply_filters( 'frm_pro_available_fields', array(
0 ignored issues
show
Bug introduced by
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

71
		return /** @scrutinizer ignore-call */ apply_filters( 'frm_pro_available_fields', array(
Loading history...
72
			'file'      => array(
73
				'name'  => __( 'File Upload', 'formidable' ),
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

73
				'name'  => /** @scrutinizer ignore-call */ __( 'File Upload', 'formidable' ),
Loading history...
74
				'icon'  => 'frm_icon_font frm_upload2_icon',
75
			),
76
			'rte'       => array(
77
				'name'  => __( 'Rich Text', 'formidable' ),
78
				'icon'  => 'dashicons dashicons-editor-alignright',
79
			),
80
			'date'      => array(
81
				'name'  => __( 'Date', 'formidable' ),
82
				'icon'  => 'frm_icon_font frm_calendar_icon',
83
			),
84
			'time'      => array(
85
				'name'  => __( 'Time', 'formidable' ),
86
				'icon'  => 'frm_icon_font frm_clock-o_icon',
87
			),
88
			'scale'     => array(
89
				'name'  => __( 'Scale', 'formidable' ),
90
				'icon'  => 'frm_icon_font frm_linear_scale_icon',
91
			),
92
			'star'      => array(
93
				'name'  => __( 'Star Rating', 'formidable' ),
94
				'icon'  => 'frm_icon_font frm_star-full_icon',
95
			),
96
			'range'     => array(
97
				'name'  => __( 'Slider', 'formidable' ),
98
				'icon'  => 'frm_icon_font frm_sliders_icon',
99
			),
100
			'toggle'    => array(
101
				'name'  => __( 'Toggle', 'formidable' ),
102
				'icon'  => 'frm_icon_font frm_toggle-on_icon',
103
			),
104
			'data'      => array(
105
				'name'  => __( 'Dynamic', 'formidable' ),
106
				'icon'  => 'frm_icon_font frm_sitemap_icon',
107
			),
108
			'lookup'    => array(
109
				'name'  => __( 'Lookup', 'formidable' ),
110
				'icon'  => 'frm_icon_font frm_search_icon',
111
			),
112
			'divider|repeat' => array(
113
				'name'  => __( 'Repeater', 'formidable' ),
114
				'icon'  => 'frm_icon_font frm_repeat_icon',
115
			),
116
			'end_divider' => array(
117
				'name'  => __( 'End Section', 'formidable' ),
118
				'switch_from' => 'divider',
119
			),
120
			'divider'   => array(
121
				'name'  => __( 'Section', 'formidable' ),
122
				'icon'  => 'frm_css_icon frm_heading_icon',
123
			),
124
			'break'     => array(
125
				'name'  => __( 'Page Break', 'formidable' ),
126
				'icon'  => 'frm_icon_font frm_page-break_icon',
127
			),
128
			'form'      => array(
129
				'name'  => __( 'Embed Form', 'formidable' ),
130
				'icon'  => 'dashicons dashicons-editor-table',
131
			),
132
			'password'  => array(
133
				'name'  => __( 'Password', 'formidable' ),
134
				'icon'  => 'frm_icon_font frm_key_icon',
135
			),
136
			'tag'       => array(
137
				'name'  => __( 'Tags', 'formidable' ),
138
				'icon'  => 'frm_icon_font frm_price-tags_icon',
139
			),
140
			'credit_card' => array(
141
				'name'  => __( 'Credit Card', 'formidable' ),
142
				'icon'  => 'frm_icon_font frm_credit-card-alt_icon',
143
			),
144
			'address'   => array(
145
				'name'  => __( 'Address', 'formidable' ),
146
				'icon'  => 'frm_icon_font frm_location_icon',
147
			),
148
		));
149
	}
150
151
    public static function create( $values, $return = true ) {
152
        global $wpdb, $frm_duplicate_ids;
153
154
        $new_values = array();
155
        $key = isset($values['field_key']) ? $values['field_key'] : $values['name'];
156
		$new_values['field_key'] = FrmAppHelper::get_unique_key( $key, $wpdb->prefix . 'frm_fields', 'field_key' );
157
158
		foreach ( array( 'name', 'description', 'type', 'default_value' ) as $col ) {
159
			$new_values[ $col ] = $values[ $col ];
160
        }
161
162
        $new_values['options'] = $values['options'];
163
164
        $new_values['field_order'] = isset($values['field_order']) ? (int) $values['field_order'] : null;
165
        $new_values['required'] = isset($values['required']) ? (int) $values['required'] : 0;
166
        $new_values['form_id'] = isset($values['form_id']) ? (int) $values['form_id'] : null;
167
        $new_values['field_options'] = $values['field_options'];
168
        $new_values['created_at'] = current_time('mysql', 1);
0 ignored issues
show
Bug introduced by
The function current_time was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

168
        $new_values['created_at'] = /** @scrutinizer ignore-call */ current_time('mysql', 1);
Loading history...
169
170
		if ( isset( $values['id'] ) ) {
171
			$frm_duplicate_ids[ $values['field_key'] ] = $new_values['field_key'];
172
            $new_values = apply_filters('frm_duplicated_field', $new_values);
0 ignored issues
show
Bug introduced by
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
            $new_values = /** @scrutinizer ignore-call */ apply_filters('frm_duplicated_field', $new_values);
Loading history...
173
        }
174
175
		self::preserve_format_option_backslashes( $new_values );
176
177
		foreach ( $new_values as $k => $v ) {
178
            if ( is_array( $v ) ) {
179
				$new_values[ $k ] = serialize( $v );
180
			}
181
            unset( $k, $v );
182
        }
183
184
        //if(isset($values['id']) and is_numeric($values['id']))
185
        //    $new_values['id'] = $values['id'];
186
187
		$query_results = $wpdb->insert( $wpdb->prefix . 'frm_fields', $new_values );
188
		$new_id = 0;
189
		if ( $query_results ) {
190
			self::delete_form_transient( $new_values['form_id'] );
191
			$new_id = $wpdb->insert_id;
192
		}
193
194
		if ( ! $return ) {
195
			return false;
196
		}
197
198
		if ( $query_results ) {
199
			if ( isset( $values['id'] ) ) {
200
				$frm_duplicate_ids[ $values['id'] ] = $new_id;
201
			}
202
			return $new_id;
203
		} else {
204
			return false;
205
		}
206
    }
207
208
    public static function duplicate( $old_form_id, $form_id, $copy_keys = false, $blog_id = false ) {
209
        global $frm_duplicate_ids;
210
211
		$where = array(
212
			array(
213
				'or' => 1,
214
				'fi.form_id' => $old_form_id,
215
				'fr.parent_form_id' => $old_form_id,
216
			),
217
		);
218
		$fields = self::getAll( $where, 'field_order', '', $blog_id );
219
220
        foreach ( (array) $fields as $field ) {
221
			$new_key = $copy_keys ? $field->field_key : '';
222
            if ( $copy_keys && substr($field->field_key, -1) == 2 ) {
223
                $new_key = rtrim($new_key, 2);
224
            }
225
226
            $values = array();
227
            FrmFieldsHelper::fill_field( $values, $field, $form_id, $new_key );
228
229
			// If this is a repeating section, create new form
230
			if ( self::is_repeating_field( $field ) ) {
231
				// create the repeatable form
232
				$new_repeat_form_id = apply_filters( 'frm_create_repeat_form', 0, array(
0 ignored issues
show
Bug introduced by
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

232
				$new_repeat_form_id = /** @scrutinizer ignore-call */ apply_filters( 'frm_create_repeat_form', 0, array(
Loading history...
233
					'parent_form_id' => $form_id,
234
					'field_name'     => $field->name,
235
				) );
236
237
				// Save old form_select
238
				$old_repeat_form_id = $field->field_options['form_select'];
239
240
				// Update form_select for repeating field
241
				$values['field_options']['form_select'] = $new_repeat_form_id;
242
			}
243
244
			// If this is a field inside of a repeating section, associate it with the correct form
245
			if ( $field->form_id != $old_form_id && isset( $old_repeat_form_id ) && isset( $new_repeat_form_id ) && $field->form_id == $old_repeat_form_id ) {
246
				$values['form_id'] = $new_repeat_form_id;
247
			}
248
249
            $values = apply_filters('frm_duplicated_field', $values);
250
            $new_id = self::create($values);
251
            $frm_duplicate_ids[ $field->id ] = $new_id;
252
            $frm_duplicate_ids[ $field->field_key ] = $new_id;
253
            unset($field);
254
        }
255
    }
256
257
	public static function update( $id, $values ) {
258
        global $wpdb;
259
260
		$id = absint( $id );
0 ignored issues
show
Bug introduced by
The function absint was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

260
		$id = /** @scrutinizer ignore-call */ absint( $id );
Loading history...
261
262
		if ( isset( $values['field_key'] ) ) {
263
			$values['field_key'] = FrmAppHelper::get_unique_key( $values['field_key'], $wpdb->prefix . 'frm_fields', 'field_key', $id );
264
		}
265
266
        if ( isset($values['required']) ) {
267
            $values['required'] = (int) $values['required'];
268
        }
269
270
		self::preserve_format_option_backslashes( $values );
271
272
		if ( isset( $values['type'] ) ) {
273
			$values = apply_filters( 'frm_clean_' . $values['type'] . '_field_options_before_update', $values );
0 ignored issues
show
Bug introduced by
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

273
			$values = /** @scrutinizer ignore-call */ apply_filters( 'frm_clean_' . $values['type'] . '_field_options_before_update', $values );
Loading history...
274
275
			if ( $values['type'] == 'hidden' && isset( $values['field_options'] ) && isset( $values['field_options']['clear_on_focus'] ) ) {
276
				// don't keep the old placeholder setting for hidden fields
277
				$values['field_options']['clear_on_focus'] = 0;
278
			}
279
		}
280
281
		// serialize array values
282
		foreach ( array( 'default_value', 'field_options', 'options' ) as $opt ) {
283
			if ( isset( $values[ $opt ] ) && is_array( $values[ $opt ] ) ) {
284
				$values[ $opt ] = serialize( $values[ $opt ] );
285
			}
286
		}
287
288
		$query_results = $wpdb->update( $wpdb->prefix . 'frm_fields', $values, array( 'id' => $id ) );
289
290
        $form_id = 0;
291
		if ( isset( $values['form_id'] ) ) {
292
            $form_id = absint( $values['form_id'] );
293
		} else {
294
            $field = self::getOne($id);
295
            if ( $field ) {
296
                $form_id = $field->form_id;
297
            }
298
            unset($field);
299
        }
300
        unset($values);
301
302
		if ( $query_results ) {
303
            wp_cache_delete( $id, 'frm_field' );
0 ignored issues
show
Bug introduced by
The function wp_cache_delete was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

303
            /** @scrutinizer ignore-call */ 
304
            wp_cache_delete( $id, 'frm_field' );
Loading history...
304
            if ( $form_id ) {
305
                self::delete_form_transient( $form_id );
306
            }
307
        }
308
309
        return $query_results;
310
    }
311
312
	/**
313
	* Keep backslashes in the phone format option
314
	*
315
	* @since 2.0.8
316
	* @param $values array - pass by reference
317
	*/
318
	private static function preserve_format_option_backslashes( &$values ) {
319
		if ( isset( $values['field_options']['format'] ) ) {
320
			$values['field_options']['format'] = FrmAppHelper::preserve_backslashes( $values['field_options']['format'] );
321
		}
322
	}
323
324
    public static function destroy( $id ) {
325
		global $wpdb;
326
327
		do_action( 'frm_before_destroy_field', $id );
0 ignored issues
show
Bug introduced by
The function do_action was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

327
		/** @scrutinizer ignore-call */ 
328
  do_action( 'frm_before_destroy_field', $id );
Loading history...
328
329
		wp_cache_delete( $id, 'frm_field' );
0 ignored issues
show
Bug introduced by
The function wp_cache_delete was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

329
		/** @scrutinizer ignore-call */ 
330
  wp_cache_delete( $id, 'frm_field' );
Loading history...
330
		$field = self::getOne( $id );
331
		if ( ! $field ) {
332
			return false;
333
		}
334
335
		self::delete_form_transient( $field->form_id );
336
337
		$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_item_metas WHERE field_id=%d', $id ) );
338
		return $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_fields WHERE id=%d', $id ) );
339
    }
340
341
	public static function delete_form_transient( $form_id ) {
342
		$form_id = absint( $form_id );
0 ignored issues
show
Bug introduced by
The function absint was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

342
		$form_id = /** @scrutinizer ignore-call */ absint( $form_id );
Loading history...
343
		delete_transient( 'frm_form_fields_' . $form_id . 'excludeinclude' );
0 ignored issues
show
Bug introduced by
The function delete_transient was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

343
		/** @scrutinizer ignore-call */ 
344
  delete_transient( 'frm_form_fields_' . $form_id . 'excludeinclude' );
Loading history...
344
		delete_transient( 'frm_form_fields_' . $form_id . 'includeinclude' );
345
		delete_transient( 'frm_form_fields_' . $form_id . 'includeexclude' );
346
		delete_transient( 'frm_form_fields_' . $form_id . 'excludeexclude' );
347
348
		global $wpdb;
349
		$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%' ) );
350
351
		FrmDb::cache_delete_group( 'frm_field' );
352
353
        $form = FrmForm::getOne($form_id);
354
        if ( $form && $form->parent_form_id && $form->parent_form_id != $form_id ) {
0 ignored issues
show
introduced by
The condition $form && $form->parent_f...ent_form_id != $form_id can never be true.
Loading history...
355
            self::delete_form_transient( $form->parent_form_id );
356
        }
357
    }
358
359
	/**
360
	 * If $field is numeric, get the field object
361
	 */
362
	public static function maybe_get_field( &$field ) {
363
		if ( ! is_object( $field ) ) {
364
			$field = self::getOne( $field );
365
		}
366
	}
367
368
	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...
369
		if ( empty( $id ) ) {
370
			return null;
371
		}
372
373
        global $wpdb;
374
375
        $where = is_numeric($id) ? 'id=%d' : 'field_key=%s';
376
		$query = $wpdb->prepare( 'SELECT * FROM ' . $wpdb->prefix . 'frm_fields WHERE ' . $where, $id );
377
378
        $results = FrmDb::check_cache( $id, 'frm_field', $query, 'get_row', 0 );
379
380
        if ( empty($results) ) {
381
            return $results;
382
        }
383
384
        if ( is_numeric($id) ) {
385
			FrmDb::set_cache( $results->field_key, $results, 'frm_field' );
386
        } else if ( $results ) {
387
			FrmDb::set_cache( $results->id, $results, 'frm_field' );
388
        }
389
390
		self::prepare_options( $results );
391
392
        return stripslashes_deep($results);
0 ignored issues
show
Bug introduced by
The function stripslashes_deep was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

392
        return /** @scrutinizer ignore-call */ stripslashes_deep($results);
Loading history...
393
    }
394
395
    /**
396
     * Get the field type by key or id
397
     * @param int|string The field id or key
0 ignored issues
show
Bug introduced by
The type The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
398
	 * @param mixed $col The name of the column in the fields database table
399
     */
400
    public static function get_type( $id, $col = 'type' ) {
401
        $field = FrmDb::check_cache( $id, 'frm_field' );
402
        if ( $field ) {
403
            $type = $field->{$col};
404
        } else {
405
			$where = array(
406
				'or'        => 1,
407
				'id'        => $id,
408
				'field_key' => $id,
409
			);
410
			$type = FrmDb::get_var( 'frm_fields', $where, $col );
411
        }
412
413
        return $type;
414
    }
415
416
	public static function get_all_types_in_form( $form_id, $type, $limit = '', $inc_sub = 'exclude' ) {
417
        if ( ! $form_id ) {
418
            return array();
419
        }
420
421
		$results = self::get_fields_from_transients( $form_id, array(
422
			'inc_embed'  => $inc_sub,
423
			'inc_repeat' => $inc_sub,
424
		) );
425
		if ( ! empty( $results ) ) {
426
            $fields = array();
427
            $count = 0;
428
            foreach ( $results as $result ) {
429
                if ( $type != $result->type ) {
430
                    continue;
431
                }
432
433
				$fields[ $result->id ] = $result;
434
                $count++;
435
                if ( $limit == 1 ) {
436
                    $fields = $result;
437
                    break;
438
                }
439
440
                if ( ! empty($limit) && $count >= $limit ) {
441
                    break;
442
                }
443
444
                unset($result);
445
            }
446
            return stripslashes_deep($fields);
0 ignored issues
show
Bug introduced by
The function stripslashes_deep was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

446
            return /** @scrutinizer ignore-call */ stripslashes_deep($fields);
Loading history...
447
        }
448
449
        self::$use_cache = false;
450
451
		$where = array(
452
			'fi.form_id' => (int) $form_id,
453
			'fi.type'    => $type,
454
		);
455
		self::maybe_include_repeating_fields( $inc_sub, $where );
456
		$results = self::getAll( $where, 'field_order', $limit );
457
        self::$use_cache = true;
458
        self::include_sub_fields($results, $inc_sub, $type);
459
460
        return $results;
461
    }
462
463
	public static function get_all_for_form( $form_id, $limit = '', $inc_embed = 'exclude', $inc_repeat = 'include' ) {
464
        if ( ! (int) $form_id ) {
465
            return array();
466
        }
467
468
		$results = self::get_fields_from_transients( $form_id, array(
469
			'inc_embed'  => $inc_embed,
470
			'inc_repeat' => $inc_repeat,
471
		) );
472
		if ( ! empty( $results ) ) {
473
            if ( empty($limit) ) {
474
				return $results;
475
            }
476
477
            $fields = array();
478
            $count = 0;
479
            foreach ( $results as $result ) {
480
				$count++;
481
				$fields[ $result->id ] = $result;
482
                if ( ! empty($limit) && $count >= $limit ) {
483
                    break;
484
                }
485
            }
486
487
			return $fields;
488
        }
489
490
        self::$use_cache = false;
491
492
		$where = array( 'fi.form_id' => absint( $form_id ) );
0 ignored issues
show
Bug introduced by
The function absint was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

492
		$where = array( 'fi.form_id' => /** @scrutinizer ignore-call */ absint( $form_id ) );
Loading history...
493
		self::maybe_include_repeating_fields( $inc_repeat, $where );
494
		$results = self::getAll( $where, 'field_order', $limit );
495
496
        self::$use_cache = true;
497
498
		self::include_sub_fields( $results, $inc_embed, 'all' );
499
500
        if ( empty($limit) ) {
501
			self::set_field_transient( $results, $form_id, 0, array(
502
				'inc_embed'  => $inc_embed,
503
				'inc_repeat' => $inc_repeat,
504
			) );
505
        }
506
507
		return $results;
508
    }
509
510
	/**
511
	* If repeating fields should be included, adjust $where accordingly
512
	*
513
	* @param string $inc_repeat
514
	* @param array $where - pass by reference
515
	*/
516
	private static function maybe_include_repeating_fields( $inc_repeat, &$where ) {
517
		if ( $inc_repeat == 'include' ) {
518
			$form_id = $where['fi.form_id'];
519
			$where[] = array(
520
				'or'         => 1,
521
				'fi.form_id' => $form_id,
522
				'fr.parent_form_id' => $form_id,
523
			);
524
			unset( $where['fi.form_id'] );
525
		}
526
	}
527
528
	public static function include_sub_fields( &$results, $inc_embed, $type = 'all' ) {
529
		if ( 'include' != $inc_embed || empty( $results ) ) {
530
            return;
531
        }
532
533
        $form_fields = $results;
534
		$index_offset = 1;
535
        foreach ( $form_fields as $k => $field ) {
536
            if ( 'form' != $field->type || ! isset($field->field_options['form_select']) ) {
537
                continue;
538
            }
539
540
            if ( $type == 'all' ) {
541
                $sub_fields = self::get_all_for_form( $field->field_options['form_select'] );
542
            } else {
543
                $sub_fields = self::get_all_types_in_form($field->form_id, $type);
544
            }
545
546
            if ( ! empty($sub_fields) ) {
547
				$index = $k + $index_offset;
548
				$index_offset += count( $sub_fields );
549
				array_splice($results, $index, 0, $sub_fields);
550
            }
551
            unset($field, $sub_fields);
552
        }
553
    }
554
555
	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...
556
		$cache_key = maybe_serialize( $where ) . $order_by . 'l' . $limit . 'b' . $blog_id;
0 ignored issues
show
Bug introduced by
The function maybe_serialize was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

556
		$cache_key = /** @scrutinizer ignore-call */ maybe_serialize( $where ) . $order_by . 'l' . $limit . 'b' . $blog_id;
Loading history...
557
        if ( self::$use_cache ) {
558
            // make sure old cache doesn't get saved as a transient
559
            $results = wp_cache_get($cache_key, 'frm_field');
0 ignored issues
show
Bug introduced by
The function wp_cache_get was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

559
            $results = /** @scrutinizer ignore-call */ wp_cache_get($cache_key, 'frm_field');
Loading history...
560
            if ( false !== $results ) {
561
                return stripslashes_deep($results);
0 ignored issues
show
Bug introduced by
The function stripslashes_deep was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

561
                return /** @scrutinizer ignore-call */ stripslashes_deep($results);
Loading history...
562
            }
563
        }
564
565
        global $wpdb;
566
567
        if ( $blog_id && is_multisite() ) {
0 ignored issues
show
Bug introduced by
The function is_multisite was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

567
        if ( $blog_id && /** @scrutinizer ignore-call */ is_multisite() ) {
Loading history...
568
            global $wpmuBaseTablePrefix;
569
            if ( $wpmuBaseTablePrefix ) {
570
				$prefix = $wpmuBaseTablePrefix . $blog_id . '_';
571
            } else {
572
                $prefix = $wpdb->get_blog_prefix( $blog_id );
573
            }
574
575
			$table_name = $prefix . 'frm_fields';
576
			$form_table_name = $prefix . 'frm_forms';
577
		} else {
578
			$table_name = $wpdb->prefix . 'frm_fields';
579
			$form_table_name = $wpdb->prefix . 'frm_forms';
580
        }
581
582
		if ( ! empty( $order_by ) && strpos( $order_by, 'ORDER BY' ) === false ) {
583
			$order_by = ' ORDER BY ' . $order_by;
584
		}
585
586
		$limit = FrmDb::esc_limit( $limit );
587
588
        $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";
589
        $query_type = ( $limit == ' LIMIT 1' || $limit == 1 ) ? 'row' : 'results';
590
591
		if ( is_array( $where ) ) {
592
			$args = array(
593
				'order_by' => $order_by,
594
				'limit'    => $limit,
595
			);
596
			$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', $args, '', $query_type );
597
		} else {
598
			// if the query is not an array, then it has already been prepared
599
			$query .= FrmDb::prepend_and_or_where(' WHERE ', $where ) . $order_by . $limit;
600
601
			$function_name = ( $query_type == 'row' ) ? 'get_row' : 'get_results';
602
			$results = $wpdb->$function_name( $query );
603
        }
604
        unset( $where );
605
606
		self::format_field_results( $results );
607
608
		FrmDb::set_cache( $cache_key, $results, 'frm_field' );
609
610
		return stripslashes_deep( $results );
611
	}
612
613
	/**
614
	 * @since 2.0.8
615
	 */
616
	private static function format_field_results( &$results ) {
617
		if ( is_array( $results ) ) {
618
			foreach ( $results as $r_key => $result ) {
619
				FrmDb::set_cache( $result->id, $result, 'frm_field' );
620
				FrmDb::set_cache( $result->field_key, $result, 'frm_field' );
621
622
				$results[ $r_key ]->field_options = maybe_unserialize( $result->field_options );
0 ignored issues
show
Bug introduced by
The function maybe_unserialize was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

622
				$results[ $r_key ]->field_options = /** @scrutinizer ignore-call */ maybe_unserialize( $result->field_options );
Loading history...
623
				$results[ $r_key ]->options = maybe_unserialize( $result->options );
624
				$results[ $r_key ]->default_value = maybe_unserialize( $result->default_value );
625
626
				unset( $r_key, $result );
627
			}
628
		} else if ( $results ) {
629
			FrmDb::set_cache( $results->id, $results, 'frm_field' );
630
			FrmDb::set_cache( $results->field_key, $results, 'frm_field' );
631
632
			self::prepare_options( $results );
633
		}
634
	}
635
636
	/**
637
	 * Unserialize all the serialized field data
638
	 * @since 2.0
639
	 */
640
	private static function prepare_options( &$results ) {
641
		$results->field_options = maybe_unserialize( $results->field_options );
0 ignored issues
show
Bug introduced by
The function maybe_unserialize was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

641
		$results->field_options = /** @scrutinizer ignore-call */ maybe_unserialize( $results->field_options );
Loading history...
642
643
		$results->options = maybe_unserialize($results->options);
644
		$results->default_value = maybe_unserialize($results->default_value);
645
	}
646
647
	/**
648
	 * If a form has too many fields, thay won't all save into a single transient.
649
	 * We'll break them into groups of 200
650
	 * @since 2.0.1
651
	 */
652
	private static function get_fields_from_transients( $form_id, $args ) {
653
		$fields = array();
654
		self::get_next_transient( $fields, 'frm_form_fields_' . $form_id . $args['inc_embed'] . $args['inc_repeat'] );
655
		return $fields;
656
	}
657
658
	/**
659
	 * Called by get_fields_from_transients
660
	 * @since 2.0.1
661
	 */
662
	private static function get_next_transient( &$fields, $base_name, $next = 0 ) {
663
		$name = $next ? $base_name . $next : $base_name;
664
		$next_fields = get_transient( $name );
0 ignored issues
show
Bug introduced by
The function get_transient was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

664
		$next_fields = /** @scrutinizer ignore-call */ get_transient( $name );
Loading history...
665
666
		if ( $next_fields ) {
667
			$fields = array_merge( $fields, $next_fields );
668
669
			if ( count( $next_fields ) >= self::$transient_size ) {
670
				// if this transient is full, check for another
671
				$next++;
672
				self::get_next_transient( $fields, $base_name, $next );
673
			}
674
		}
675
	}
676
677
	/**
678
	 * Save the transients in chunks for large forms
679
	 * @since 2.0.1
680
	 */
681
	private static function set_field_transient( &$fields, $form_id, $next = 0, $args = array() ) {
682
		$base_name = 'frm_form_fields_' . $form_id . $args['inc_embed'] . $args['inc_repeat'];
683
		$field_chunks = array_chunk( $fields, self::$transient_size );
684
685
		foreach ( $field_chunks as $field ) {
686
			$name = $next ? $base_name . $next : $base_name;
687
			$set = set_transient( $name, $field, 60 * 60 * 6 );
0 ignored issues
show
Bug introduced by
The function set_transient was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

687
			$set = /** @scrutinizer ignore-call */ set_transient( $name, $field, 60 * 60 * 6 );
Loading history...
688
			if ( ! $set ) {
689
				// the transient didn't save
690
				if ( $name != $base_name ) {
691
					// if the first saved an others fail, this will show an incmoplete form
692
					self::delete_form_transient( $form_id );
693
				}
694
				return;
695
			}
696
697
			$next++;
698
		}
699
	}
700
701
	public static function is_no_save_field( $type ) {
702
		return in_array( $type, self::no_save_fields() );
703
	}
704
705
	public static function no_save_fields() {
706
		return array( 'divider', 'end_divider', 'captcha', 'break', 'html', 'form' );
707
	}
708
709
	/**
710
	 * Check if this field can hold an array of values
711
	 *
712
	 * @since 2.0.9
713
	 *
714
	 * @param array|object $field
715
	 * @return boolean
716
	 */
717
	public static function is_field_with_multiple_values( $field ) {
718
		if ( ! $field ) {
0 ignored issues
show
introduced by
The condition ! $field can never be false.
Loading history...
719
			return false;
720
		}
721
722
		$field_type = self::get_original_field_type( $field );
723
724
		$is_multi_value_field = (
725
			self::is_checkbox( $field ) ||
726
			$field_type == 'address' ||
727
			self::is_multiple_select( $field )
728
		);
729
730
		return $is_multi_value_field;
731
	}
732
733
	/**
734
	 * @since 3.0
735
	 * @return string
736
	 */
737
	public static function get_field_type( $field ) {
738
		return is_array( $field ) ? $field['type'] : $field->type;
739
	}
740
741
	/**
742
	 * @since 3.0
743
	 * @return string
744
	 */
745
	public static function get_original_field_type( $field ) {
746
		$field_type = self::get_field_type( $field );
747
		$original_type = self::get_option( $field, 'original_type' );
748
749
		if ( ! empty( $original_type ) && $original_type != $field_type ) {
750
			$field_type = $original_type; // check the original type for arrays
751
		}
752
753
		return $field_type;
754
	}
755
756
	/**
757
	 * Check if this is a multiselect dropdown field
758
	 *
759
	 * @since 2.0.9
760
	 * @return boolean
761
	 */
762
	public static function is_multiple_select( $field ) {
763
		$field_type = self::get_field_type( $field );
764
		$data_type = self::get_option( $field, 'data_type' );
765
766
		return self::is_option_true( $field, 'multiple' ) && ( ( $field_type == 'select' || ( $field_type == 'data' && $data_type == 'select' ) ) );
767
	}
768
769
	/**
770
	 * Check if a field is read only. Read only can be set in the field options,
771
	 * but disabled with the shortcode options
772
	 *
773
	 * @since 2.0.9
774
	 */
775
	public static function is_read_only( $field ) {
776
		global $frm_vars;
777
		return ( self::is_option_true( $field, 'read_only' ) && ( ! isset( $frm_vars['readonly'] ) || $frm_vars['readonly'] != 'disabled' ) );
778
	}
779
780
	/**
781
	 * @since 2.0.9
782
	 */
783
	public static function is_required( $field ) {
784
		$required = ( $field['required'] != '0' );
785
		$required = apply_filters( 'frm_is_field_required', $required, $field );
0 ignored issues
show
Bug introduced by
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

785
		$required = /** @scrutinizer ignore-call */ apply_filters( 'frm_is_field_required', $required, $field );
Loading history...
786
		return $required;
787
	}
788
789
	/**
790
	 * @since 2.0.9
791
	 */
792
	public static function is_option_true( $field, $option ) {
793
		if ( is_array( $field ) ) {
794
			return self::is_option_true_in_array( $field, $option );
795
		} else {
796
			return self::is_option_true_in_object( $field, $option );
797
		}
798
	}
799
800
	/**
801
	 * @since 2.0.9
802
	 */
803
	public static function is_option_empty( $field, $option ) {
804
		if ( is_array( $field ) ) {
805
			return self::is_option_empty_in_array( $field, $option );
806
		} else {
807
			return self::is_option_empty_in_object( $field, $option );
808
		}
809
	}
810
811
	public static function is_option_true_in_array( $field, $option ) {
812
		return isset( $field[ $option ] ) && $field[ $option ];
813
	}
814
815
	public static function is_option_true_in_object( $field, $option ) {
816
		return isset( $field->field_options[ $option ] ) && $field->field_options[ $option ];
817
	}
818
819
	public static function is_option_empty_in_array( $field, $option ) {
820
		return ! isset( $field[ $option ] ) || empty( $field[ $option ] );
821
	}
822
823
	public static function is_option_empty_in_object( $field, $option ) {
824
		return ! isset( $field->field_options[ $option ] ) || empty( $field->field_options[ $option ] );
825
	}
826
827
	public static function is_option_value_in_object( $field, $option ) {
828
		return isset( $field->field_options[ $option ] ) && $field->field_options[ $option ] != '';
829
	}
830
831
	/**
832
	 * @since 2.0.18
833
	 */
834
	public static function get_option( $field, $option ) {
835
		if ( is_array( $field ) ) {
836
			$option = self::get_option_in_array( $field, $option );
837
		} else {
838
			$option = self::get_option_in_object( $field, $option );
839
		}
840
		return $option;
841
	}
842
843
	public static function get_option_in_array( $field, $option ) {
844
		return isset( $field[ $option ] ) ? $field[ $option ] : '';
845
	}
846
847
	public static function get_option_in_object( $field, $option ) {
848
		return isset( $field->field_options[ $option ] ) ? $field->field_options[ $option ] : '';
849
	}
850
851
	/**
852
	* @since 2.0.09
853
	*/
854
	public static function is_repeating_field( $field ) {
855
		if ( is_array( $field ) ) {
856
			$is_repeating_field = ( 'divider' == $field['type'] );
857
		} else {
858
			$is_repeating_field = ( 'divider' == $field->type );
859
		}
860
		return ( $is_repeating_field && self::is_option_true( $field, 'repeat' ) );
861
	}
862
863
    /**
864
     * @param string $key
865
     * @return int field id
866
     */
867
	public static function get_id_by_key( $key ) {
868
        $id = FrmDb::get_var( 'frm_fields', array( 'field_key' => sanitize_title( $key ) ) );
0 ignored issues
show
Bug introduced by
The function sanitize_title was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

868
        $id = FrmDb::get_var( 'frm_fields', array( 'field_key' => /** @scrutinizer ignore-call */ sanitize_title( $key ) ) );
Loading history...
869
        return $id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $id also could return the type object|string|array which is incompatible with the documented return type integer.
Loading history...
870
    }
871
872
	/**
873
	 * @param string $id
874
	 * @return string
875
	 */
876
	public static function get_key_by_id( $id ) {
877
		return FrmDb::get_var( 'frm_fields', array( 'id' => $id ), 'field_key' );
0 ignored issues
show
Bug Best Practice introduced by
The expression return FrmDb::get_var('f...' => $id), 'field_key') also could return the type object|array which is incompatible with the documented return type string.
Loading history...
878
	}
879
880
	public static function is_image( $field ) {
881
		$type = self::get_field_type( $field );
882
		return ( $type == 'url' && self::get_option( $field, 'show_image' ) );
883
	}
884
885
	/**
886
	 * Check if field is radio or Dynamic radio
887
	 *
888
	 * @since 3.0
889
	 *
890
	 * @param array|object $field
891
	 * @return boolean true if field type is radio or Dynamic radio
892
	 */
893
	public static function is_radio( $field ) {
894
		return self::is_field_type( $field, 'radio' );
895
	}
896
897
	/**
898
	 * Check if field is checkbox or Dynamic checkbox
899
	 *
900
	 * @since 3.0
901
	 *
902
	 * @param array|object $field
903
	 * @return boolean true if field type is checkbox or Dynamic checkbox
904
	 */
905
	public static function is_checkbox( $field ) {
906
		return self::is_field_type( $field, 'checkbox' );
907
	}
908
909
	/**
910
	 * Check if field is checkbox or radio
911
	 *
912
	 * @since 3.0
913
	 *
914
	 * @param array|object $field
915
	 * @param string $is_type Options include radio, checkbox, text
916
	 * @return boolean true if field type is checkbox or Dynamic checkbox
917
	 */
918
	public static function is_field_type( $field, $is_type ) {
919
		$field_type = self::get_original_field_type( $field );
920
		$data_type = self::get_option( $field, 'data_type' );
921
922
		return (
923
			$is_type === $field_type ||
924
			( 'data' === $field_type && $is_type === $data_type ) ||
925
			( 'lookup' === $field_type && $is_type === $data_type )
926
		);
927
	}
928
929
	/**
930
	 * Check if a field might by taller than other fields
931
	 * @since 3.0
932
	 *
933
	 * @param array|object $field
934
	 *
935
	 * @return bool
936
	 */
937
	public static function is_tall_field( $field ) {
938
		$field_type = FrmField::get_field_type( $field );
939
		return FrmFieldFactory::field_has_property( $field_type, 'is_tall' );
940
	}
941
}
942