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

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