Completed
Push — master ( 807d29...7c5184 )
by Stephanie
06:58
created

FrmForm::validate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
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 FrmForm {
7
8
    /**
9
     * @return int|boolean id on success or false on failure
10
     */
11
    public static function create( $values ) {
12
        global $wpdb;
13
14
		$new_values = array(
15
			'form_key'      => FrmAppHelper::get_unique_key( $values['form_key'], $wpdb->prefix . 'frm_forms', 'form_key' ),
16
			'name'          => $values['name'],
17
			'description'   => $values['description'],
18
			'status'        => isset( $values['status'] ) ? $values['status'] : 'draft',
19
			'logged_in'     => isset( $values['logged_in'] ) ? $values['logged_in'] : 0,
20
			'is_template'   => isset( $values['is_template'] ) ? (int) $values['is_template'] : 0,
21
			'parent_form_id' => isset( $values['parent_form_id'] ) ? absint( $values['parent_form_id'] ) : 0,
22
			'editable'      => isset( $values['editable'] ) ? (int) $values['editable'] : 0,
23
			'default_template' => isset( $values['default_template'] ) ? (int) $values['default_template'] : 0,
24
			'created_at'    => isset( $values['created_at'] ) ? $values['created_at'] : current_time( 'mysql', 1 ),
25
		);
26
27
		$options = isset( $values['options'] ) ? (array) $values['options'] : array();
28
		FrmFormsHelper::fill_form_options( $options, $values );
29
30
		$options['before_html'] = isset( $values['options']['before_html'] ) ? $values['options']['before_html'] : FrmFormsHelper::get_default_html( 'before' );
31
		$options['after_html'] = isset( $values['options']['after_html'] ) ? $values['options']['after_html'] : FrmFormsHelper::get_default_html( 'after' );
32
		$options['submit_html'] = isset( $values['options']['submit_html'] ) ? $values['options']['submit_html'] : FrmFormsHelper::get_default_html( 'submit' );
33
34
		$options = apply_filters( 'frm_form_options_before_update', $options, $values );
35
		$new_values['options'] = serialize( $options );
36
37
        //if(isset($values['id']) && is_numeric($values['id']))
38
        //    $new_values['id'] = $values['id'];
39
40
		$wpdb->insert( $wpdb->prefix . 'frm_forms', $new_values );
41
42
        $id = $wpdb->insert_id;
43
44
		// Clear form caching
45
		self::clear_form_cache();
46
47
        return $id;
48
    }
49
50
    /**
51
     * @return int|boolean ID on success or false on failure
52
     */
53
    public static function duplicate( $id, $template = false, $copy_keys = false, $blog_id = false ) {
54
        global $wpdb;
55
56
        $values = self::getOne( $id, $blog_id );
57
        if ( ! $values ) {
58
            return false;
59
        }
60
61
        $new_key = $copy_keys ? $values->form_key : '';
62
63
        $new_values = array(
64
			'form_key'      => FrmAppHelper::get_unique_key( $new_key, $wpdb->prefix . 'frm_forms', 'form_key' ),
65
            'name'          => $values->name,
66
            'description'   => $values->description,
67
            'status'        => $template ? 'published' : 'draft',
68
            'logged_in'     => $values->logged_in ? $values->logged_in : 0,
69
            'editable'      => $values->editable ? $values->editable : 0,
70
			'created_at'    => current_time( 'mysql', 1 ),
71
            'is_template'   => $template ? 1 : 0,
72
        );
73
74
        if ( $blog_id ) {
75
            $new_values['status'] = 'published';
76
			$new_options = maybe_unserialize( $values->options );
77
			$new_options['email_to'] = get_option( 'admin_email' );
78
            $new_options['copy'] = false;
79
            $new_values['options'] = $new_options;
80
        } else {
81
            $new_values['options'] = $values->options;
82
        }
83
84
		if ( is_array( $new_values['options'] ) ) {
85
			$new_values['options'] = serialize( $new_values['options'] );
86
		}
87
88
		$query_results = $wpdb->insert( $wpdb->prefix . 'frm_forms', $new_values );
89
90
        if ( $query_results ) {
91
			// Clear form caching
92
			self::clear_form_cache();
93
94
            $form_id = $wpdb->insert_id;
95
			FrmField::duplicate( $id, $form_id, $copy_keys, $blog_id );
96
97
            // update form settings after fields are created
98
			do_action( 'frm_after_duplicate_form', $form_id, $new_values, array( 'old_id' => $id ) );
99
            return $form_id;
100
        }
101
102
        return false;
103
    }
104
105
	public static function after_duplicate( $form_id, $values ) {
106
		$new_opts = maybe_unserialize( $values['options'] );
107
		$values['options'] = $new_opts;
108
109
		if ( isset( $new_opts['success_msg'] ) ) {
110
			$new_opts['success_msg'] = FrmFieldsHelper::switch_field_ids( $new_opts['success_msg'] );
111
		}
112
113
		$new_opts = apply_filters( 'frm_after_duplicate_form_values', $new_opts, $form_id );
114
115
        if ( $new_opts != $values['options'] ) {
116
            global $wpdb;
117
			$wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => maybe_serialize( $new_opts ) ), array( 'id' => $form_id ) );
118
        }
