PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
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
← All changes | classes/models/FrmEntry.php +465 -186 6.5.3 → trunk View file →
@@ -5,45 +5,67 @@
5 5
6 6 class FrmEntry {
7 7
8 8 /**
9 + * @since 6.16.3
10 + *
11 + * @var array
12 + */
13 + private static $unique_id_match_checks = array();
14 +
15 + /**
9 16 * Create a new entry
10 17 *
11 18 * @param array $values
12 19 *
13 - * @return int | boolean $entry_id
20 + * @return bool|int Entry ID.
14 21 */
15 22 public static function create( $values ) {
16 - $entry_id = self::create_entry( $values, 'standard' );
17 -
18 - return $entry_id;
23 + return self::create_entry( $values, 'standard' );
19 24 }
20 25
21 26 /**
22 27 * Create a new entry with some differences depending on type
23 28 *
24 - * @param array $values
29 + * @param array $values
25 30 * @param string $type
26 31 *
27 - * @return int | boolean $entry_id
32 + * @return bool|int Entry ID.
28 33 */
29 34 private static function create_entry( $values, $type ) {
30 35 $new_values = self::before_insert_entry_in_database( $values, $type );
31 36
32 37 // Don't check XML entries for duplicates
33 - if ( $type != 'xml' && self::is_duplicate( $new_values, $values ) ) {
38 + if ( $type !== 'xml' && self::is_duplicate( $new_values, $values ) ) {
34 39 return false;
35 40 }
36 41
37 - $entry_id = self::continue_to_create_entry( $values, $new_values );
42 + return self::continue_to_create_entry( $values, $new_values );
43 + }
38 44
39 - return $entry_id;
45 + /**
46 + * Flag the memoized unique id check after a new entry is created.
47 + * This prevents possibly DB requests and helps avoid issues when creating repeater entries.
48 + *
49 + * @since 6.16.3
50 + *
51 + * @param string $unique_id
52 + *
53 + * @return void
54 + */
55 + private static function flag_new_unique_key( $unique_id ) {
56 + if ( ! isset( self::$unique_id_match_checks[ $unique_id ] ) ) {
57 + self::$unique_id_match_checks[ $unique_id ] = false;
58 + }
40 59 }
41 60
42 61 /**
43 62 * Check for duplicate entries created in the last minute
44 63 *
45 - * @return boolean
64 + * @param array $new_values New values.
65 + * @param array $values Values.
66 + *
67 + * @return bool
46 68 */
47 69 public static function is_duplicate( $new_values, $values ) {
48 70 $duplicate_entry_time = apply_filters( 'frm_time_to_check_duplicates', 60, $new_values );
49 71
@@ -50,13 +72,18 @@
50 72 if ( false === self::is_duplicate_check_needed( $values, $duplicate_entry_time ) ) {
51 73 return false;
52 74 }
53 75
76 + if ( self::maybe_check_for_unique_id_match( $values, $new_values['created_at'] ) ) {
77 + return true;
78 + }
79 +
54 80 $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 ) ) );
81 + $check_val['created_at >'] = gmdate( 'Y-m-d H:i:s', strtotime( $new_values['created_at'] ) - absint( $duplicate_entry_time ) );
56 82
57 83 unset( $check_val['created_at'], $check_val['updated_at'], $check_val['is_draft'], $check_val['id'], $check_val['item_key'] );
58 84
85 + // phpcs:ignore Universal.Operators.StrictComparisons
59 86 if ( $new_values['item_key'] == $new_values['name'] ) {
60 87 unset( $check_val['name'] );
61 88 }
62 89
@@ -61,26 +88,34 @@
61 88 }
62 89
63 90 $check_val = apply_filters( 'frm_duplicate_check_val', $check_val );
64 91
65 - global $wpdb;
66 - $entry_exists = FrmDb::get_col( $wpdb->prefix . 'frm_items', $check_val, 'id', array( 'order_by' => 'created_at DESC' ) );
92 + if ( ! isset( $values['item_meta'] ) ) {
93 + return false;
94 + }
67 95
68 - if ( ! $entry_exists || ! isset( $values['item_meta'] ) ) {
96 + $entry_exists = FrmDb::get_col( 'frm_items', $check_val, 'id', array( 'order_by' => 'created_at DESC' ) );
97 +
98 + if ( ! $entry_exists ) {
69 99 return false;
70 100 }
71 101
72 102 global $frm_vars;
73 103 $frm_vars['checking_duplicates'] = true;
104 + $is_duplicate = false;
74 105
75 - $is_duplicate = false;
76 106 foreach ( $entry_exists as $entry_exist ) {
77 107 $is_duplicate = true;
78 108
79 - // make sure it's a duplicate
109 + // Make sure it's a duplicate
80 110 $metas = FrmEntryMeta::get_entry_meta_info( $entry_exist );
81 111 $field_metas = array();
112 +
82 113 foreach ( $metas as $meta ) {
114 + if ( 0 === (int) $meta->field_id ) {
115 + continue;
116 + }
117 +
83 118 $field_metas[ $meta->field_id ] = $meta->meta_value;
84 119 }
85 120
86 121 $filtered_vals = array_filter( $values['item_meta'] );
@@ -87,13 +122,13 @@
87 122 $filtered_vals = self::convert_values_to_their_saved_value( $filtered_vals, $entry_exist );
88 123 $field_metas = array_filter( $field_metas );
89 124
90 125 // If prev entry is empty and current entry is not, they are not duplicates
91 - if ( empty( $field_metas ) && ! empty( $filtered_vals ) ) {
126 + if ( ! $field_metas && $filtered_vals ) {
92 127 return false;
93 128 }
94 129
95 - // compare serialized values and not arrays
130 + // Compare serialized values and not arrays
96 131 $new_meta = array_map( 'maybe_serialize', $filtered_vals );
97 132
98 133 if ( $field_metas === $new_meta ) {
99 134 $is_duplicate = true;
@@ -106,12 +141,12 @@
106 141 continue;
107 142 }
108 143
109 144 $diff = array_diff_assoc( $field_metas, $new_meta );
110 - foreach ( $diff as $field_id => $meta_value ) {
111 - if ( ! empty( $meta_value ) ) {
145 +
146 + foreach ( $diff as $meta_value ) {
147 + if ( $meta_value ) {
112 148 $is_duplicate = false;
113 - continue;
114 149 }
115 150 }
116 151
117 152 if ( $is_duplicate ) {
@@ -116,9 +151,9 @@
116 151
117 152 if ( $is_duplicate ) {
118 153 break;
119 154 }
120 - }
155 + }//end foreach
121 156
122 157 $frm_vars['checking_duplicates'] = false;
123 158
124 159 return $is_duplicate;
@@ -124,25 +159,95 @@
124 159 return $is_duplicate;
125 160 }
126 161
127 162 /**
163 + * @since 6.16.3
164 + *
165 + * @param array $values POST request data.
166 + * @param string $created_at The timestamp of the entry we are checking for.
167 + *
168 + * @return bool
169 + */
170 + private static function maybe_check_for_unique_id_match( $values, $created_at ) {
171 + if ( ! self::should_check_for_unique_id_match() ) {
172 + return false;
173 + }
174 +
175 + if ( empty( $values['unique_id'] ) ) {
176 + return false;
177 + }
178 +
179 + $unique_id = sanitize_key( $values['unique_id'] );
180 +
181 + if ( ! $unique_id ) {
182 + // Only continue if a unique ID was generated on form submit.
183 + return false;
184 + }
185 +
186 + if ( isset( self::$unique_id_match_checks[ $unique_id ] ) ) {
187 + return self::$unique_id_match_checks[ $unique_id ];
188 + }
189 +
190 + $timestamp = strtotime( $created_at );
191 +
192 + if ( false === $timestamp ) {
193 + $timestamp = time();
194 + }
195 +
196 + self::$unique_id_match_checks[ $unique_id ] = (bool) FrmDb::get_var(
197 + 'frm_item_metas',
198 + array(
199 + 'field_id' => 0,
200 + 'meta_value' => serialize( compact( 'unique_id' ) ),
201 + 'created_at >' => gmdate( 'Y-m-d H:i:s', $timestamp - MONTH_IN_SECONDS ),
202 + ),
203 + 'id'
204 + );
205 +
206 + return self::$unique_id_match_checks[ $unique_id ];
207 + }
208 +
209 + /**
210 + * @since 6.16.3
211 + *
212 + * @return bool
213 + */
214 + private static function should_check_for_unique_id_match() {
215 + /**
216 + * Allow users to opt out of the DB query, in case it causes performance issues.
217 + *
218 + * @since 6.16.3
219 + *
220 + * @param bool $should_extend
221 + */
222 + $should_check = apply_filters( 'frm_check_for_unique_id_match', true );
223 + return (bool) $should_check;
224 + }
225 +
226 + /**
128 227 * 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 228 *
229 + * This is important for the duplicate check as something like 'a:2:{s:5:"typed";s:0:"";s:6:"output";s:0:"";}'
230 + * (a signature value) is actually an empty string and does not get saved.
231 + *
131 232 * @param array $filter_vals
132 233 * @param int $entry_id
234 + *
133 235 * @return array
134 236 */
135 237 private static function convert_values_to_their_saved_value( $filter_vals, $entry_id ) {
136 238 $reduced = array();
239 +
137 240 foreach ( $filter_vals as $field_id => $value ) {
138 241 $field = FrmFieldFactory::get_field_object( $field_id );
139 242 $reduced[ $field_id ] = $field->get_value_to_save( $value, array( 'entry_id' => $entry_id ) );
140 243 $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 ] ) ) ) {
244 +
245 + if ( '' === $reduced[ $field_id ] || array() === $reduced[ $field_id ] ) {
142 246 unset( $reduced[ $field_id ] );
143 247 }
144 248 }
249 +
145 250 return $reduced;
146 251 }
147 252
148 253 /**
@@ -150,15 +255,15 @@
150 255 *
151 256 * @since 2.0.23
152 257 *
153 258 * @param array $values
154 - * @param int $duplicate_entry_time
259 + * @param int $duplicate_entry_time
155 260 *
156 261 * @return bool
157 262 */
158 263 private static function is_duplicate_check_needed( $values, $duplicate_entry_time ) {
159 264 // If time for checking duplicates is set to an empty value, don't check for duplicates
160 - if ( empty( $duplicate_entry_time ) ) {
265 + if ( ! $duplicate_entry_time ) {
161 266 return false;
162 267 }
163 268
164 269 // If CSV is importing, don't check for duplicates
@@ -166,20 +271,20 @@
166 271 return false;
167 272 }
168 273
169 274 // 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;
275 + return empty( $values['parent_form_id'] );
175 276 }
176 277
278 + /**
279 + * @param int|string $id
280 + *
281 + * @return false|int
282 + */
177 283 public static function duplicate( $id ) {
178 284 global $wpdb;
179 285
180 - $values = self::getOne( $id );
181 -
286 + $values = self::getOne( $id );
182 287 $new_values = array();
183 288 $new_values['item_key'] = FrmAppHelper::get_unique_key( '', $wpdb->prefix . 'frm_items', 'item_key' );
184 289 $new_values['name'] = $values->name;
185 290 $new_values['is_draft'] = $values->is_draft;
@@ -189,8 +294,9 @@
189 294 $new_values['created_at'] = current_time( 'mysql', 1 );
190 295 $new_values['updated_at'] = $new_values['created_at'];
191 296
192 297 $query_results = $wpdb->insert( $wpdb->prefix . 'frm_items', $new_values );
298 +
193 299 if ( ! $query_results ) {
194 300 return false;
195 301 }
196 302
@@ -196,8 +302,9 @@
196 302
197 303 $entry_id = $wpdb->insert_id;
198 304
199 305 global $frm_vars;
306 +
200 307 if ( ! isset( $frm_vars['saved_entries'] ) ) {
201 308 $frm_vars['saved_entries'] = array();
202 309 }
203 310 $frm_vars['saved_entries'][] = (int) $entry_id;
@@ -212,17 +319,15 @@
212 319
213 320 /**
214 321 * Update an entry (not via XML)
215 322 *
216 - * @param int $id
323 + * @param int $id
217 324 * @param array $values
218 325 *
219 - * @return boolean|int $update_results
326 + * @return bool|int Update results.
220 327 */
221 328 public static function update( $id, $values ) {
222 - $update_results = self::update_entry( $id, $values, 'standard' );
223 -
224 - return $update_results;
329 + return self::update_entry( $id, $values, 'standard' );
225 330 }
226 331
227 332 /**
228 333 * Update an entry with some differences depending on the update type
@@ -228,23 +333,24 @@
228 333 * Update an entry with some differences depending on the update type
229 334 *
230 335 * @since 2.0.16
231 336 *
232 - * @param int $id
233 - * @param array $values
337 + * @param int $id
338 + * @param array $values
339 + * @param string $update_type
234 340 *
235 - * @return boolean|int $query_results
341 + * @return bool|int Query results.
236 342 */
237 343 private static function update_entry( $id, $values, $update_type ) {
238 344 global $wpdb;
239 345
240 346 $update = self::before_update_entry( $id, $values, $update_type );
347 +
241 348 if ( ! $update ) {
242 349 return false;
243 350 }
244 351
245 - $new_values = self::package_entry_to_update( $id, $values );
246 -
352 + $new_values = self::package_entry_to_update( $id, $values, $update_type );
247 353 $query_results = $wpdb->update( $wpdb->prefix . 'frm_items', $new_values, compact( 'id' ) );
248 354
249 355 self::after_update_entry( $query_results, $id, $values, $new_values );
250 356
@@ -253,9 +359,10 @@
253 359
254 360 /**
255 361 * Delete an entry.
256 362 *
257 - * @param string|int $id
363 + * @param int|string $id
364 + *
258 365 * @return bool True on success, false if nothing was deleted.
259 366 */
260 367 public static function destroy( $id ) {
261 368 global $wpdb;
@@ -260,12 +367,13 @@
260 367 public static function destroy( $id ) {
261 368 global $wpdb;
262 369 $id = (int) $id;
263 370
264 - $entry = self::getOne( $id, true ); // Item meta is required for conditional logic in actions with 'delete' events.
371 + // Item meta is required for conditional logic in actions with 'delete' events.
372 + $entry = self::getOne( $id, true );
373 +
265 374 if ( ! $entry ) {
266 - $result = false;
267 - return $result;
375 + return false;
268 376 }
269 377
270 378 /**
271 379 * Trigger an action to run custom logic before the entry is deleted.
@@ -293,12 +401,20 @@
293 401
294 402 return $result;
295 403 }
296 404
405 + /**
406 + * @param int $id
407 + * @param mixed $value
408 + * @param int|string $form_id
409 + *
410 + * @return false|int
411 + */
297 412 public static function update_form( $id, $value, $form_id ) {
298 413 global $wpdb;
299 414 $form_id = isset( $value ) ? $form_id : null;
300 415 $result = $wpdb->update( $wpdb->prefix . 'frm_items', array( 'form_id' => $form_id ), array( 'id' => $id ) );
416 +
301 417 if ( $result ) {
302 418 self::clear_cache();
303 419 }
304 420
@@ -309,8 +425,10 @@
309 425 * Clear entry caching
310 426 * Called when an entry is changed
311 427 *
312 428 * @since 2.0.5
429 + *
430 + * @return void
313 431 */
314 432 public static function clear_cache() {
315 433 FrmDb::cache_delete_group( 'frm_entry' );
316 434 FrmDb::cache_delete_group( 'frm_item' );
@@ -322,33 +440,42 @@
322 440 * After switching to the wp_loaded hook for processing entries,
323 441 * we can no longer use 'name', but check it as a fallback
324 442 *
325 443 * @since 2.0.11
444 + *
445 + * @param array $values
446 + * @param array|string $default
447 + *
448 + * @return string
326 449 */
327 450 public static function get_new_entry_name( $values, $default = '' ) {
328 - $name = isset( $values['item_name'] ) ? $values['item_name'] : ( isset( $values['name'] ) ? $values['name'] : $default );
329 - if ( is_array( $name ) ) {
330 - $name = reset( $name );
331 - }
332 -
333 - return $name;
451 + $name = $values['item_name'] ?? $values['name'] ?? $default;
452 + return is_array( $name ) ? reset( $name ) : $name;
334 453 }
335 454
336 455 /**
337 456 * If $entry is numeric, get the entry object
338 457 *
339 - * @param int|object $entry by reference
458 + * @since 2.0.9
340 459 *
341 - * @since 2.0.9
460 + * @param int|object|string $entry By reference.
461 + *
462 + * @return void
342 463 */
343 464 public static function maybe_get_entry( &$entry ) {
344 465 if ( $entry && is_numeric( $entry ) ) {
345 466 $entry = self::getOne( $entry );
346 - } elseif ( empty( $entry ) || 'false' === $entry ) {
467 + } elseif ( ! $entry || 'false' === $entry ) {
347 468 $entry = false;
348 469 }
349 470 }
350 471
472 + /**
473 + * @param int|string $id
474 + * @param bool $meta
475 + *
476 + * @return object|null
477 + */
351 478 public static function getOne( $id, $meta = false ) {
352 479 global $wpdb;
353 480
354 481 $query = "SELECT it.*, fr.name as form_name, fr.form_key as form_key FROM {$wpdb->prefix}frm_items it
@@ -353,9 +480,9 @@
353 480
354 481 $query = "SELECT it.*, fr.name as form_name, fr.form_key as form_key FROM {$wpdb->prefix}frm_items it
355 482 LEFT OUTER JOIN {$wpdb->prefix}frm_forms fr ON it.form_id=fr.id WHERE ";
356 483
357 - $query .= is_numeric( $id ) ? 'it.id=%d' : 'it.item_key=%s';
484 + $query .= is_numeric( $id ) ? 'it.id=%d' : 'it.item_key=%s';
358 485 $query_args = array( $id );
359 486 $query = $wpdb->prepare( $query, $query_args ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
360 487
361 488 if ( ! $meta ) {
@@ -364,8 +491,9 @@
364 491 return $entry;
365 492 }
366 493
367 494 $entry = FrmDb::check_cache( $id, 'frm_entry' );
495 +
368 496 if ( $entry !== false ) {
369 497 self::prepare_entry( $entry );
370 498 return $entry;
371 499 }
@@ -380,16 +508,19 @@
380 508 /**
381 509 * @since 4.02.03
382 510 *
383 511 * @param object $entry
512 + *
513 + * @return void
384 514 */
385 515 private static function prepare_entry( &$entry ) {
386 - if ( empty( $entry ) ) {
516 + if ( ! $entry ) {
387 517 return;
388 518 }
389 519
390 520 FrmAppHelper::unserialize_or_decode( $entry->description );
391 - $entry = wp_unslash( $entry ); // TODO: Remove slashes on input only, not output.
521 + // TODO: Remove slashes on input only, not output.
522 + $entry = wp_unslash( $entry );
392 523 }
393 524
394 525 /**
395 526 * @since 4.02.03
@@ -394,8 +525,10 @@
394 525 /**
395 526 * @since 4.02.03
396 527 *
397 528 * @param array $entries
529 + *
530 + * @return void
398 531 */
399 532 private static function prepare_entries( &$entries ) {
400 533 foreach ( $entries as $k => $entry ) {
401 534 self::prepare_entry( $entry );
@@ -402,8 +535,13 @@
402 535 $entries[ $k ] = $entry;
403 536 }
404 537 }
405 538
539 + /**
540 + * @param object|null $entry
541 + *
542 + * @return object|null
543 + */
406 544 public static function get_meta( $entry ) {
407 545 if ( ! $entry ) {
408 546 return $entry;
409 547 }
@@ -420,13 +558,15 @@
420 558
421 559 $entry->metas = array();
422 560
423 561 $include_key = apply_filters( 'frm_include_meta_keys', false, array( 'form_id' => $entry->form_id ) );
562 +
424 563 foreach ( $metas as $meta_val ) {
425 564 FrmFieldsHelper::prepare_field_value( $meta_val->meta_value, $meta_val->type );
426 565
427 - if ( $meta_val->item_id == $entry->id ) {
566 + if ( (int) $meta_val->item_id === (int) $entry->id ) {
428 567 $entry->metas[ $meta_val->field_id ] = $meta_val->meta_value;
568 +
429 569 if ( $include_key ) {
430 570 $entry->metas[ $meta_val->field_key ] = $entry->metas[ $meta_val->field_id ];
431 571 }
432 572 continue;
@@ -431,9 +571,9 @@
431 571 }
432 572 continue;
433 573 }
434 574
435 - // include sub entries in an array
575 + // Include sub entries in an array
436 576 if ( ! isset( $entry->metas[ $meta_val->field_id ] ) ) {
437 577 $entry->metas[ $meta_val->field_id ] = array();
438 578 }
439 579
@@ -439,9 +579,9 @@
439 579
440 580 $entry->metas[ $meta_val->field_id ][] = $meta_val->meta_value;
441 581
442 582 unset( $meta_val );
443 - }
583 + }//end foreach
444 584 unset( $metas );
445 585
446 586 FrmDb::set_cache( $entry->id, $entry, 'frm_entry' );
447 587
@@ -449,43 +589,45 @@
449 589 }
450 590
451 591 /**
452 592 * @param string $id
593 + *
594 + * @return bool
453 595 */
454 596 public static function exists( $id ) {
455 - global $wpdb;
456 -
457 597 if ( FrmDb::check_cache( $id, 'frm_entry' ) ) {
458 - $exists = true;
459 -
460 - return $exists;
598 + return true;
461 599 }
462 600
463 - if ( is_numeric( $id ) ) {
464 - $where = array( 'id' => $id );
465 - } else {
466 - $where = array( 'item_key' => $id );
467 - }
468 - $id = FrmDb::get_var( $wpdb->prefix . 'frm_items', $where );
601 + $where = is_numeric( $id ) ? array( 'id' => $id ) : array( 'item_key' => $id );
602 + $id = FrmDb::get_var( 'frm_items', $where );
469 603
470 - return ( $id && $id > 0 );
604 + return $id && $id > 0;
471 605 }
472 606
607 + /**
608 + * @param array|string $where
609 + * @param string $order_by
610 + * @param string $limit
611 + * @param bool $meta
612 + * @param bool $inc_form
613 + *
614 + * @return array
615 + */
473 616 public static function getAll( $where, $order_by = '', $limit = '', $meta = false, $inc_form = true ) {
474 617 global $wpdb;
475 618
476 - $limit = FrmDb::esc_limit( $limit );
477 -
619 + $limit = FrmDb::esc_limit( $limit );
478 620 $cache_key = FrmAppHelper::maybe_json_encode( $where ) . $order_by . $limit . $inc_form;
479 621 $entries = wp_cache_get( $cache_key, 'frm_entry' );
480 622
481 623 if ( false === $entries ) {
482 - $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, it.description';
624 + $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, it.description'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
483 625 $table = $wpdb->prefix . 'frm_items it ';
484 626
485 627 if ( $inc_form ) {
486 628 $fields = 'it.*, fr.name as form_name,fr.form_key as form_key';
487 - $table .= 'LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_forms fr ON it.form_id=fr.id ';
629 + $table .= 'LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_forms fr ON it.form_id=fr.id ';
488 630 }
489 631
490 632 if ( preg_match( '/ meta_([0-9]+)/', $order_by, $order_matches ) ) {
491 633 $fields .= self::sort_by_field( $order_matches[1] );
@@ -491,9 +633,9 @@
491 633 $fields .= self::sort_by_field( $order_matches[1] );
492 634 unset( $order_matches );
493 635 }
494 636
495 - // prepare the query
637 + // Prepare the query
496 638 $query = 'SELECT ' . $fields . ' FROM ' . $table . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
497 639
498 640 $entries = $wpdb->get_results( $query, OBJECT_K ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
499 641 unset( $query );
@@ -498,9 +640,9 @@
498 640 $entries = $wpdb->get_results( $query, OBJECT_K ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
499 641 unset( $query );
500 642
501 643 FrmDb::set_cache( $cache_key, $entries, 'frm_entry' );
502 - }
644 + }//end if
503 645
504 646 if ( ! $meta || ! $entries ) {
505 647 self::prepare_entries( $entries );
506 648 return $entries;
@@ -511,9 +653,11 @@
511 653 $where = array( 'it.form_id' => substr( $where, 11 ) );
512 654 }
513 655
514 656 $meta_where = array( 'field_id !' => 0 );
515 - if ( $limit == '' && is_array( $where ) && count( $where ) == 1 && isset( $where['it.form_id'] ) ) {
657 +
658 + // phpcs:ignore Universal.Operators.StrictComparisons
659 + if ( $limit == '' && is_array( $where ) && count( $where ) === 1 && isset( $where['it.form_id'] ) ) {
516 660 $meta_where['fi.form_id'] = $where['it.form_id'];
517 661 } else {
518 662 $meta_where['item_id'] = array_keys( $entries );
519 663 }
@@ -556,15 +700,15 @@
556 700 return $entries;
557 701 }
558 702
559 703 /**
560 - * @param int $field_id
704 + * @param int|string $field_id
705 + *
561 706 * @return string
562 707 */
563 708 private static function sort_by_field( $field_id ) {
564 709 global $wpdb;
565 - $field_id = (int) $field_id;
566 -
710 + $field_id = (int) $field_id;
567 711 $field_options = FrmDb::get_var( 'frm_fields', array( 'id' => $field_id ), 'field_options' );
568 712 FrmAppHelper::unserialize_or_decode( $field_options );
569 713
570 714 if ( empty( $field_options['post_field'] ) ) {
@@ -577,13 +721,15 @@
577 721 }
578 722
579 723 // Pagination Methods
580 724 /**
581 - * @param int|array|string If int, use the form id.
725 + * @param array|int|string $where If int, use the form id.
726 + *
727 + * @return int|string
582 728 */
583 729 public static function getRecordCount( $where = '' ) {
584 730 global $wpdb;
585 - $table_join = $wpdb->prefix . 'frm_items it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_forms fr ON it.form_id=fr.id';
731 + $table_join = $wpdb->prefix . 'frm_items it JOIN ' . $wpdb->prefix . 'frm_forms fr ON it.form_id=fr.id';
586 732
587 733 if ( is_numeric( $where ) ) {
588 734 $table_join = 'frm_items';
589 735 $where = array( 'form_id' => $where );
@@ -589,29 +735,35 @@
589 735 $where = array( 'form_id' => $where );
590 736 }
591 737
592 738 if ( is_array( $where ) ) {
593 - $count = FrmDb::get_count( $table_join, $where );
594 - } else {
595 - $cache_key = 'count_' . FrmAppHelper::maybe_json_encode( $where );
596 - $query = 'SELECT COUNT(*) FROM ' . $table_join . FrmDb::prepend_and_or_where( ' WHERE ', $where );
597 - $count = FrmDb::check_cache( $cache_key, 'frm_entry', $query, 'get_var' );
739 + return FrmDb::get_count( $table_join, $where );
598 740 }
599 741
600 - return $count;
742 + $cache_key = 'count_' . FrmAppHelper::maybe_json_encode( $where );
743 + $query = 'SELECT COUNT(*) FROM ' . $table_join . FrmDb::prepend_and_or_where( ' WHERE ', $where );
744 +
745 + return FrmDb::check_cache( $cache_key, 'frm_entry', $query, 'get_var' );
601 746 }
602 747
748 + /**
749 + * @param int|string $p_size
750 + * @param array|int|string $where
751 + *
752 + * @return int
753 + */
603 754 public static function getPageCount( $p_size, $where = '' ) {
604 755 $p_size = (int) $p_size;
605 - $count = 1;
756 +
606 757 if ( $p_size ) {
607 758 if ( ! is_numeric( $where ) ) {
608 759 $where = self::getRecordCount( $where );
609 760 }
610 - $count = ceil( (int) $where / $p_size );
761 +
762 + return ceil( (int) $where / $p_size );
611 763 }
612 764
613 - return $count;
765 + return 1;
614 766 }
615 767
616 768 /**
617 769 * Prepare the data before inserting it into the database
@@ -617,24 +769,21 @@
617 769 * Prepare the data before inserting it into the database
618 770 *
619 771 * @since 2.0.16
620 772 *
621 - * @param array $values
773 + * @param array $values
622 774 * @param string $type
623 775 *
624 - * @return array $new_values
776 + * @return array New values.
625 777 */
626 778 private static function before_insert_entry_in_database( &$values, $type ) {
627 -
628 779 self::sanitize_entry_post( $values );
629 780
630 - if ( $type != 'xml' ) {
781 + if ( $type !== 'xml' ) {
631 782 $values = apply_filters( 'frm_pre_create_entry', $values );
632 783 }
633 784
634 - $new_values = self::package_entry_data( $values );
635 -
636 - return $new_values;
785 + return self::package_entry_data( $values, $type );
637 786 }
638 787
639 788 /**
640 789 * Create an entry and perform after create actions
@@ -643,12 +792,13 @@
643 792 *
644 793 * @param array $values
645 794 * @param array $new_values
646 795 *
647 - * @return boolean|int $entry_id
796 + * @return bool|int Entry ID.
648 797 */
649 798 private static function continue_to_create_entry( $values, $new_values ) {
650 799 $entry_id = self::insert_entry_into_database( $new_values );
800 +
651 801 if ( ! $entry_id ) {
652 802 return false;
653 803 }
654 804
@@ -661,9 +811,11 @@
661 811 * Sanitize the POST values before we use them
662 812 *
663 813 * @since 2.0
664 814 *
665 - * @param array $values The POST values by reference
815 + * @param array $values The POST values by reference.
816 + *
817 + * @return void
666 818 */
667 819 public static function sanitize_entry_post( &$values ) {
668 820 $sanitize_method = array(
669 821 'form_id' => 'absint',
@@ -686,13 +838,14 @@
686 838 * Prepare the new values for inserting into the database
687 839 *
688 840 * @since 2.0.16
689 841 *
690 - * @param array $values
842 + * @param array $values
843 + * @param string $type The create type. 'xml' for an import.
691 844 *
692 - * @return array $new_values
845 + * @return array New values.
693 846 */
694 - private static function package_entry_data( &$values ) {
847 + private static function package_entry_data( &$values, $type = 'standard' ) {
695 848 global $wpdb;
696 849
697 850 if ( ! isset( $values['item_key'] ) ) {
698 851 $values['item_key'] = '';
@@ -700,9 +853,9 @@
700 853
701 854 $item_name = self::get_new_entry_name( $values, $values['item_key'] );
702 855 $new_values = array(
703 856 'item_key' => FrmAppHelper::get_unique_key( $values['item_key'], $wpdb->prefix . 'frm_items', 'item_key' ),
704 - 'name' => FrmAppHelper::truncate( $item_name, 255, 1, '' ),
857 + 'name' => FrmAppHelper::truncate( $item_name, 255, 1, '', true ),
705 858 'ip' => self::get_ip( $values ),
706 859 'is_draft' => self::get_is_draft_value( $values ),
707 860 'form_id' => (int) self::get_entry_value( $values, 'form_id', null ),
708 861 'post_id' => (int) self::get_entry_value( $values, 'post_id', 0 ),
@@ -709,21 +862,53 @@
709 862 'parent_item_id' => (int) self::get_entry_value( $values, 'parent_item_id', 0 ),
710 863 'created_at' => self::get_created_at( $values ),
711 864 'updated_at' => self::get_updated_at( $values ),
712 865 'description' => self::get_entry_description( $values ),
713 - 'user_id' => self::get_entry_user_id( $values ),
866 + 'user_id' => self::get_entry_user_id( $values, $type ),
714 867 );
715 868
716 - $new_values['updated_by'] = isset( $values['updated_by'] ) ? $values['updated_by'] : $new_values['user_id'];
869 + $new_values['updated_by'] = self::get_updated_by( $values, $type, $new_values['user_id'] );
717 870
718 871 return $new_values;
719 872 }
720 873
874 + /**
875 + * @param array $values
876 + * @param string $name
877 + * @param mixed $default
878 + *
879 + * @return mixed
880 + */
721 881 private static function get_entry_value( $values, $name, $default ) {
722 - return isset( $values[ $name ] ) ? $values[ $name ] : $default;
882 + return $values[ $name ] ?? $default;
723 883 }
724 884
725 885 /**
886 + * Get the updated_by value for an entry.
887 + *
888 + * The submitted value is only used during a trusted import, which restores the user who last
889 + * edited each entry. Every other save is being made by the current user, so a submitted
890 + * updated_by is ignored and cannot be pointed at another account. This matters because
891 + * updated_by is treated as a privilege signal when deciding how much HTML to strip from entry
892 + * values in FrmFieldType::should_strip_most_html().
893 + *
894 + * @since 6.35
895 + *
896 + * @param array $values
897 + * @param string $type The create/update type. 'xml' for an import.
898 + * @param int|string $default The value to use when an import doesn't include updated_by.
899 + *
900 + * @return int
901 + */
902 + private static function get_updated_by( $values, $type, $default ) {
903 + if ( self::is_trusted_import( $type ) ) {
904 + return absint( self::get_entry_value( $values, 'updated_by', $default ) );
905 + }
906 +
907 + return get_current_user_id();
908 + }
909 +
910 + /**
726 911 * Get the ip for a new entry.
727 912 * Allow the import to override the value.
728 913 *
729 914 * @since 2.03.10
@@ -737,10 +922,11 @@
737 922 return '';
738 923 }
739 924
740 925 $ip = FrmAppHelper::get_ip_address();
926 +
741 927 if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
742 - $ip = self::get_entry_value( $values, 'ip', $ip );
928 + return self::get_entry_value( $values, 'ip', $ip );
743 929 }
744 930
745 931 return $ip;
746 932 }
@@ -784,15 +970,9 @@
784 970 *
785 971 * @return string
786 972 */
787 973 private static function get_updated_at( $values ) {
788 - if ( isset( $values['updated_at'] ) ) {
789 - $updated_at = $values['updated_at'];
790 - } else {
791 - $updated_at = self::get_created_at( $values );
792 - }
793 -
794 - return $updated_at;
974 + return $values['updated_at'] ?? self::get_created_at( $values );
795 975 }
796 976
797 977 /**
798 978 * Get the description value for a new entry
@@ -803,20 +983,18 @@
803 983 *
804 984 * @return string
805 985 */
806 986 private static function get_entry_description( $values ) {
807 - if ( isset( $values['description'] ) && ! empty( $values['description'] ) ) {
808 - $description = FrmAppHelper::maybe_json_encode( $values['description'] );
809 - } else {
810 - $description = json_encode(
811 - array(
812 - 'browser' => FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' ),
813 - 'referrer' => FrmAppHelper::get_server_value( 'HTTP_REFERER' ),
814 - )
815 - );
987 + if ( ! empty( $values['description'] ) ) {
988 + return FrmAppHelper::maybe_json_encode( $values['description'] );
816 989 }
817 990
818 - return $description;
991 + return json_encode(
992 + array(
993 + 'browser' => FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' ),
994 + 'referrer' => FrmAppHelper::get_server_value( 'HTTP_REFERER' ),
995 + )
996 + );
819 997 }
820 998
821 999 /**
822 1000 * Get the user_id value for a new entry
@@ -822,24 +1000,61 @@
822 1000 * Get the user_id value for a new entry
823 1001 *
824 1002 * @since 2.0.16
825 1003 *
826 - * @param array $values
1004 + * @param array $values
1005 + * @param string $type The create type. 'xml' for an import.
827 1006 *
828 1007 * @return int
829 1008 */
830 - private static function get_entry_user_id( $values ) {
831 - if ( isset( $values['frm_user_id'] ) && ( is_numeric( $values['frm_user_id'] ) || FrmAppHelper::is_admin() ) ) {
832 - $user_id = $values['frm_user_id'];
833 - } else {
834 - $current_user_id = get_current_user_id();
835 - $user_id = $current_user_id ? $current_user_id : 0;
1009 + private static function get_entry_user_id( $values, $type = 'standard' ) {
1010 + if ( isset( $values['frm_user_id'] ) && self::can_set_entry_user_id_from_values( $type ) ) {
1011 + return $values['frm_user_id'];
836 1012 }
837 1013
838 - return $user_id;
1014 + $current_user_id = get_current_user_id();
1015 + return $current_user_id ? $current_user_id : 0;
839 1016 }
840 1017
841 1018 /**
1019 + * Whether a submitted frm_user_id is allowed to set the entry owner.
1020 + *
1021 + * The owner is only taken from the submitted value when the current user is allowed to manage
1022 + * entries, or during a trusted import that restores each entry's original owner. On a public
1023 + * submission neither is true, so the owner falls back to the current user and cannot be set to
1024 + * another account.
1025 + *
1026 + * @since 6.34
1027 + *
1028 + * @param string $type The create/update type. 'xml' for an import.
1029 + *
1030 + * @return bool
1031 + */
1032 + private static function can_set_entry_user_id_from_values( $type = 'standard' ) {
1033 + if ( self::is_trusted_import( $type ) ) {
1034 + return true;
1035 + }
1036 +
1037 + return current_user_can( 'frm_edit_entries' ) || current_user_can( 'administrator' );
1038 + }
1039 +
1040 + /**
1041 + * Whether an entry is being saved by an import rather than by a normal request.
1042 + *
1043 + * An import is trusted to restore the values stored on each entry, including the columns that
1044 + * are otherwise taken from the current request.
1045 + *
1046 + * @since 6.35
1047 + *
1048 + * @param string $type The create/update type. 'xml' for an import.
1049 + *
1050 + * @return bool
1051 + */
1052 + private static function is_trusted_import( $type = 'standard' ) {
1053 + return 'xml' === $type || ( defined( 'WP_IMPORTING' ) && WP_IMPORTING );
1054 + }
1055 +
1056 + /**
842 1057 * Insert new entry into the database
843 1058 *
844 1059 * @since 2.0.16
845 1060 *
@@ -844,9 +1059,9 @@
844 1059 * @since 2.0.16
845 1060 *
846 1061 * @param array $new_values
847 1062 *
848 - * @return int | boolean $entry_id
1063 + * @return bool|int Entry ID.
849 1064 */
850 1065 private static function insert_entry_into_database( $new_values ) {
851 1066 global $wpdb;
852 1067
@@ -851,15 +1066,9 @@
851 1066 global $wpdb;
852 1067
853 1068 $query_results = $wpdb->insert( $wpdb->prefix . 'frm_items', $new_values );
854 1069
855 - if ( ! $query_results ) {
856 - $entry_id = false;
857 - } else {
858 - $entry_id = $wpdb->insert_id;
859 - }
860 -
861 - return $entry_id;
1070 + return $query_results ? $wpdb->insert_id : false;
862 1071 }
863 1072
864 1073 /**
865 1074 * Add the new entry to global $frm_vars
@@ -865,9 +1074,11 @@
865 1074 * Add the new entry to global $frm_vars
866 1075 *
867 1076 * @since 2.0.16
868 1077 *
869 - * @param int $entry_id
1078 + * @param int|string $entry_id
1079 + *
1080 + * @return void
870 1081 */
871 1082 private static function add_new_entry_to_frm_vars( $entry_id ) {
872 1083 global $frm_vars;
873 1084
@@ -882,32 +1093,63 @@
882 1093 * Add entry metas, if there are any
883 1094 *
884 1095 * @since 2.0.16
885 1096 *
886 - * @param array $values
887 - * @param int $entry_id
1097 + * @param array $values
1098 + * @param int|string $entry_id
1099 + *
888 1100 * @return void
889 1101 */
890 1102 private static function maybe_add_entry_metas( $values, $entry_id ) {
891 1103 if ( isset( $values['item_meta'] ) ) {
892 1104 FrmEntryMeta::update_entry_metas( $entry_id, $values['item_meta'] );
1105 + self::maybe_add_unique_id_meta( $values, $entry_id );
893 1106 }
894 1107 self::maybe_add_captcha_meta( (int) $values['form_id'], (int) $entry_id );
895 1108 }
896 1109
897 1110 /**
1111 + * @since 6.16.3
1112 + *
1113 + * @param array $values
1114 + * @param int $entry_id
1115 + *
1116 + * @return void
1117 + */
1118 + private static function maybe_add_unique_id_meta( $values, $entry_id ) {
1119 + if ( ! empty( $values['parent_form_id'] ) || empty( $values['unique_id'] ) || ! self::should_check_for_unique_id_match() ) {
1120 + return;
1121 + }
1122 +
1123 + // This unique ID is inserted with JS on form submit.
1124 + // It is used to check for duplicate entries.
1125 + $unique_id = sanitize_key( $values['unique_id'] );
1126 +
1127 + if ( ! $unique_id ) {
1128 + return;
1129 + }
1130 +
1131 + FrmEntryMeta::add_entry_meta( $entry_id, 0, '', compact( 'unique_id' ) );
1132 + self::flag_new_unique_key( $unique_id );
1133 + }
1134 +
1135 + /**
898 1136 * @since 5.0.15
899 1137 *
900 1138 * @param int $form_id
901 1139 * @param int $entry_id
1140 + *
902 1141 * @return void
903 1142 */
904 1143 private static function maybe_add_captcha_meta( $form_id, $entry_id ) {
905 1144 global $frm_vars;
906 - if ( array_key_exists( 'captcha_scores', $frm_vars ) && array_key_exists( $form_id, $frm_vars['captcha_scores'] ) ) {
907 - $captcha_score_meta = array( 'captcha_score' => $frm_vars['captcha_scores'][ $form_id ] );
908 - FrmEntryMeta::add_entry_meta( $entry_id, 0, '', maybe_serialize( $captcha_score_meta ) );
1145 +
1146 + if ( ! array_key_exists( 'captcha_scores', $frm_vars ) || ! array_key_exists( $form_id, $frm_vars['captcha_scores'] ) ) {
1147 + return;
909 1148 }
1149 +
1150 + $captcha_score_meta = array( 'captcha_score' => $frm_vars['captcha_scores'][ $form_id ] );
1151 + FrmEntryMeta::add_entry_meta( $entry_id, 0, '', maybe_serialize( $captcha_score_meta ) );
910 1152 }
911 1153
912 1154 /**
913 1155 * Trigger frm_after_create_entry hooks
@@ -913,17 +1155,30 @@
913 1155 * Trigger frm_after_create_entry hooks
914 1156 *
915 1157 * @since 2.0.16
916 1158 *
917 - * @param int $entry_id
1159 + * @param int $entry_id
1160 + * @param array $values
918 1161 * @param array $new_values
1162 + *
1163 + * @return void
919 1164 */
920 1165 private static function after_entry_created_actions( $entry_id, $values, $new_values ) {
921 - // this is a child entry
922 - $is_child = isset( $values['parent_form_id'] ) && isset( $values['parent_nonce'] ) && ! empty( $values['parent_form_id'] ) && wp_verify_nonce( $values['parent_nonce'], 'parent' );
1166 + // This is a child entry.
1167 + $is_child = isset( $values['parent_nonce'] ) && ! empty( $values['parent_form_id'] ) && wp_verify_nonce( $values['parent_nonce'], 'parent' );
923 1168
924 1169 do_action( 'frm_after_create_entry', $entry_id, $new_values['form_id'], compact( 'is_child' ) );
925 1170 do_action( 'frm_after_create_entry_' . $new_values['form_id'], $entry_id, compact( 'is_child' ) );
1171 +
1172 + if ( ! empty( $values['form_key'] ) ) {
1173 + /**
1174 + * @since 6.30
1175 + *
1176 + * @param int $entry_id
1177 + * @param array $is_child
1178 + */
1179 + do_action( 'frm_after_create_entry_' . $values['form_key'], $entry_id, compact( 'is_child' ) );
1180 + }
926 1181 }
927 1182
928 1183 /**
929 1184 * Actions to perform immediately after an entry is inserted in the frm_items database
@@ -931,12 +1186,13 @@
931 1186 * @since 2.0.16
932 1187 *
933 1188 * @param array $values
934 1189 * @param array $new_values
935 - * @param int $entry_id
1190 + * @param int $entry_id
1191 + *
1192 + * @return void
936 1193 */
937 1194 private static function after_insert_entry_in_database( $values, $new_values, $entry_id ) {
938 -
939 1195 self::add_new_entry_to_frm_vars( $entry_id );
940 1196
941 1197 self::maybe_add_entry_metas( $values, $entry_id );
942 1198
@@ -949,13 +1205,13 @@
949 1205 * Perform some actions right before updating an entry
950 1206 *
951 1207 * @since 2.0.16
952 1208 *
953 - * @param int $id
954 - * @param array $values
955 - * @param string $update_type
1209 + * @param int|string $id
1210 + * @param array $values
1211 + * @param string $update_type
956 1212 *
957 - * @return boolean $update
1213 + * @return bool Update.
958 1214 */
959 1215 private static function before_update_entry( $id, &$values, $update_type ) {
960 1216 $update = true;
961 1217
@@ -960,13 +1216,14 @@
960 1216 $update = true;
961 1217
962 1218 global $frm_vars;
963 1219
964 - if ( isset( $frm_vars['saved_entries'] ) && is_array( $frm_vars['saved_entries'] ) && in_array( (int) $id, (array) $frm_vars['saved_entries'] ) ) {
1220 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
1221 + if ( isset( $frm_vars['saved_entries'] ) && is_array( $frm_vars['saved_entries'] ) && in_array( (int) $id, $frm_vars['saved_entries'] ) ) {
965 1222 $update = false;
966 1223 }
967 1224
968 - if ( $update && $update_type != 'xml' ) {
1225 + if ( $update && $update_type !== 'xml' ) {
969 1226 $values = apply_filters( 'frm_pre_update_entry', $values, $id );
970 1227 }
971 1228
972 1229 return $update;
@@ -976,22 +1233,23 @@
976 1233 * Package the entry data for updating
977 1234 *
978 1235 * @since 2.0.16
979 1236 *
980 - * @param int $id
981 - * @param array $values
1237 + * @param int $id
1238 + * @param array $values
1239 + * @param string $update_type The update type. 'xml' for an import.
982 1240 *
983 - * @return array $new_values
1241 + * @return array New values.
984 1242 */
985 - private static function package_entry_to_update( $id, $values ) {
1243 + private static function package_entry_to_update( $id, $values, $update_type = 'standard' ) {
986 1244 global $wpdb;
987 1245
988 1246 $new_values = array(
989 - 'name' => self::get_new_entry_name( $values ),
1247 + 'name' => FrmAppHelper::truncate( self::get_new_entry_name( $values ), 255, 1, '', true ),
990 1248 'form_id' => (int) self::get_entry_value( $values, 'form_id', null ),
991 1249 'is_draft' => self::get_is_draft_value( $values ),
992 1250 'updated_at' => current_time( 'mysql', 1 ),
993 - 'updated_by' => isset( $values['updated_by'] ) ? $values['updated_by'] : get_current_user_id(),
1251 + 'updated_by' => self::get_updated_by( $values, $update_type, get_current_user_id() ),
994 1252 );
995 1253
996 1254 if ( isset( $values['post_id'] ) ) {
997 1255 $new_values['post_id'] = (int) $values['post_id'];
@@ -1004,15 +1262,13 @@
1004 1262 if ( isset( $values['parent_item_id'] ) ) {
1005 1263 $new_values['parent_item_id'] = (int) $values['parent_item_id'];
1006 1264 }
1007 1265
1008 - if ( isset( $values['frm_user_id'] ) && is_numeric( $values['frm_user_id'] ) ) {
1266 + if ( isset( $values['frm_user_id'] ) && is_numeric( $values['frm_user_id'] ) && self::can_set_entry_user_id_from_values( $update_type ) ) {
1009 1267 $new_values['user_id'] = $values['frm_user_id'];
1010 1268 }
1011 1269
1012 - $new_values = apply_filters( 'frm_update_entry', $new_values, $id );
1013 -
1014 - return $new_values;
1270 + return apply_filters( 'frm_update_entry', $new_values, $id );
1015 1271 }
1016 1272
1017 1273 /**
1018 1274 * Perform some actions right after updating an entry
@@ -1018,12 +1274,14 @@
1018 1274 * Perform some actions right after updating an entry
1019 1275 *
1020 1276 * @since 2.0.16
1021 1277 *
1022 - * @param boolean|int $query_results
1023 - * @param int $id
1024 - * @param array $values
1025 - * @param array $new_values
1278 + * @param bool|int $query_results
1279 + * @param int|string $id
1280 + * @param array $values
1281 + * @param array $new_values
1282 + *
1283 + * @return void
1026 1284 */
1027 1285 private static function after_update_entry( $query_results, $id, $values, $new_values ) {
1028 1286 if ( $query_results ) {
1029 1287 self::clear_cache();
@@ -1029,8 +1287,9 @@
1029 1287 self::clear_cache();
1030 1288 }
1031 1289
1032 1290 global $frm_vars;
1291 +
1033 1292 if ( ! isset( $frm_vars['saved_entries'] ) ) {
1034 1293 $frm_vars['saved_entries'] = array();
1035 1294 }
1036 1295
@@ -1041,8 +1300,17 @@
1041 1300 }
1042 1301
1043 1302 do_action( 'frm_after_update_entry', $id, $new_values['form_id'] );
1044 1303 do_action( 'frm_after_update_entry_' . $new_values['form_id'], $id );
1304 +
1305 + if ( ! empty( $values['form_key'] ) ) {
1306 + /**
1307 + * @since 6.30
1308 + *
1309 + * @param int $entry_id
1310 + */
1311 + do_action( 'frm_after_update_entry_' . $values['form_key'], $id );
1312 + }
1045 1313 }
1046 1314
1047 1315 /**
1048 1316 * Create entry from an XML import
@@ -1051,14 +1319,12 @@
1051 1319 * @since 2.0.16
1052 1320 *
1053 1321 * @param array $values
1054 1322 *
1055 - * @return int | boolean $entry_id
1323 + * @return bool|int Entry ID.
1056 1324 */
1057 1325 public static function create_entry_from_xml( $values ) {
1058 - $entry_id = self::create_entry( $values, 'xml' );
1059 -
1060 - return $entry_id;
1326 + return self::create_entry( $values, 'xml' );
1061 1327 }
1062 1328
1063 1329 /**
1064 1330 * Update entry from an XML import
@@ -1065,17 +1331,15 @@
1065 1331 * Certain actions aren't necessary when importing (like saving sub entries and modifying other vals)
1066 1332 *
1067 1333 * @since 2.0.16
1068 1334 *
1069 - * @param int $id
1335 + * @param int $id
1070 1336 * @param array $values
1071 1337 *
1072 - * @return int | boolean $updated
1338 + * @return bool|int Updated.
1073 1339 */
1074 1340 public static function update_entry_from_xml( $id, $values ) {
1075 - $updated = self::update_entry( $id, $values, 'xml' );
1076 -
1077 - return $updated;
1341 + return self::update_entry( $id, $values, 'xml' );
1078 1342 }
1079 1343
1080 1344 /**
1081 1345 * @param string $key
@@ -1083,8 +1347,23 @@
1083 1347 * @return int entry_id
1084 1348 */
1085 1349 public static function get_id_by_key( $key ) {
1086 1350 $entry_id = FrmDb::get_var( 'frm_items', array( 'item_key' => sanitize_title( $key ) ) );
1351 + return (int) $entry_id;
1352 + }
1087 1353
1088 - return (int) $entry_id;
1354 + /**
1355 + * Get entries count.
1356 + *
1357 + * @since 6.8
1358 + *
1359 + * @return int|string
1360 + */
1361 + public static function get_entries_count() {
1362 + $args = array(
1363 + 'or' => 1,
1364 + 'parent_form_id' => null,
1365 + 'parent_form_id <' => 1,
1366 + );
1367 + return self::getRecordCount( $args );
1089 1368 }
1090 1369 }