Completed
Push — master ( b3ff26...a88860 )
by Stephanie
02:55
created

FrmEntry   D

Complexity

Total Complexity 150

Size/Duplication

Total Lines 919
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 919
rs 4.4444
c 0
b 0
f 0
wmc 150
lcom 1
cbo 4

48 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 5 1
A create_entry() 0 12 3
C is_duplicate() 0 56 13
B is_duplicate_check_needed() 0 18 6
B duplicate() 0 34 4
A update() 0 5 1
A update_entry() 0 16 2
A destroy() 0 19 2
A update_form() 0 9 3
A clear_cache() 0 6 1
A get_new_entry_name() 0 3 3
A maybe_get_entry() 0 5 3
B getOne() 0 25 4
B get_meta() 0 38 6
A exists() 0 17 4
D getAll() 0 80 18
A getRecordCount() 0 19 3
A getPageCount() 0 12 3
A before_insert_entry_in_database() 0 12 2
A continue_to_create_entry() 0 10 2
A sanitize_entry_post() 0 17 1
B package_entry_data() 0 30 4
A get_entry_value() 0 3 2
A get_ip() 0 11 4
B get_is_draft_value() 0 3 5
A get_created_at() 0 3 1
A get_updated_at() 0 9 2
A get_entry_description() 0 12 3
B get_entry_user_id() 0 10 5
A insert_entry_into_database() 0 13 2
A add_new_entry_to_frm_vars() 0 9 2
A maybe_add_entry_metas() 0 5 2
A after_entry_created_actions() 0 7 4
A after_insert_entry_in_database() 0 10 1
B before_update_entry() 0 15 6
C package_entry_to_update() 0 31 7
A after_update_entry() 0 19 4
A create_entry_from_xml() 0 5 1
A update_entry_from_xml() 0 5 1
A get_id_by_key() 0 4 1
A validate() 0 4 1
A validate_field() 0 4 1
A validate_url_field() 0 4 1
A validate_email_field() 0 4 1
A validate_recaptcha() 0 4 1
A spam_check() 0 4 1
A blacklist_check() 0 4 1
A akismet() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like FrmEntry often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FrmEntry, and based on these observations, apply Extract Interface, too.