119
    }
120
121
    /**
122
     * @return int|boolean
123
     */
124
    public static function update( $id, $values, $create_link = false ) {
125
        global $wpdb;
126
127
        if ( ! isset( $values['status'] ) && ( $create_link || isset( $values['options'] ) || isset( $values['item_meta'] ) || isset( $values['field_options'] ) ) ) {
128
            $values['status'] = 'published';
129
        }
130
131
		if ( isset( $values['form_key'] ) ) {
132
			$values['form_key'] = FrmAppHelper::get_unique_key( $values['form_key'], $wpdb->prefix . 'frm_forms', 'form_key', $id );
133
        }
134
135
		$form_fields = array( 'form_key', 'name', 'description', 'status', 'parent_form_id' );
136
137
		$new_values = self::set_update_options( array(), $values );
138
139
        foreach ( $values as $value_key => $value ) {
140
			if ( $value_key && in_array( $value_key, $form_fields ) ) {
141
				$new_values[ $value_key ] = $value;
142
            }
143
        }
144
145
        if ( isset( $values['new_status'] ) && ! empty( $values['new_status'] ) ) {
146
            $new_values['status'] = $values['new_status'];
147
        }
148
149
        if ( ! empty( $new_values ) ) {
150
			$query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', $new_values, array( 'id' => $id ) );
151
            if ( $query_results ) {
152
				self::clear_form_cache();
153
            }
154
        } else {
155
            $query_results = true;
156
        }
157
		unset( $new_values );
158
159
		$values = self::update_fields( $id, $values );
160
161
		do_action( 'frm_update_form', $id, $values );
162
		do_action( 'frm_update_form_' . $id, $values );
163
164
        return $query_results;
165
    }
166
167
    /**
168
     * @return array
169
     */
170
	public static function set_update_options( $new_values, $values ) {
171
		if ( ! isset( $values['options'] ) ) {
172
            return $new_values;
173
        }
174
175
		$options = isset( $values['options'] ) ? (array) $values['options'] : array();
176
		FrmFormsHelper::fill_form_options( $options, $values );
177
178
		$options['custom_style'] = isset( $values['options']['custom_style'] ) ? $values['options']['custom_style'] : 0;
179
		$options['before_html'] = isset( $values['options']['before_html'] ) ? $values['options']['before_html'] : FrmFormsHelper::get_default_html( 'before' );
180
		$options['after_html'] = isset( $values['options']['after_html'] ) ? $values['options']['after_html'] : FrmFormsHelper::get_default_html( 'after' );
181
		$options['submit_html'] = ( isset( $values['options']['submit_html'] ) && '' !== $values['options']['submit_html'] ) ? $values['options']['submit_html'] : FrmFormsHelper::get_default_html( 'submit' );
182
183
		$options = apply_filters( 'frm_form_options_before_update', $options, $values );
184
		$new_values['options'] = serialize( $options );
185
186
		return $new_values;
187
    }
188
189
190
    /**
191
     * @return array
192
     */
