PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.4
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.4
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.4, at classes/models/FrmEntry.php

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