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

1,044 lines 27.4 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 ); // WPCS: unprepared SQL ok.
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 ); // WPCS: unprepared SQL ok.
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 ); // WPCS: unprepared SQL ok.
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 */
859 private static function maybe_add_entry_metas( $values, $entry_id ) {
860 if ( isset( $values['item_meta'] ) ) {
861 FrmEntryMeta::update_entry_metas( $entry_id, $values['item_meta'] );
862 }
863 }
864
865 /**
866 * Trigger frm_after_create_entry hooks
867 *
868 * @since 2.0.16
869 *
870 * @param int $entry_id
871 * @param array $new_values
872 */
873 private static function after_entry_created_actions( $entry_id, $values, $new_values ) {
874 // this is a child entry
875 $is_child = isset( $values['parent_form_id'] ) && isset( $values['parent_nonce'] ) && ! empty( $values['parent_form_id'] ) && wp_verify_nonce( $values['parent_nonce'], 'parent' );
876
877 do_action( 'frm_after_create_entry', $entry_id, $new_values['form_id'], compact( 'is_child' ) );
878 do_action( 'frm_after_create_entry_' . $new_values['form_id'], $entry_id, compact( 'is_child' ) );
879 }
880
881 /**
882 * Actions to perform immediately after an entry is inserted in the frm_items database
883 *
884 * @since 2.0.16
885 *
886 * @param array $values
887 * @param array $new_values
888 * @param int $entry_id
889 */
890 private static function after_insert_entry_in_database( $values, $new_values, $entry_id ) {
891
892 self::add_new_entry_to_frm_vars( $entry_id );
893
894 self::maybe_add_entry_metas( $values, $entry_id );
895
896 self::clear_cache();
897
898 self::after_entry_created_actions( $entry_id, $values, $new_values );
899 }
900
901 /**
902 * Perform some actions right before updating an entry
903 *
904 * @since 2.0.16
905 *
906 * @param int $id
907 * @param array $values
908 * @param string $update_type
909 *
910 * @return boolean $update
911 */
912 private static function before_update_entry( $id, &$values, $update_type ) {
913 $update = true;
914
915 global $frm_vars;
916
917 if ( isset( $frm_vars['saved_entries'] ) && is_array( $frm_vars['saved_entries'] ) && in_array( (int) $id, (array) $frm_vars['saved_entries'] ) ) {
918 $update = false;
919 }
920
921 if ( $update && $update_type != 'xml' ) {
922 $values = apply_filters( 'frm_pre_update_entry', $values, $id );
923 }
924
925 return $update;
926 }
927
928 /**
929 * Package the entry data for updating
930 *
931 * @since 2.0.16
932 *
933 * @param int $id
934 * @param array $values
935 *
936 * @return array $new_values
937 */
938 private static function package_entry_to_update( $id, $values ) {
939 global $wpdb;
940
941 $new_values = array(
942 'name' => self::get_new_entry_name( $values ),
943 'form_id' => (int) self::get_entry_value( $values, 'form_id', null ),
944 'is_draft' => self::get_is_draft_value( $values ),
945 'updated_at' => current_time( 'mysql', 1 ),
946 'updated_by' => isset( $values['updated_by'] ) ? $values['updated_by'] : get_current_user_id(),
947 );
948
949 if ( isset( $values['post_id'] ) ) {
950 $new_values['post_id'] = (int) $values['post_id'];
951 }
952
953 if ( isset( $values['item_key'] ) ) {
954 $new_values['item_key'] = FrmAppHelper::get_unique_key( $values['item_key'], $wpdb->prefix . 'frm_items', 'item_key', $id );
955 }
956
957 if ( isset( $values['parent_item_id'] ) ) {
958 $new_values['parent_item_id'] = (int) $values['parent_item_id'];
959 }
960
961 if ( isset( $values['frm_user_id'] ) && is_numeric( $values['frm_user_id'] ) ) {
962 $new_values['user_id'] = $values['frm_user_id'];
963 }
964
965 $new_values = apply_filters( 'frm_update_entry', $new_values, $id );
966
967 return $new_values;
968 }
969
970 /**
971 * Perform some actions right after updating an entry
972 *
973 * @since 2.0.16
974 *
975 * @param boolean|int $query_results
976 * @param int $id
977 * @param array $values
978 * @param array $new_values
979 */
980 private static function after_update_entry( $query_results, $id, $values, $new_values ) {
981 if ( $query_results ) {
982 self::clear_cache();
983 }
984
985 global $frm_vars;
986 if ( ! isset( $frm_vars['saved_entries'] ) ) {
987 $frm_vars['saved_entries'] = array();
988 }
989
990 $frm_vars['saved_entries'][] = (int) $id;
991
992 if ( isset( $values['item_meta'] ) ) {
993 FrmEntryMeta::update_entry_metas( $id, $values['item_meta'] );
994 }
995
996 do_action( 'frm_after_update_entry', $id, $new_values['form_id'] );
997 do_action( 'frm_after_update_entry_' . $new_values['form_id'], $id );
998 }
999
1000 /**
1001 * Create entry from an XML import
1002 * Certain actions aren't necessary when importing (like saving sub entries, checking for duplicates, etc.)
1003 *
1004 * @since 2.0.16
1005 *
1006 * @param array $values
1007 *
1008 * @return int | boolean $entry_id
1009 */
1010 public static function create_entry_from_xml( $values ) {
1011 $entry_id = self::create_entry( $values, 'xml' );
1012
1013 return $entry_id;
1014 }
1015
1016 /**
1017 * Update entry from an XML import
1018 * Certain actions aren't necessary when importing (like saving sub entries and modifying other vals)
1019 *
1020 * @since 2.0.16
1021 *
1022 * @param int $id
1023 * @param array $values
1024 *
1025 * @return int | boolean $updated
1026 */
1027 public static function update_entry_from_xml( $id, $values ) {
1028 $updated = self::update_entry( $id, $values, 'xml' );
1029
1030 return $updated;
1031 }
1032
1033 /**
1034 * @param string $key
1035 *
1036 * @return int entry_id
1037 */
1038 public static function get_id_by_key( $key ) {
1039 $entry_id = FrmDb::get_var( 'frm_items', array( 'item_key' => sanitize_title( $key ) ) );
1040
1041 return (int) $entry_id;
1042 }
1043 }
1044