193
	public static function update_fields( $id, $values ) {
194
195
		if ( ! isset( $values['item_meta'] ) && ! isset( $values['field_options'] ) ) {
196
            return $values;
197
        }
198
199
		$all_fields = FrmField::get_all_for_form( $id );
200
		if ( empty( $all_fields ) ) {
201
			return $values;
202
		}
203
204
		if ( ! isset( $values['item_meta'] ) ) {
205
			$values['item_meta'] = array();
206
		}
207
208
        $field_array = array();
209
        $existing_keys = array_keys( $values['item_meta'] );
210
        foreach ( $all_fields as $fid ) {
211
			if ( ! in_array( $fid->id, $existing_keys ) && ( isset( $values['frm_fields_submitted'] ) && in_array( $fid->id, $values['frm_fields_submitted'] ) ) || isset( $values['options'] ) ) {
212
				$values['item_meta'][ $fid->id ] = '';
213
            }
214
			$field_array[ $fid->id ] = $fid;
215
        }
216
		unset( $all_fields );
217
218
        foreach ( $values['item_meta'] as $field_id => $default_value ) {
219
			if ( isset( $field_array[ $field_id ] ) ) {
220
				$field = $field_array[ $field_id ];
221
            } else {
222
				$field = FrmField::getOne( $field_id );
223
            }
224
225
            if ( ! $field ) {
226
                continue;
227
            }
228
229
			$is_settings_page = ( isset( $values['options'] ) || isset( $values['field_options'][ 'custom_html_' . $field_id ] ) );
230
			if ( $is_settings_page ) {
231
				self::get_settings_page_html( $values, $field );
232
233
				if ( ! defined( 'WP_IMPORTING' ) ) {
234
					continue;
235
				}
236
			}
237
238
			//updating the form
239
			$update_options = FrmFieldsHelper::get_default_field_options_from_field( $field );
240
			unset( $update_options['custom_html'] ); // don't check for POST html
241
			$update_options = apply_filters( 'frm_field_options_to_update', $update_options );
242
243
			foreach ( $update_options as $opt => $default ) {
244
				$field->field_options[ $opt ] = isset( $values['field_options'][ $opt . '_' . $field_id ] ) ? $values['field_options'][ $opt . '_' . $field_id ] : $default;
245
				if ( is_string( $field->field_options[ $opt ] ) ) {
246
					$field->field_options[ $opt ] = trim( FrmAppHelper::kses( $field->field_options[ $opt ], 'all' ) );
247
				}
248
            }
249
250
			$field->field_options = apply_filters( 'frm_update_field_options', $field->field_options, $field, $values );
251
			$default_value = maybe_serialize( $values['item_meta'][ $field_id ] );
252
253
			$new_field = array(
254
				'field_options' => $field->field_options,
255
				'default_value' => $default_value,
256
			);
257
258
			self::prepare_field_update_values( $field, $values, $new_field );
259
260
			FrmField::update( $field_id, $new_field );
261
262
			FrmField::delete_form_transient( $field->form_id );
263
        }
264
		self::clear_form_cache();
265
266
        return $values;
267
    }
268
269
	/**
270
	 * updating the settings page
271
	 */
272
	private static function get_settings_page_html( $values, &$field ) {
273
		if ( isset( $values['field_options'][ 'custom_html_' . $field->id ] ) ) {
274
			$prev_opts = array();
275
			$fallback_html = isset( $field->field_options['custom_html'] ) ? $field->field_options['custom_html'] : FrmFieldsHelper::get_default_html( $field->type );
276
			$field->field_options['custom_html'] = isset( $values['field_options'][ 'custom_html_' . $field->id ] ) ? $values['field_options'][ 'custom_html_' . $field->id ] : $fallback_html;
277
		} elseif ( $field->type == 'hidden' || $field->type == 'user_id' ) {
278
			$prev_opts = $field->field_options;
279
		}
280
281
		if ( isset( $prev_opts ) ) {
282
			$field->field_options = apply_filters( 'frm_update_form_field_options', $field->field_options, $field, $values );
283
			if ( $prev_opts != $field->field_options ) {
284
				FrmField::update( $field->id, array( 'field_options' => $field->field_options ) );
285
			}
286
		}
287
	}