1
<?php
2
if ( ! defined('ABSPATH') ) {
3
	die( 'You are not allowed to call this page directly.' );
4
}
5
6
class FrmEntry {
7
8
	/**
9
	* Create a new entry
10
	*
11
	* @param array $values
12
	* @return int | boolean $entry_id
13
	*/
14
	public static function create( $values ) {
15
		$entry_id = self::create_entry( $values, 'standard' );
16
17
		return $entry_id;
18
	}
19
20
	/**
21
	* Create a new entry with some differences depending on type
22
	*
23
	* @param array $values
24
	* @param string $type
25
	* @return int | boolean $entry_id
26
	*/
27
	private static function create_entry( $values, $type ) {
28
		$new_values = self::before_insert_entry_in_database( $values, $type );
29
30
		// Don't check XML entries for duplicates
31
		if ( $type != 'xml' && self::is_duplicate( $new_values, $values ) ) {
32
			return false;
33
		}
34
35
		$entry_id = self::continue_to_create_entry( $values, $new_values );
36
37
		return $entry_id;
38
	}
39
40
    /**
41
     * check for duplicate entries created in the last minute
42
     * @return boolean
43
     */
44
	public static function is_duplicate( $new_values, $values ) {
45
		$duplicate_entry_time = apply_filters( 'frm_time_to_check_duplicates', 60, $new_values );
46
47
		if ( false === self::is_duplicate_check_needed( $values, $duplicate_entry_time ) ) {
48
			return false;
49
		}
50
51
        $check_val = $new_values;
52
		$check_val['created_at >'] = date( 'Y-m-d H:i:s', ( strtotime( $new_values['created_at'] ) - absint( $duplicate_entry_time ) ) );
53
54
		unset( $check_val['created_at'], $check_val['updated_at'] );
55
		unset( $check_val['is_draft'], $check_val['id'], $check_val['item_key'] );
56
57
        if ( $new_values['item_key'] == $new_values['name'] ) {
58
            unset($check_val['name']);
59
        }
60
61
        global $wpdb;
62
		$entry_exists = FrmDb::get_col( $wpdb->prefix . 'frm_items', $check_val, 'id', array( 'order_by' => 'created_at DESC' ) );
63
64
        if ( ! $entry_exists || empty($entry_exists) || ! isset($values['item_meta']) ) {
65
            return false;
66
        }
67
68
        $is_duplicate = false;
69
        foreach ( $entry_exists as $entry_exist ) {
0 ignored issues
show
Bug introduced by
The expression $entry_exists 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...
70
            $is_duplicate = true;
71
72
            //add more checks here to make sure it's a duplicate
73
            $metas = FrmEntryMeta::get_entry_meta_info($entry_exist);
74
            $field_metas = array();
75
            foreach ( $metas as $meta ) {
0 ignored issues
show
Bug introduced by
The expression $metas 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...
76
				$field_metas[ $meta->field_id ] = $meta->meta_value;
77
            }
78
79
            // If prev entry is empty and current entry is not, they are not duplicates
80
            $filtered_vals = array_filter( $values['item_meta'] );
81
            if ( empty( $field_metas ) && ! empty( $filtered_vals ) ) {
82
                return false;
83
            }
84
85
            $diff = array_diff_assoc($field_metas, array_map('maybe_serialize', $values['item_meta']));
86
            foreach ( $diff as $field_id => $meta_value ) {
87
                if ( ! empty($meta_value) ) {
88
                    $is_duplicate = false;
89
                    continue;
90
                }
91
            }
92
93
            if ( $is_duplicate ) {
94
				break;
95
            }
96
        }
97
98
        return $is_duplicate;
99
    }
100
101
	/**
102
	 * Determine if an entry needs to be checked as a possible duplicate
103
	 *
104
	 * @since 2.0.23
105
	 * @param array $values
106
	 * @param int $duplicate_entry_time
107
	 * @return bool
108
	 */
109
	private static function is_duplicate_check_needed( $values, $duplicate_entry_time ) {
110
		// If time for checking duplicates is set to an empty value, don't check for duplicates
111
		if ( empty( $duplicate_entry_time ) ) {
112
			return false;
113
		}
114
115
		// If CSV is importing, don't check for duplicates
116
		if ( defined('WP_IMPORTING') && WP_IMPORTING ) {
117
			return false;
118
		}
119
120
		// If repeating field entries are getting created, don't check for duplicates
121
		if ( isset( $values['parent_form_id'] ) && $values['parent_form_id'] ) {
122
			return false;
123
		}
124
125
		return true;
126
	}
127
128
	public static function duplicate( $id ) {
129
		global $wpdb;
130
131
		$values = self::getOne( $id );
132
133
		$new_values = array();
134
		$new_values['item_key']   = FrmAppHelper::get_unique_key( '', $wpdb->prefix . 'frm_items', 'item_key' );
135
		$new_values['name']       = $values->name;
136
		$new_values['is_draft']   = $values->is_draft;
137
		$new_values['user_id']    = (int) $values->user_id;
138
		$new_values['updated_by'] = (int) $values->user_id;
139
		$new_values['form_id']    = $values->form_id ? (int) $values->form_id : null;
140
		$new_values['created_at'] = current_time( 'mysql', 1 );
141
		$new_values['updated_at'] = $new_values['created_at'];
142
143
		$query_results = $wpdb->insert( $wpdb->prefix . 'frm_items', $new_values );
144
        if ( ! $query_results ) {
145
            return false;
146
        }
147
148
        $entry_id = $wpdb->insert_id;
149
150
        global $frm_vars;
151
        if ( ! isset($frm_vars['saved_entries']) ) {
152
            $frm_vars['saved_entries'] = array();
153
        }
154
        $frm_vars['saved_entries'][] = (int) $entry_id;
155
156
        FrmEntryMeta::duplicate_entry_metas($id, $entry_id);
157
		self::clear_cache();
158
159
		do_action( 'frm_after_duplicate_entry', $entry_id, $new_values['form_id'], array( 'old_id' => $id ) );
160
        return $entry_id;
161
    }
162
163
	/**
164
	* Update an entry (not via XML)
165
	*
166
	* @param int $id
167
	* @param array $values
168
	* @return boolean|int $update_results
169
	*/
170
	public static function update( $id, $values ) {
171
		$update_results = self::update_entry( $id, $values, 'standard' );
172
173
		return $update_results;
174
	}
175
176
	/**
177
	* Update an entry with some differences depending on the update type
178
	*
179
	* @since 2.0.16
180
	*
181
	* @param int $id
182
	* @param array $values
183
	* @return boolean|int $query_results
184
	*/
185
	private static function update_entry( $id, $values, $update_type ) {
186
		global $wpdb;
187
188
		$update = self::before_update_entry( $id, $values, $update_type );
189
		if ( ! $update ) {
190
			return false;
191
		}
192
193
		$new_values = self::package_entry_to_update( $id, $values );
194
195
		$query_results = $wpdb->update( $wpdb->prefix . 'frm_items', $new_values, compact('id') );
196
197
		self::after_update_entry( $query_results, $id, $values, $new_values );
198
199
		return $query_results;
200
	}
201
202
	public static function destroy( $id ) {
203
        global $wpdb;
204
        $id = (int) $id;
205
206
		$entry = self::getOne( $id );
207
        if ( ! $entry ) {
208
            $result = false;
209
            return $result;
210
        }
211
212
        do_action('frm_before_destroy_entry', $id, $entry);
213
214
		$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_item_metas WHERE item_id=%d', $id ) );
215
		$result = $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_items WHERE id=%d', $id ) );
216
217
		self::clear_cache();
218
219
        return $result;
220
    }
221
222
	public static function update_form( $id, $value, $form_id ) {
223
        global $wpdb;
224
        $form_id = isset($value) ? $form_id : null;
225
		$result = $wpdb->update( $wpdb->prefix . 'frm_items', array( 'form_id' => $form_id ), array( 'id' => $id ) );
226
		if ( $result ) {
227
			self::clear_cache();
228
		}
229
        return $result;
230
    }
231
232
	/**
233
	 * Clear entry caching
234
	 * Called when an entry is changed
235
	 *
236
	 * @since 2.0.5
237
	 */
238
	public static function clear_cache() {
239
		FrmDb::cache_delete_group( 'frm_entry' );
240
		FrmDb::cache_delete_group( 'frm_item' );
241
		FrmDb::cache_delete_group( 'frm_entry_meta' );
242
		FrmDb::cache_delete_group( 'frm_item_meta' );
243
	}
244
245
	/**
246
	 * After switching to the wp_loaded hook for processing entries,
247
	 * we can no longer use 'name', but check it as a fallback
248
	 * @since 2.0.11
249
	 */
250
	public static function get_new_entry_name( $values, $default = '' ) {
251
		return isset( $values['item_name'] ) ? $values['item_name'] : ( isset( $values['name'] ) ? $values['name'] : $default );
252
	}
253
254
	/**
255
	 * If $entry is numeric, get the entry object
256
	 * @param int|object $entry by reference
257
	 * @since 2.0.9
258
	 */
259
	public static function maybe_get_entry( &$entry ) {
260
		if ( $entry && is_numeric( $entry ) ) {
261
			$entry = self::getOne( $entry );
262
		}
263
	}
264
265
	public static function getOne( $id, $meta = 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...
266
        global $wpdb;
267
268
        $query = "SELECT it.*, fr.name as form_name, fr.form_key as form_key FROM {$wpdb->prefix}frm_items it
269
                  LEFT OUTER JOIN {$wpdb->prefix}frm_forms fr ON it.form_id=fr.id WHERE ";
270
271
        $query .= is_numeric($id) ? 'it.id=%d' : 'it.item_key=%s';
272
        $query_args = array( $id );
273
        $query = $wpdb->prepare( $query, $query_args );
274
275
        if ( ! $meta ) {
276
			$entry = FrmDb::check_cache( $id . '_nometa', 'frm_entry', $query, 'get_row' );
277
            return stripslashes_deep($entry);
278
        }
279
280
        $entry = FrmDb::check_cache( $id, 'frm_entry' );
281
        if ( $entry !== false ) {
282
            return stripslashes_deep($entry);
283
        }
284
285
        $entry = $wpdb->get_row( $query );
286
        $entry = self::get_meta($entry);
287
288
        return stripslashes_deep($entry);
289
    }
290
291
	public static function get_meta( $entry ) {
292
        if ( ! $entry ) {
293
            return $entry;
294
        }
295
296
        global $wpdb;
297
		$metas = FrmDb::get_results( $wpdb->prefix . 'frm_item_metas m LEFT JOIN ' . $wpdb->prefix . 'frm_fields f ON m.field_id=f.id', array(
298
			'item_id' => $entry->id,
299
			'field_id !' => 0,
300
		), 'field_id, meta_value, field_key, item_id' );
301
302
        $entry->metas = array();
303
304
		$include_key = apply_filters( 'frm_include_meta_keys', false, array( 'form_id' => $entry->form_id ) );
305
        foreach ( $metas as $meta_val ) {
0 ignored issues
show
Bug introduced by
The expression $metas 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...
306
            if ( $meta_val->item_id == $entry->id ) {
307
				$entry->metas[ $meta_val->field_id ] = maybe_unserialize( $meta_val->meta_value );
308
				if ( $include_key ) {
309
					$entry->metas[ $meta_val->field_key ] = $entry->metas[ $meta_val->field_id ];
310
				}
311
                 continue;
312
            }
313
314
            // include sub entries in an array
315
			if ( ! isset( $entry_metas[ $meta_val->field_id ] ) ) {
316
				$entry->metas[ $meta_val->field_id ] = array();
317
            }
318
319
			$entry->metas[ $meta_val->field_id ][] = maybe_unserialize( $meta_val->meta_value );
320
321
            unset($meta_val);
322
        }
323
        unset($metas);
324
325
		FrmDb::set_cache( $entry->id, $entry, 'frm_entry' );
326
327
        return $entry;
328
    }
329
330
    /**
331
     * @param string $id
332
     */
333
	public static function exists( $id ) {
334
        global $wpdb;
335
336
        if ( FrmDb::check_cache( $id, 'frm_entry' ) ) {
337
            $exists = true;
338
            return $exists;
339
        }
340
341
        if ( is_numeric($id) ) {
342
            $where = array( 'id' => $id );
343
        } else {
344
            $where = array( 'item_key' => $id );
345
        }
346
		$id = FrmDb::get_var( $wpdb->prefix . 'frm_items', $where );
347
348
		return ( $id && $id > 0 );
349
    }
350
351
    public static function getAll( $where, $order_by = '', $limit = '', $meta = false, $inc_form = true ) {
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...
352
		global $wpdb;
353
354
        $limit = FrmDb::esc_limit($limit);
355
356
        $cache_key = maybe_serialize($where) . $order_by . $limit . $inc_form;
357
        $entries = wp_cache_get($cache_key, 'frm_entry');
358
359
        if ( false === $entries ) {
360
            $fields = 'it.id, it.item_key, it.name, it.ip, it.form_id, it.post_id, it.user_id, it.parent_item_id, it.updated_by, it.created_at, it.updated_at, it.is_draft';
361
			$table = $wpdb->prefix . 'frm_items it ';
362
363
            if ( $inc_form ) {
364
                $fields = 'it.*, fr.name as form_name,fr.form_key as form_key';
365
                $table .= 'LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_forms fr ON it.form_id=fr.id ';
366
            }
367
368
            if ( preg_match( '/ meta_([0-9]+)/', $order_by, $order_matches ) ) {
369
    		    // sort by a requested field
370
                $field_id = (int) $order_matches[1];
371
				$fields .= ', (SELECT meta_value FROM ' . $wpdb->prefix . 'frm_item_metas WHERE field_id = ' . $field_id . ' AND item_id = it.id) as meta_' . $field_id;
372
				unset( $order_matches, $field_id );
373
		    }
374
375
			// prepare the query
376
			$query = 'SELECT ' . $fields . ' FROM ' . $table . FrmDb::prepend_and_or_where(' WHERE ', $where) . $order_by . $limit;
377
378
            $entries = $wpdb->get_results($query, OBJECT_K);
379
            unset($query);
380
381
			FrmDb::set_cache( $cache_key, $entries, 'frm_entry' );
382
        }
383
384
        if ( ! $meta || ! $entries ) {
385
            return stripslashes_deep($entries);
386
        }
387
        unset($meta);
388
389
        if ( ! is_array( $where ) && preg_match('/^it\.form_id=\d+$/', $where) ) {
390
			$where = array( 'it.form_id' => substr( $where, 11 ) );
391
        }
392
393
        $meta_where = array( 'field_id !' => 0 );
394
        if ( $limit == '' && is_array($where) && count($where) == 1 && isset($where['it.form_id']) ) {
395
            $meta_where['fi.form_id'] = $where['it.form_id'];
396
        } else {
397
            $meta_where['item_id'] = array_keys( $entries );
398
        }
399
400
        $metas = FrmDb::get_results( $wpdb->prefix . 'frm_item_metas it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON (it.field_id = fi.id)', $meta_where, 'item_id, meta_value, field_id, field_key, form_id' );
401
402
        unset( $meta_where );
403
404
        if ( ! $metas ) {
405
            return stripslashes_deep($entries);
406
        }
407
408
        foreach ( $metas as $m_key => $meta_val ) {
0 ignored issues
show
Bug introduced by
The expression $metas 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...
409
            if ( ! isset( $entries[ $meta_val->item_id ] ) ) {
410
                continue;
411
            }
412
413
            if ( ! isset( $entries[ $meta_val->item_id ]->metas ) ) {
414
				$entries[ $meta_val->item_id ]->metas = array();
415
            }
416
417
			$entries[ $meta_val->item_id ]->metas[ $meta_val->field_id ] = maybe_unserialize( $meta_val->meta_value );
418
419
            unset($m_key, $meta_val);
420
        }
421
422
		if ( ! FrmAppHelper::prevent_caching() ) {
423
			foreach ( $entries as $entry ) {
424
				FrmDb::set_cache( $entry->id, $entry, 'frm_entry' );
425
				unset( $entry );
426
			}
427
		}
428
429
        return stripslashes_deep($entries);
430
    }
431
432
    // Pagination Methods
433
    public static function getRecordCount( $where = '' ) {
0 ignored issues
show
Coding Style introduced by
The function name getRecordCount is in camel caps, but expected get_record_count instead as per the coding standard.
Loading history...
434
        global $wpdb;
435
		$table_join = $wpdb->prefix . 'frm_items it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_forms fr ON it.form_id=fr.id';
436
437
        if ( is_numeric($where) ) {
438
            $table_join = 'frm_items';
439
            $where = array( 'form_id' => $where );
440
        }
441
442
        if ( is_array( $where ) ) {
443
            $count = FrmDb::get_count( $table_join, $where );
444
        } else {
445
			$cache_key = 'count_' . maybe_serialize( $where );
446
			$query = 'SELECT COUNT(*) FROM ' . $table_join . FrmDb::prepend_and_or_where( ' WHERE ', $where );
447
			$count = FrmDb::check_cache( $cache_key, 'frm_entry', $query, 'get_var' );
448
        }
449
450
        return $count;
451
    }
452
453
    public static function getPageCount( $p_size, $where = '' ) {
0 ignored issues
show
Coding Style introduced by
The function name getPageCount is in camel caps, but expected get_page_count instead as per the coding standard.
Loading history...
454
		$p_size = (int) $p_size;
455
		$count = 1;
456
		if ( $p_size ) {
457
			if ( ! is_numeric( $where ) ) {
458
				$where = self::getRecordCount( $where );
459
			}
460
			$count = ceil( (int) $where / $p_size );
461
		}
462
463
		return $count;
464
    }
465
466
	/**
467
	* Prepare the data before inserting it into the database
468
	*
469
	* @since 2.0.16
470
	* @param array $values
471
	* @param string $type
472
	* @return array $new_values
473
	*/
474
	private static function before_insert_entry_in_database( &$values, $type ) {
475
476
		self::sanitize_entry_post( $values );
477
478
		if ( $type != 'xml' ) {
479
			$values = apply_filters('frm_pre_create_entry', $values);
480
		}
481
482
		$new_values = self::package_entry_data( $values );
483
484
		return $new_values;
485
	}
486
487
	/**
488
	* Create an entry and perform after create actions
489
	*
490
	* @since 2.0.16
491
	* @param array $values
492
	* @param array $new_values
493
	* @return boolean|int $entry_id
494
	*/
495
	private static function continue_to_create_entry( $values, $new_values ) {
496
		$entry_id = self::insert_entry_into_database( $new_values );
497
		if ( ! $entry_id ) {
498
			return false;
499
		}
500
501
		self::after_insert_entry_in_database( $values, $new_values, $entry_id );
502
503
		return $entry_id;
504
	}
505
506
    /**
507
     * Sanitize the POST values before we use them
508
     *
509
     * @since 2.0
510
     * @param array $values The POST values by reference
511
     */
512
    public static function sanitize_entry_post( &$values ) {
513
        $sanitize_method = array(
514
            'form_id'       => 'absint',
515
            'frm_action'    => 'sanitize_title',
516
            'form_key'      => 'sanitize_title',
517
            'item_key'      => 'sanitize_title',
518
            'item_name'     => 'sanitize_text_field',
519
            'frm_saving_draft' => 'absint',
520
            'is_draft'      => 'absint',
521
            'post_id'       => 'absint',
522
            'parent_item_id' => 'absint',
523
            'created_at'    => 'sanitize_text_field',
524
            'updated_at'    => 'sanitize_text_field',
525
        );
526
527
        FrmAppHelper::sanitize_request( $sanitize_method, $values );
528
    }
529
530
	/**
531
	* Prepare the new values for inserting into the database
532
	*
533
	* @since 2.0.16
534
	* @param array $values
535
	* @return array $new_values
536
	*/
537
	private static function package_entry_data( &$values ) {
538
		global $wpdb;
539
540
		if ( ! isset( $values['item_key'] ) ) {
541
			$values['item_key'] = '';
542
		}
543
544
		$item_name = self::get_new_entry_name( $values, $values['item_key'] );
545
		$new_values = array(
546
			'item_key'  => FrmAppHelper::get_unique_key( $values['item_key'], $wpdb->prefix . 'frm_items', 'item_key' ),
547
			'name'      => FrmAppHelper::truncate( $item_name, 255, 1, '' ),
548
			'ip'        => self::get_ip( $values ),
549
			'is_draft'  => self::get_is_draft_value( $values ),
550
			'form_id'   => (int) self::get_entry_value( $values, 'form_id', null ),
551
			'post_id'   => (int) self::get_entry_value( $values, 'post_id', 0 ),
552
			'parent_item_id' => (int) self::get_entry_value( $values, 'parent_item_id', 0 ),
553
			'created_at' => self::get_created_at( $values ),
554
			'updated_at' => self::get_updated_at( $values ),
555
			'description' => self::get_entry_description( $values ),
556
			'user_id' => self::get_entry_user_id( $values ),
557
		);
558
559
		if ( is_array($new_values['name']) ) {
560
			$new_values['name'] = reset($new_values['name']);
561
		}
562
563
		$new_values['updated_by'] = isset($values['updated_by']) ? $values['updated_by'] : $new_values['user_id'];
564
565
		return $new_values;
566
	}
567
568
	private static function get_entry_value( $values, $name, $default ) {
569
		return isset( $values[ $name ] ) ? $values[ $name ] : $default;
570
	}
571
572
	/**
573
	 * Get the ip for a new entry.
574
	 * Allow the import to override the value.
575
	 *
576
	 * @since 2.03.10
577
	 * @param array $values
578
	 * @return string
579
	 */
580
	private static function get_ip( $values ) {
581
		if ( ! FrmAppHelper::ips_saved() ) {
582
			return '';
583
		}
584
585
		$ip = FrmAppHelper::get_ip_address();
586
		if ( defined('WP_IMPORTING') && WP_IMPORTING ) {
587
			$ip = self::get_entry_value( $values, 'ip', $ip );
588
		}
589
		return $ip;
590
	}
591
592
	/**
593
	* Get the is_draft value for a new entry
594
	*
595
	* @since 2.0.16
596
	* @param array $values
597
	* @return int
598
	*/
599
	private static function get_is_draft_value( $values ) {
600
		return ( ( isset( $values['frm_saving_draft'] ) && $values['frm_saving_draft'] == 1 ) || ( isset( $values['is_draft'] ) && $values['is_draft'] == 1 ) ) ? 1 : 0;
601
	}
602
603
	/**
604
	* Get the created_at value for a new entry
605
	*
606
	* @since 2.0.16
607
	* @param array $values
608
	* @return string
609
	*/
610
	private static function get_created_at( $values ) {
611
		return self::get_entry_value( $values, 'created_at', current_time( 'mysql', 1 ) );
612
	}
613
614
	/**
615
	* Get the updated_at value for a new entry
616
	*
617
	* @since 2.0.16
618
	* @param array $values
619
	* @return string
620
	*/
621
	private static function get_updated_at( $values ) {
622
		if ( isset( $values['updated_at'] ) ) {
623
			$updated_at = $values['updated_at'];
624
		} else {
625
			$updated_at = self::get_created_at( $values );
626
		}
627
628
		return $updated_at;
629
	}
630
631
	/**
632
	* Get the description value for a new entry
633
	*
634
	* @since 2.0.16
635
	* @param array $values
636
	* @return string
637
	*/
638
	private static function get_entry_description( $values ) {
639
		if ( isset( $values['description'] ) && ! empty( $values['description'] ) ) {
640
			$description = maybe_serialize( $values['description'] );
641
		} else {
642
			$description = serialize( array(
643
				'browser'  => FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' ),
644
				'referrer' => FrmAppHelper::get_server_value( 'HTTP_REFERER' ),
645
			) );
646
		}
647
648
		return $description;
649
	}
650
651
	/**
652
	* Get the user_id value for a new entry
653
	*
654
	* @since 2.0.16
655
	* @param array $values
656
	* @return int
657
	*/
658
	private static function get_entry_user_id( $values ) {
659
		if ( isset( $values['frm_user_id'] ) && ( is_numeric( $values['frm_user_id'] ) || FrmAppHelper::is_admin() ) ) {
660
			$user_id = $values['frm_user_id'];
661
		} else {
662
			$current_user_id = get_current_user_id();
663
			$user_id = $current_user_id ? $current_user_id : 0;
664
		}
665
666
		return $user_id;
667
	}
668
669
	/**
670
	* Insert new entry into the database
671
	*
672
	* @since 2.0.16
673
	* @param array $new_values
674
	* @return int | boolean $entry_id
675
	*/
676
	private static function insert_entry_into_database( $new_values ) {
677
		global $wpdb;
678
679
		$query_results = $wpdb->insert( $wpdb->prefix . 'frm_items', $new_values );
680
681
		if ( ! $query_results ) {
682
			$entry_id = false;
683
		} else {
684
			$entry_id = $wpdb->insert_id;
685
		}
686
687
		return $entry_id;
688
	}
689
690
	/**
691
	* Add the new entry to global $frm_vars
692
	*
693
	* @since 2.0.16
694
	* @param int $entry_id
695
	*/
696
	private static function add_new_entry_to_frm_vars( $entry_id ) {
697
		global $frm_vars;
698
699
		if ( ! isset($frm_vars['saved_entries']) ) {
700
			$frm_vars['saved_entries'] = array();
701
		}
702
703
		$frm_vars['saved_entries'][] = (int) $entry_id;
704
	}
705
706
	/**
707
	* Add entry metas, if there are any
708
	*
709
	* @since 2.0.16
710
	* @param array $values
711
	* @param int $entry_id
712
	*/
713
	private static function maybe_add_entry_metas( $values, $entry_id ) {
714
		if ( isset($values['item_meta']) ) {
715
			FrmEntryMeta::update_entry_metas( $entry_id, $values['item_meta'] );
716
		}
717
	}
718
719
	/**
720
	* Trigger frm_after_create_entry hooks
721
	*
722
	* @since 2.0.16
723
	* @param int $entry_id
724
	* @param array $new_values
725
	*/
726
	private static function after_entry_created_actions( $entry_id, $values, $new_values ) {
727
		// this is a child entry
728
		$is_child = isset( $values['parent_form_id'] ) && isset( $values['parent_nonce'] ) && ! empty( $values['parent_form_id'] ) && wp_verify_nonce( $values['parent_nonce'], 'parent' );
729
730
		do_action( 'frm_after_create_entry', $entry_id, $new_values['form_id'], compact( 'is_child' ) );
731
		do_action( 'frm_after_create_entry_' . $new_values['form_id'], $entry_id, compact( 'is_child' ) );
732
	}
733
734
	/**
735
	* Actions to perform immediately after an entry is inserted in the frm_items database
736
	*
737
	* @since 2.0.16
738
	* @param array $values
739
	* @param array $new_values
740
	* @param int $entry_id
741
	*/
742
	private static function after_insert_entry_in_database( $values, $new_values, $entry_id ) {
743
744
		self::add_new_entry_to_frm_vars( $entry_id );
745
746
		self::maybe_add_entry_metas( $values, $entry_id );
747
748
		self::clear_cache();
749
750
		self::after_entry_created_actions( $entry_id, $values, $new_values );
751
	}
752
753
	/**
754
	* Perform some actions right before updating an entry
755
	*
756
	* @since 2.0.16
757
	* @param int $id
758
	* @param array $values
759
	* @param string $update_type
760
	* @return boolean $update
761
	*/
762
	private static function before_update_entry( $id, &$values, $update_type ) {
763
		$update = true;
764
765
		global $frm_vars;
766
767
		if ( isset( $frm_vars['saved_entries'] ) && is_array( $frm_vars['saved_entries'] ) && in_array( (int) $id, (array) $frm_vars['saved_entries'] ) ) {
768
			$update = false;
769
		}
770
771
		if ( $update && $update_type != 'xml' ) {
772
			$values = apply_filters('frm_pre_update_entry', $values, $id);
773
		}
774
775
		return $update;
776
	}
777
778
	/**
779
	* Package the entry data for updating
780
	*
781
	* @since 2.0.16
782
	* @param int $id
783
	* @param array $values
784
	* @return array $new_values
785
	*/
786
	private static function package_entry_to_update( $id, $values ) {
787
		global $wpdb;
788
789
		$new_values = array(
790
			'name'      => self::get_new_entry_name( $values ),
791
			'form_id'   => (int) self::get_entry_value( $values, 'form_id', null ),
792
			'is_draft'  => self::get_is_draft_value( $values ),
793
			'updated_at' => current_time('mysql', 1),
794
			'updated_by' => isset($values['updated_by']) ? $values['updated_by'] : get_current_user_id(),
795
		);
796
797
		if ( isset($values['post_id']) ) {
798
			$new_values['post_id'] = (int) $values['post_id'];
799
		}
800
801
		if ( isset($values['item_key']) ) {
802
			$new_values['item_key'] = FrmAppHelper::get_unique_key( $values['item_key'], $wpdb->prefix . 'frm_items', 'item_key', $id );
803
		}
804
805
		if ( isset($values['parent_item_id']) ) {
806
			$new_values['parent_item_id'] = (int) $values['parent_item_id'];
807
		}
808
809
		if ( isset($values['frm_user_id']) && is_numeric($values['frm_user_id']) ) {
810
			$new_values['user_id'] = $values['frm_user_id'];
811
		}
812
813
		$new_values = apply_filters('frm_update_entry', $new_values, $id);
814
815
		return $new_values;
816
	}
817
818
	/**
819
	* Perform some actions right after updating an entry
820
	*
821
	* @since 2.0.16
822
	* @param boolean|int $query_results
823
	* @param int $id
824
	* @param array $values
825
	* @param array $new_values
826
	*/
827
	private static function after_update_entry( $query_results, $id, $values, $new_values ) {
828
		if ( $query_results ) {
829
			self::clear_cache();
830
		}
831
832
		global $frm_vars;
833
		if ( ! isset( $frm_vars['saved_entries'] ) ) {
834
			$frm_vars['saved_entries'] = array();
835
		}
836
837
		$frm_vars['saved_entries'][] = (int) $id;
838
839
		if ( isset( $values['item_meta'] ) ) {
840
			FrmEntryMeta::update_entry_metas( $id, $values['item_meta'] );
841
		}
842
843
		do_action( 'frm_after_update_entry', $id, $new_values['form_id'] );
844
		do_action( 'frm_after_update_entry_' . $new_values['form_id'], $id );
845
	}
846
847
	/**
848
	* Create entry from an XML import
849
	* Certain actions aren't necessary when importing (like saving sub entries, checking for duplicates, etc.)
850
	*
851
	* @since 2.0.16
852
	* @param array $values
853
	* @return int | boolean $entry_id
854
	*/
855
	public static function create_entry_from_xml( $values ) {
856
		$entry_id = self::create_entry( $values, 'xml' );
857
858
		return $entry_id;
859
	}
860
861
	/**
862
	* Update entry from an XML import
863
	* Certain actions aren't necessary when importing (like saving sub entries and modifying other vals)
864
	*
865
	* @since 2.0.16
866
	* @param int $id
867
	* @param array $values
868
	* @return int | boolean $updated
869
	*/
870
	public static function update_entry_from_xml( $id, $values ) {
871
		$updated = self::update_entry( $id, $values, 'xml' );
872
873
		return $updated;
874
	}
875
876
    /**
877
     * @param string $key
878
     * @return int entry_id
879
     */
880
	public static function get_id_by_key( $key ) {
881
        $entry_id = FrmDb::get_var( 'frm_items', array( 'item_key' => sanitize_title( $key ) ) );
882
        return $entry_id;
883
    }
884
885
	public static function validate( $values, $exclude = false ) {
886
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryValidate::validate' );
887
		return FrmEntryValidate::validate( $values, $exclude );
888
	}
889
890
	public static function validate_field( $posted_field, &$errors, $values, $args = array() ) {
891
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryValidate::validate_field' );
892
		FrmEntryValidate::validate_field( $posted_field, $errors, $values, $args );
893
	}
894
895
	public static function validate_url_field( &$errors, $field, &$value, $args ) {
896
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryValidate::validate_url_field' );
897
		FrmEntryValidate::validate_url_field( $errors, $field, $value, $args );
898
	}
899
900
	public static function validate_email_field( &$errors, $field, $value, $args ) {
901
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryValidate::validate_email_field' );
902
		FrmEntryValidate::validate_email_field( $errors, $field, $value, $args );
903
	}
904
905
	public static function validate_recaptcha( &$errors, $field, $args ) {
906
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryValidate::validate_recaptcha' );
907
		FrmEntryValidate::validate_recaptcha( $errors, $field, $args );
908
	}
909
910
	public static function spam_check( $exclude, $values, &$errors ) {
911
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryValidate::spam_check' );
912
		FrmEntryValidate::spam_check( $exclude, $values, $errors );
913
	}
914
915
	public static function blacklist_check( $values ) {
916
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryValidate::blacklist_check' );
917
		return FrmEntryValidate::blacklist_check( $values );
918
	}
919
920
	public static function akismet( $values ) {
921
		_deprecated_function( __FUNCTION__, '2.0.9', 'FrmEntryValidate::akismet' );
922
		return FrmEntryValidate::akismet( $values );
923
	}
924
}
925