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

1,039 lines 27.3 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 $fields .= self::sort_by_field( $order_matches[1] );
465 unset( $order_matches );
466 }
467
468 // prepare the query
469 $query = 'SELECT ' . $fields . ' FROM ' . $table . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
470
471 $entries = $wpdb->get_results( $query, OBJECT_K ); // WPCS: unprepared SQL ok.
472 unset( $query );
473
474 FrmDb::set_cache( $cache_key, $entries, 'frm_entry' );
475 }
476
477 if ( ! $meta || ! $entries ) {
478 self::prepare_entries( $entries );
479 return $entries;
480 }
481 unset( $meta );
482
483 if ( ! is_array( $where ) && preg_match( '/^it\.form_id=\d+$/', $where ) ) {
484 $where = array( 'it.form_id' => substr( $where, 11 ) );
485 }
486
487 $meta_where = array( 'field_id !' => 0 );
488 if ( $limit == '' && is_array( $where ) && count( $where ) == 1 && isset( $where['it.form_id'] ) ) {
489 $meta_where['fi.form_id'] = $where['it.form_id'];
490 } else {
491 $meta_where['item_id'] = array_keys( $entries );
492 }
493
494 $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' );
495
496 unset( $meta_where );
497
498 if ( ! $metas ) {
499 self::prepare_entries( $entries );
500 return $entries;
501 }
502
503 foreach ( $metas as $m_key => $meta_val ) {
504 if ( ! isset( $entries[ $meta_val->item_id ] ) ) {
505 continue;
506 }
507
508 if ( ! isset( $entries[ $meta_val->item_id ]->metas ) ) {
509 $entries[ $meta_val->item_id ]->metas = array();
510 }
511
512 FrmAppHelper::unserialize_or_decode( $meta_val->meta_value );
513 $entries[ $meta_val->item_id ]->metas[ $meta_val->field_id ] = $meta_val->meta_value;
514 unset( $m_key, $meta_val );
515 }
516
517 if ( ! FrmAppHelper::prevent_caching() ) {
518 foreach ( $entries as $entry ) {
519 FrmDb::set_cache( $entry->id, $entry, 'frm_entry' );
520 unset( $entry );
521 }
522 }
523
524 self::prepare_entries( $entries );
525 return $entries;
526 }
527
528 /**
529 * @param int $field_id
530 * @return string
531 */
532 private static function sort_by_field( $field_id ) {
533 global $wpdb;
534 $field_id = (int) $field_id;
535
536 $field_options = FrmDb::get_var( 'frm_fields', array( 'id' => $field_id ), 'field_options' );
537 FrmAppHelper::unserialize_or_decode( $field_options );
538
539 if ( empty( $field_options['post_field'] ) ) {
540 $sort = ', (SELECT meta_value FROM ' . $wpdb->prefix . 'frm_item_metas WHERE field_id = ' . $field_id . ' AND item_id = it.id) as meta_' . $field_id;
541 } else {
542 $sort = '';
543 }
544
545 return apply_filters( 'frm_handle_field_column_sort', $sort, $field_id, $field_options );
546 }
547
548 // Pagination Methods
549 /**
550 * @param int|array|string If int, use the form id.
551 */
552 public static function getRecordCount( $where = '' ) {
553 global $wpdb;
554 $table_join = $wpdb->prefix . 'frm_items it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_forms fr ON it.form_id=fr.id';
555
556 if ( is_numeric( $where ) ) {
557 $table_join = 'frm_items';
558 $where = array( 'form_id' => $where );
559 }
560
561 if ( is_array( $where ) ) {
562 $count = FrmDb::get_count( $table_join, $where );
563 } else {
564 $cache_key = 'count_' . FrmAppHelper::maybe_json_encode( $where );
565 $query = 'SELECT COUNT(*) FROM ' . $table_join . FrmDb::prepend_and_or_where( ' WHERE ', $where );
566 $count = FrmDb::check_cache( $cache_key, 'frm_entry', $query, 'get_var' );
567 }
568
569 return $count;
570 }
571
572 public static function getPageCount( $p_size, $where = '' ) {
573 $p_size = (int) $p_size;
574 $count = 1;
575 if ( $p_size ) {
576 if ( ! is_numeric( $where ) ) {
577 $where = self::getRecordCount( $where );
578 }
579 $count = ceil( (int) $where / $p_size );
580 }
581
582 return $count;
583 }
584
585 /**
586 * Prepare the data before inserting it into the database
587 *
588 * @since 2.0.16
589 *
590 * @param array $values
591 * @param string $type
592 *
593 * @return array $new_values
594 */
595 private static function before_insert_entry_in_database( &$values, $type ) {
596
597 self::sanitize_entry_post( $values );
598
599 if ( $type != 'xml' ) {
600 $values = apply_filters( 'frm_pre_create_entry', $values );
601 }
602
603 $new_values = self::package_entry_data( $values );
604
605 return $new_values;
606 }
607
608 /**
609 * Create an entry and perform after create actions
610 *
611 * @since 2.0.16
612 *
613 * @param array $values
614 * @param array $new_values
615 *
616 * @return boolean|int $entry_id
617 */
618 private static function continue_to_create_entry( $values, $new_values ) {
619 $entry_id = self::insert_entry_into_database( $new_values );
620 if ( ! $entry_id ) {
621 return false;
622 }
623
624 self::after_insert_entry_in_database( $values, $new_values, $entry_id );
625
626 return $entry_id;
627 }
628
629 /**
630 * Sanitize the POST values before we use them
631 *
632 * @since 2.0
633 *
634 * @param array $values The POST values by reference
635 */
636 public static function sanitize_entry_post( &$values ) {
637 $sanitize_method = array(
638 'form_id' => 'absint',
639 'frm_action' => 'sanitize_title',
640 'form_key' => 'sanitize_title',
641 'item_key' => 'sanitize_title',
642 'item_name' => 'sanitize_text_field',
643 'frm_saving_draft' => 'absint',
644 'is_draft' => 'absint',
645 'post_id' => 'absint',
646 'parent_item_id' => 'absint',
647 'created_at' => 'sanitize_text_field',
648 'updated_at' => 'sanitize_text_field',
649 );
650
651 FrmAppHelper::sanitize_request( $sanitize_method, $values );
652 }
653
654 /**
655 * Prepare the new values for inserting into the database
656 *
657 * @since 2.0.16
658 *
659 * @param array $values
660 *
661 * @return array $new_values
662 */
663 private static function package_entry_data( &$values ) {
664 global $wpdb;
665
666 if ( ! isset( $values['item_key'] ) ) {
667 $values['item_key'] = '';
668 }
669
670 $item_name = self::get_new_entry_name( $values, $values['item_key'] );
671 $new_values = array(
672 'item_key' => FrmAppHelper::get_unique_key( $values['item_key'], $wpdb->prefix . 'frm_items', 'item_key' ),
673 'name' => FrmAppHelper::truncate( $item_name, 255, 1, '' ),
674 'ip' => self::get_ip( $values ),
675 'is_draft' => self::get_is_draft_value( $values ),
676 'form_id' => (int) self::get_entry_value( $values, 'form_id', null ),
677 'post_id' => (int) self::get_entry_value( $values, 'post_id', 0 ),
678 'parent_item_id' => (int) self::get_entry_value( $values, 'parent_item_id', 0 ),
679 'created_at' => self::get_created_at( $values ),
680 'updated_at' => self::get_updated_at( $values ),
681 'description' => self::get_entry_description( $values ),
682 'user_id' => self::get_entry_user_id( $values ),
683 );
684
685 $new_values['updated_by'] = isset( $values['updated_by'] ) ? $values['updated_by'] : $new_values['user_id'];
686
687 return $new_values;
688 }
689
690 private static function get_entry_value( $values, $name, $default ) {
691 return isset( $values[ $name ] ) ? $values[ $name ] : $default;
692 }
693
694 /**
695 * Get the ip for a new entry.
696 * Allow the import to override the value.
697 *
698 * @since 2.03.10
699 *
700 * @param array $values
701 *
702 * @return string
703 */
704 private static function get_ip( $values ) {
705 if ( ! FrmAppHelper::ips_saved() ) {
706 return '';
707 }
708
709 $ip = FrmAppHelper::get_ip_address();
710 if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
711 $ip = self::get_entry_value( $values, 'ip', $ip );
712 }
713
714 return $ip;
715 }
716
717 /**
718 * Get the is_draft value for a new entry
719 *
720 * @since 2.0.16
721 *
722 * @param array $values
723 *
724 * @return int
725 */
726 private static function get_is_draft_value( $values ) {
727 return ( ( isset( $values['frm_saving_draft'] ) && $values['frm_saving_draft'] == 1 ) || ( isset( $values['is_draft'] ) && $values['is_draft'] == 1 ) ) ? 1 : 0;
728 }
729
730 /**
731 * Get the created_at value for a new entry
732 *
733 * @since 2.0.16
734 *
735 * @param array $values
736 *
737 * @return string
738 */
739 private static function get_created_at( $values ) {
740 return self::get_entry_value( $values, 'created_at', current_time( 'mysql', 1 ) );
741 }
742
743 /**
744 * Get the updated_at value for a new entry
745 *
746 * @since 2.0.16
747 *
748 * @param array $values
749 *
750 * @return string
751 */
752 private static function get_updated_at( $values ) {
753 if ( isset( $values['updated_at'] ) ) {
754 $updated_at = $values['updated_at'];
755 } else {
756 $updated_at = self::get_created_at( $values );
757 }
758
759 return $updated_at;
760 }
761
762 /**
763 * Get the description value for a new entry
764 *
765 * @since 2.0.16
766 *
767 * @param array $values
768 *
769 * @return string
770 */
771 private static function get_entry_description( $values ) {
772 if ( isset( $values['description'] ) && ! empty( $values['description'] ) ) {
773 $description = FrmAppHelper::maybe_json_encode( $values['description'] );
774 } else {
775 $description = json_encode(
776 array(
777 'browser' => FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' ),
778 'referrer' => FrmAppHelper::get_server_value( 'HTTP_REFERER' ),
779 )
780 );
781 }
782
783 return $description;
784 }
785
786 /**
787 * Get the user_id value for a new entry
788 *
789 * @since 2.0.16
790 *
791 * @param array $values
792 *
793 * @return int
794 */
795 private static function get_entry_user_id( $values ) {
796 if ( isset( $values['frm_user_id'] ) && ( is_numeric( $values['frm_user_id'] ) || FrmAppHelper::is_admin() ) ) {
797 $user_id = $values['frm_user_id'];
798 } else {
799 $current_user_id = get_current_user_id();
800 $user_id = $current_user_id ? $current_user_id : 0;
801 }
802
803 return $user_id;
804 }
805
806 /**
807 * Insert new entry into the database
808 *
809 * @since 2.0.16
810 *
811 * @param array $new_values
812 *
813 * @return int | boolean $entry_id
814 */
815 private static function insert_entry_into_database( $new_values ) {
816 global $wpdb;
817
818 $query_results = $wpdb->insert( $wpdb->prefix . 'frm_items', $new_values );
819
820 if ( ! $query_results ) {
821 $entry_id = false;
822 } else {
823 $entry_id = $wpdb->insert_id;
824 }
825
826 return $entry_id;
827 }
828
829 /**
830 * Add the new entry to global $frm_vars
831 *
832 * @since 2.0.16
833 *
834 * @param int $entry_id
835 */
836 private static function add_new_entry_to_frm_vars( $entry_id ) {
837 global $frm_vars;
838
839 if ( ! isset( $frm_vars['saved_entries'] ) ) {
840 $frm_vars['saved_entries'] = array();
841 }
842
843 $frm_vars['saved_entries'][] = (int) $entry_id;
844 }
845
846 /**
847 * Add entry metas, if there are any
848 *
849 * @since 2.0.16
850 *
851 * @param array $values
852 * @param int $entry_id
853 */
854 private static function maybe_add_entry_metas( $values, $entry_id ) {
855 if ( isset( $values['item_meta'] ) ) {
856 FrmEntryMeta::update_entry_metas( $entry_id, $values['item_meta'] );
857 }
858 }
859
860 /**
861 * Trigger frm_after_create_entry hooks
862 *
863 * @since 2.0.16
864 *
865 * @param int $entry_id
866 * @param array $new_values
867 */
868 private static function after_entry_created_actions( $entry_id, $values, $new_values ) {
869 // this is a child entry
870 $is_child = isset( $values['parent_form_id'] ) && isset( $values['parent_nonce'] ) && ! empty( $values['parent_form_id'] ) && wp_verify_nonce( $values['parent_nonce'], 'parent' );
871
872 do_action( 'frm_after_create_entry', $entry_id, $new_values['form_id'], compact( 'is_child' ) );
873 do_action( 'frm_after_create_entry_' . $new_values['form_id'], $entry_id, compact( 'is_child' ) );
874 }
875
876 /**
877 * Actions to perform immediately after an entry is inserted in the frm_items database
878 *
879 * @since 2.0.16
880 *
881 * @param array $values
882 * @param array $new_values
883 * @param int $entry_id
884 */
885 private static function after_insert_entry_in_database( $values, $new_values, $entry_id ) {
886
887 self::add_new_entry_to_frm_vars( $entry_id );
888
889 self::maybe_add_entry_metas( $values, $entry_id );
890
891 self::clear_cache();
892
893 self::after_entry_created_actions( $entry_id, $values, $new_values );
894 }
895
896 /**
897 * Perform some actions right before updating an entry
898 *
899 * @since 2.0.16
900 *
901 * @param int $id
902 * @param array $values
903 * @param string $update_type
904 *
905 * @return boolean $update
906 */
907 private static function before_update_entry( $id, &$values, $update_type ) {
908 $update = true;
909
910 global $frm_vars;
911
912 if ( isset( $frm_vars['saved_entries'] ) && is_array( $frm_vars['saved_entries'] ) && in_array( (int) $id, (array) $frm_vars['saved_entries'] ) ) {
913 $update = false;
914 }
915
916 if ( $update && $update_type != 'xml' ) {
917 $values = apply_filters( 'frm_pre_update_entry', $values, $id );
918 }
919
920 return $update;
921 }
922
923 /**
924 * Package the entry data for updating
925 *
926 * @since 2.0.16
927 *
928 * @param int $id
929 * @param array $values
930 *
931 * @return array $new_values
932 */
933 private static function package_entry_to_update( $id, $values ) {
934 global $wpdb;
935
936 $new_values = array(
937 'name' => self::get_new_entry_name( $values ),
938 'form_id' => (int) self::get_entry_value( $values, 'form_id', null ),
939 'is_draft' => self::get_is_draft_value( $values ),
940 'updated_at' => current_time( 'mysql', 1 ),
941 'updated_by' => isset( $values['updated_by'] ) ? $values['updated_by'] : get_current_user_id(),
942 );
943
944 if ( isset( $values['post_id'] ) ) {
945 $new_values['post_id'] = (int) $values['post_id'];
946 }
947
948 if ( isset( $values['item_key'] ) ) {
949 $new_values['item_key'] = FrmAppHelper::get_unique_key( $values['item_key'], $wpdb->prefix . 'frm_items', 'item_key', $id );
950 }
951
952 if ( isset( $values['parent_item_id'] ) ) {
953 $new_values['parent_item_id'] = (int) $values['parent_item_id'];
954 }
955
956 if ( isset( $values['frm_user_id'] ) && is_numeric( $values['frm_user_id'] ) ) {
957 $new_values['user_id'] = $values['frm_user_id'];
958 }
959
960 $new_values = apply_filters( 'frm_update_entry', $new_values, $id );
961
962 return $new_values;
963 }
964
965 /**
966 * Perform some actions right after updating an entry
967 *
968 * @since 2.0.16
969 *
970 * @param boolean|int $query_results
971 * @param int $id
972 * @param array $values
973 * @param array $new_values
974 */
975 private static function after_update_entry( $query_results, $id, $values, $new_values ) {
976 if ( $query_results ) {
977 self::clear_cache();
978 }
979
980 global $frm_vars;
981 if ( ! isset( $frm_vars['saved_entries'] ) ) {
982 $frm_vars['saved_entries'] = array();
983 }
984
985 $frm_vars['saved_entries'][] = (int) $id;
986
987 if ( isset( $values['item_meta'] ) ) {
988 FrmEntryMeta::update_entry_metas( $id, $values['item_meta'] );
989 }
990
991 do_action( 'frm_after_update_entry', $id, $new_values['form_id'] );
992 do_action( 'frm_after_update_entry_' . $new_values['form_id'], $id );
993 }
994
995 /**
996 * Create entry from an XML import
997 * Certain actions aren't necessary when importing (like saving sub entries, checking for duplicates, etc.)
998 *
999 * @since 2.0.16
1000 *
1001 * @param array $values
1002 *
1003 * @return int | boolean $entry_id
1004 */
1005 public static function create_entry_from_xml( $values ) {
1006 $entry_id = self::create_entry( $values, 'xml' );
1007
1008 return $entry_id;
1009 }
1010
1011 /**
1012 * Update entry from an XML import
1013 * Certain actions aren't necessary when importing (like saving sub entries and modifying other vals)
1014 *
1015 * @since 2.0.16
1016 *
1017 * @param int $id
1018 * @param array $values
1019 *
1020 * @return int | boolean $updated
1021 */
1022 public static function update_entry_from_xml( $id, $values ) {
1023 $updated = self::update_entry( $id, $values, 'xml' );
1024
1025 return $updated;
1026 }
1027
1028 /**
1029 * @param string $key
1030 *
1031 * @return int entry_id
1032 */
1033 public static function get_id_by_key( $key ) {
1034 $entry_id = FrmDb::get_var( 'frm_items', array( 'item_key' => sanitize_title( $key ) ) );
1035
1036 return (int) $entry_id;
1037 }
1038 }
1039