288
289
	private static function prepare_field_update_values( $field, $values, &$new_field ) {
290
		$field_cols = array(
291
			'field_key'   => '',
292
			'required'    => false,
293
			'type'        => '',
294
			'description' => '',
295
			'options'     => '',
296
			'name'        => '',
297
		);
298
		foreach ( $field_cols as $col => $default ) {
299
			$default = ( $default === '' ) ? $field->{$col} : $default;
300
			$new_field[ $col ] = isset( $values['field_options'][ $col . '_' . $field->id ] ) ? $values['field_options'][ $col . '_' . $field->id ] : $default;
301
		}
302
	}
303
304
    /**
305
     * @param string $status
306
     * @return int|boolean
307
     */
308
	public static function set_status( $id, $status ) {
309
        if ( 'trash' == $status ) {
310
			return self::trash( $id );
311
        }
312
313
		$statuses  = array( 'published', 'draft', 'trash' );
314
        if ( ! in_array( $status, $statuses ) ) {
315
            return false;
316
        }
317
318
        global $wpdb;
319
320
		if ( is_array( $id ) ) {
321
			$where = array(
322
				'id' => $id,
323
				'parent_form_id' => $id,
324
				'or' => 1,
325
			);
326
			FrmDb::get_where_clause_and_values( $where );
327
			array_unshift( $where['values'], $status );
328
329
			$query_results = $wpdb->query( $wpdb->prepare( 'UPDATE ' . $wpdb->prefix . 'frm_forms SET status = %s ' . $where['where'], $where['values'] ) ); // WPCS: unprepared SQL ok.
330
        } else {
331
			$query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'status' => $status ), array( 'id' => $id ) );
332
			$wpdb->update( $wpdb->prefix . 'frm_forms', array( 'status' => $status ), array( 'parent_form_id' => $id ) );
333
        }
334
335
        if ( $query_results ) {
336
			self::clear_form_cache();
337
        }
338
339
        return $query_results;
340
    }
341
342
    /**
343
     * @return int|boolean
344
     */
345
	public static function trash( $id ) {
346
        if ( ! EMPTY_TRASH_DAYS ) {
347
            return self::destroy( $id );
348
        }
349
350
		$form = self::getOne( $id );
351
        if ( ! $form ) {
352
            return false;
353
        }
354
355
        $options = $form->options;
356
        $options['trash_time'] = time();
357
358
		global $wpdb;
359
		$query_results = $wpdb->update(
360
			$wpdb->prefix . 'frm_forms',
361
			array(
362
				'status'  => 'trash',
363
				'options' => serialize( $options ),
364
			),
365
			array(
366
				'id' => $id,
367
			)
368
		);
369
370
		$wpdb->update(
371
			$wpdb->prefix . 'frm_forms',
372
			array(
373
				'status'  => 'trash',
374
				'options' => serialize( $options ),
375
			),
376
			array(
377
				'parent_form_id' => $id,
378
			)
379
		);
380
381
        if ( $query_results ) {
382
			self::clear_form_cache();
383
        }
384
385
        return $query_results;
386
    }
387
388
    /**
389
     * @return int|boolean
390
     */
391
	public static function destroy( $id ) {
392
        global $wpdb;
393
394
		$form = self::getOne( $id );
395
        if ( ! $form ) {
396
            return false;
397
        }
398
		$id = $form->id;
399
400
        // Disconnect the entries from this form
401
		$entries = FrmDb::get_col( $wpdb->prefix . 'frm_items', array( 'form_id' => $id ) );
402
		foreach ( $entries as $entry_id ) {
0 ignored issues
show
Bug introduced by
The expression $entries of type array|null|string|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
403
			FrmEntry::destroy( $entry_id );
404
			unset( $entry_id );
405
		}
406
407
        // Disconnect the fields from this form
408
		$wpdb->query( $wpdb->prepare( 'DELETE fi FROM ' . $wpdb->prefix . 'frm_fields AS fi LEFT JOIN ' . $wpdb->prefix . 'frm_forms fr ON (fi.form_id = fr.id) WHERE fi.form_id=%d OR parent_form_id=%d', $id, $id ) );
409
410
		$query_results = $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_forms WHERE id=%d OR parent_form_id=%d', $id, $id ) );
411
        if ( $query_results ) {
412
            // Delete all form actions linked to this form
413
            $action_control = FrmFormActionsController::get_form_actions( 'email' );
414
			$action_control->destroy( $id, 'all' );
415
416
			// Clear form caching
417
			self::clear_form_cache();
418
419
			do_action( 'frm_destroy_form', $id );
420
			do_action( 'frm_destroy_form_' . $id );
421
        }
422
423
        return $query_results;
424
    }
