PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.0
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.0
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / FrmEntry.php

FrmEntry.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 5.0, at classes/models/FrmEntry.php

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