425
426
	/**
427
	 * Delete trashed forms based on how long they have been trashed
428
	 * @return int The number of forms deleted
429
	 */
430
	public static function scheduled_delete( $delete_timestamp = '' ) {
431
		global $wpdb;
432
433
		$trash_forms = FrmDb::get_results( $wpdb->prefix . 'frm_forms', array( 'status' => 'trash' ), 'id, options' );
434
435
		if ( ! $trash_forms ) {
436
			return;
437
		}
438
439
		if ( empty( $delete_timestamp ) ) {
440
			$delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
441
		}
442
443
		$count = 0;
444
		foreach ( $trash_forms as $form ) {
0 ignored issues
show
Bug introduced by
The expression $trash_forms of type array|string|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
445
			$form->options = maybe_unserialize( $form->options );
446
			if ( ! isset( $form->options['trash_time'] ) || $form->options['trash_time'] < $delete_timestamp ) {
447
				self::destroy( $form->id );
448
				$count++;
449
			}
450
451
			unset( $form );
452
		}
453
		return $count;
454
	}
455
456
    /**
457
     * @return string form name
458
     */
459
    public static function getName( $id ) {
0 ignored issues
show
Coding Style introduced by
The function name getName is in camel caps, but expected get_name instead as per the coding standard.
Loading history...
460
		$form = FrmDb::check_cache( $id, 'frm_form' );
461
        if ( $form ) {
462
			$r = stripslashes( $form->name );
463
            return $r;
464
        }
465
466
        $query_key = is_numeric( $id ) ? 'id' : 'form_key';
467
        $r = FrmDb::get_var( 'frm_forms', array( $query_key => $id ), 'name' );
468
		$r = stripslashes( $r );
469
470
        return $r;
471
    }
472
473
    /**
474
	 * @since 3.0
475
     * @param string $key
476
     * @return int form id
477
     */
478
	public static function get_id_by_key( $key ) {
479
		return (int) FrmDb::get_var( 'frm_forms', array( 'form_key' => sanitize_title( $key ) ) );
480
    }
481
482
	/**
483
	 * @deprecated 3.0
484
	 * @codeCoverageIgnore
485
	 *
486
     * @param string $key
487
     * @return int form id
488
     */
489
	public static function getIdByKey( $key ) {
0 ignored issues
show
Coding Style introduced by
The function name getIdByKey is in camel caps, but expected get_id_by_key instead as per the coding standard.
Loading history...
490
		_deprecated_function( __METHOD__, '3.0', 'FrmForm::get_id_by_key' );
491
		return self::get_id_by_key( $key );
492
    }
493
494
    /**
495
	 * @since 3.0
496
     * @param int $id
497
     * @return string form key
498
     */
499
	public static function get_key_by_id( $id ) {
500
        $id = (int) $id;
501
		$cache = FrmDb::check_cache( $id, 'frm_form' );
502
        if ( $cache ) {
503
            return $cache->form_key;
504
        }
505
506
        $key = FrmDb::get_var( 'frm_forms', array( 'id' => $id ), 'form_key' );
507
508
        return $key;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $key; (array|null|string|object) is incompatible with the return type documented by FrmForm::get_key_by_id of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
509
    }
510
511
	/**
512
	 * @deprecated 3.0
513
	 * @codeCoverageIgnore
514
	 */
515
	public static function getKeyById( $id ) {
0 ignored issues
show
Coding Style introduced by
The function name getKeyById is in camel caps, but expected get_key_by_id instead as per the coding standard.
Loading history...
516
		_deprecated_function( __METHOD__, '3.0', 'FrmForm::get_key_by_id' );
517
		return self::get_key_by_id( $id );
518
	}
519
520
	/**
521
	 * If $form is numeric, get the form object
522
	 * @param object|int $form
523
	 * @since 2.0.9
524
	 */
525
	public static function maybe_get_form( &$form ) {
526
		if ( ! is_object( $form ) && ! is_array( $form ) && ! empty( $form ) ) {
527
			$form = self::getOne( $form );
528
		}
529
	}
530
531
    /**
532
     * @return object form
533
     */
534
    public static function getOne( $id, $blog_id = false ) {
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...
535
        global $wpdb;
536
537
        if ( $blog_id && is_multisite() ) {
538
            global $wpmuBaseTablePrefix;
539
			$prefix = $wpmuBaseTablePrefix ? $wpmuBaseTablePrefix . $blog_id . '_' : $wpdb->get_blog_prefix( $blog_id );
540
541
			$table_name = $prefix . 'frm_forms';
542
        } else {
543
			$table_name = $wpdb->prefix . 'frm_forms';
544
			$cache = wp_cache_get( $id, 'frm_form' );
545
            if ( $cache ) {
546
				if ( isset( $cache->options ) ) {
547
					$cache->options = maybe_unserialize( $cache->options );
548
                }
549
550
				return stripslashes_deep( $cache );
551
            }
552
        }
553
554
		if ( is_numeric( $id ) ) {
555
            $where = array( 'id' => $id );
556
        } else {
557
            $where = array( 'form_key' => $id );
558
        }
559
560
        $results = FrmDb::get_row( $table_name, $where );
561
562 View Code Duplication
		if ( isset( $results->options ) ) {
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...
563
			FrmDb::set_cache( $results->id, $results, 'frm_form' );
564
			$results->options = maybe_unserialize( $results->options );
565
        }
566
		return stripslashes_deep( $results );
567
    }
568
569
    /**
570
     * @return object|array of objects
571
     */
572
	public static function getAll( $where = array(), $order_by = '', $limit = '' ) {
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...
573
		if ( is_array( $where ) && ! empty( $where ) ) {
574
			if ( isset( $where['is_template'] ) && $where['is_template'] && ! isset( $where['status'] ) ) {
575
				// don't get trashed templates
576
				$where['status'] = array( null, '', 'published' );
577
			}
578
579
			$results = FrmDb::get_results( 'frm_forms', $where, '*', array(
580
				'order_by' => $order_by,
581
				'limit'    => $limit,
582
			) );
583
		} else {
584
			global $wpdb;
585
586
			// the query has already been prepared if this is not an array
587
			$query = 'SELECT * FROM ' . $wpdb->prefix . 'frm_forms' . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . FrmDb::esc_order( $order_by ) . FrmDb::esc_limit( $limit );
588
			$results = $wpdb->get_results( $query ); // WPCS: unprepared SQL ok.
589
		}
590
591 View Code Duplication
		if ( $results ) {
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...
592
			foreach ( $results as $result ) {
593
				FrmDb::set_cache( $result->id, $result, 'frm_form' );
594
				$result->options = maybe_unserialize( $result->options );
595
			}
596
		}
597
598
		if ( $limit == ' LIMIT 1' || $limit == 1 ) {
599
			// return the first form object if we are only getting one form
600
			$results = reset( $results );
601
		}
602
603
		return stripslashes_deep( $results );
604
    }
605
606
	/**
607
	 * Get all published forms
608
	 * @since 2.0
609
	 * @return array of forms
610
	 */
611
	public static function get_published_forms( $query = array(), $limit = 999, $inc_children = 'exclude' ) {
612
		$query['is_template'] = 0;
613
		$query['status'] = array( null, '', 'published' );
614
		if ( $inc_children == 'exclude' ) {
615
			$query['parent_form_id'] = array( null, 0 );
616
		}
617
618
		$forms = self::getAll( $query, 'name', $limit );
619
		return $forms;
620
	}
621
622
    /**
623
     * @return int count of forms
624
     */
625
    public static function get_count() {
626
    	global $wpdb;
627
628
    	$cache_key = 'frm_form_counts';
629
630
    	$counts = wp_cache_get( $cache_key, 'frm_form' );
631
    	if ( false !== $counts ) {
632
    	    return $counts;
633
    	}
634
635
		$results = (array) FrmDb::get_results( 'frm_forms', array(
636
			'or' => 1,
637
			'parent_form_id' => null,
638
			'parent_form_id <' => 0,
639
		), 'status, is_template' );
640
641
		$statuses = array( 'published', 'draft', 'template', 'trash' );
642
    	$counts = array_fill_keys( $statuses, 0 );
643
644
    	foreach ( $results as $row ) {
645
            if ( 'trash' != $row->status ) {
646
    	        if ( $row->is_template ) {
647
					$counts['template']++;
648
    	        } else {
649
					$counts['published']++;
650
    	        }
651
    	    } else {
652
				$counts['trash']++;
653
        	}
654
655
    	    if ( 'draft' == $row->status ) {
656
				$counts['draft']++;
657
    	    }
658
659
			unset( $row );
660
    	}
661
662
    	$counts = (object) $counts;
663
		FrmDb::set_cache( $cache_key, $counts, 'frm_form' );
664
665
    	return $counts;
666
    }
667
668
	/**
669
	 * Clear form caching
670
	 * Called when a form is created, updated, duplicated, or deleted
671
	 * or when the form status is changed
672
	 *
673
	 * @since 2.0.4
674
	 */
675
	public static function clear_form_cache() {
676
		FrmDb::cache_delete_group( 'frm_form' );
677
	}
678
679
    /**
680
     * @return array of errors
681
     */
682
	public static function validate( $values ) {
683
        $errors = array();
684
685
		return apply_filters( 'frm_validate_form', $errors, $values );
686
    }
687
688
	public static function get_params( $form = null ) {
689
		global $frm_vars;
690
691
		if ( ! $form ) {
692
			$form = self::getAll( array(), 'name', 1 );
693
		} else {
694
			self::maybe_get_form( $form );
695
		}
696
697
		if ( isset( $frm_vars['form_params'] ) && is_array( $frm_vars['form_params'] ) && isset( $frm_vars['form_params'][ $form->id ] ) ) {
698
			return $frm_vars['form_params'][ $form->id ];
699
		}
700
701
		$action_var = isset( $_REQUEST['frm_action'] ) ? 'frm_action' : 'action'; // WPCS: CSRF ok.
702
		$action = apply_filters( 'frm_show_new_entry_page', FrmAppHelper::get_param( $action_var, 'new', 'get', 'sanitize_title' ), $form );
703
704
		$default_values = array(
705
			'id'        => '',
706
			'form_name' => '',
707
			'paged'     => 1,
708
			'form'      => $form->id,
709
			'form_id'   => $form->id,
710
			'field_id'  => '',
711
			'search'    => '',
712
			'sort'      => '',
713
			'sdir'      => '',
714
			'action'    => $action,
715
		);
716
717
		$values = array();
718
		$values['posted_form_id'] = FrmAppHelper::get_param( 'form_id', '', 'get', 'absint' );
719
		if ( ! $values['posted_form_id'] ) {
720
			$values['posted_form_id'] = FrmAppHelper::get_param( 'form', '', 'get', 'absint' );
721
		}
722
723
		if ( $form->id == $values['posted_form_id'] ) {
724
			//if there are two forms on the same page, make sure not to submit both
725
			foreach ( $default_values as $var => $default ) {
726
				if ( $var == 'action' ) {
727
					$values[ $var ] = FrmAppHelper::get_param( $action_var, $default, 'get', 'sanitize_title' );
728
				} else {
729
					$values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
730
				}
731
				unset( $var, $default );
732
			}
733
		} else {
734
			foreach ( $default_values as $var => $default ) {
735
				$values[ $var ] = $default;
736
				unset( $var, $default );
737
			}
738
		}
739
740
		if ( in_array( $values['action'], array( 'create', 'update' ) ) && ( ! $_POST || ( ! isset( $_POST['action'] ) && ! isset( $_POST['frm_action'] ) ) ) ) { // WPCS: CSRF ok.
741
			$values['action'] = 'new';
742
		}
743
744
		return $values;
745
	}
746
747
	public static function list_page_params() {
748
		$values = array();
749
		$defaults = array(
750
			'template' => 0,
751
			'id'     => '',
752
			'paged'  => 1,
753
			'form'   => '',
754
			'search' => '',
755
			'sort'   => '',
756
			'sdir'   => '',
757
		);
758
		foreach ( $defaults as $var => $default ) {
759
			$values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
760
		}
761
762
		return $values;
763
	}
764
765
	public static function get_admin_params( $form = null ) {
766
		$form_id = $form;
767
		if ( $form === null ) {
768
			$form_id = FrmForm::get_current_form_id();
769
		} else if ( $form && is_object( $form ) ) {
770
			$form_id = $form->id;
771
		}
772
773
		$values = array();
774
		$defaults = array(
775
			'id'        => '',
776
			'form_name' => '',
777
			'paged'     => 1,
778
			'form'      => $form_id,
779
			'field_id'  => '',
780
			'search'    => '',
781
			'sort'      => '',
782
			'sdir'      => '',
783
			'fid'       => '',
784
			'keep_post' => '',
785
		);
786
		foreach ( $defaults as $var => $default ) {
787
			$values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
788
		}
789
790
		return $values;
791
	}
792
793
	public static function get_current_form_id( $default_form = 'none' ) {
794
		if ( 'first' == $default_form ) {
795
			$form = self::get_current_form();
796
		} else {
797
			$form = self::maybe_get_current_form();
798
		}
799
		$form_id = $form ? $form->id : 0;
800
801
		return $form_id;
802
	}
803
804
	public static function maybe_get_current_form( $form_id = 0 ) {
805
		global $frm_vars;
806
807
		if ( isset( $frm_vars['current_form'] ) && $frm_vars['current_form'] && ( ! $form_id || $form_id == $frm_vars['current_form']->id ) ) {
808
			return $frm_vars['current_form'];
809
		}
810
811
		$form_id = FrmAppHelper::get_param( 'form', $form_id, 'get', 'absint' );
812
		if ( $form_id ) {
813
			$form_id = self::set_current_form( $form_id );
814
		}
815
		return $form_id;
816
	}
817
818
	public static function get_current_form( $form_id = 0 ) {
819
		$form = self::maybe_get_current_form( $form_id );
820
		if ( is_numeric( $form ) ) {
821
			 $form = self::set_current_form( $form );
822
		}
823
		return $form;
824
	}
825
826
	public static function set_current_form( $form_id ) {
827
		global $frm_vars;
828
829
		$query = array();
830
		if ( $form_id ) {
831
			$query['id'] = $form_id;
832
		}
833
834
		$frm_vars['current_form'] = self::get_published_forms( $query, 1 );
835
836
		return $frm_vars['current_form'];
837
	}
838
839
	public static function is_form_loaded( $form, $this_load, $global_load ) {
840
		global $frm_vars;
841
		$small_form = new stdClass();
842
		foreach ( array( 'id', 'form_key', 'name' ) as $var ) {
843
			$small_form->{$var} = $form->{$var};
844
			unset( $var );
845
		}
846
847
		$frm_vars['forms_loaded'][] = $small_form;
848
849
		if ( $this_load && empty( $global_load ) ) {
850
			$global_load = true;
851
			$frm_vars['load_css'] = true;
852
		}
853
854
		return ( ( ! isset( $frm_vars['css_loaded'] ) || ! $frm_vars['css_loaded'] ) && $global_load );
855
	}
856
857
	public static function show_submit( $form ) {
858
		$show = ( ! $form->is_template && $form->status == 'published' && ! FrmAppHelper::is_admin() );
859
		$show = apply_filters( 'frm_show_submit_button', $show, $form );
860
		return $show;
861
	}
862
863
	/**
864
	 * @since 2.3
865
	 */
866
	public static function get_option( $atts ) {
867
		$form = $atts['form'];
868
		return isset( $form->options[ $atts['option'] ] ) ? $form->options[ $atts['option'] ] : $atts['default'];
869
	}
870
}
871