| @@ -53,26 +53,22 @@ | ||
| 53 | 53 | |
| 54 | 54 | $check_val = $new_values; |
| 55 | 55 | $check_val['created_at >'] = gmdate( 'Y-m-d H:i:s', ( strtotime( $new_values['created_at'] ) - absint( $duplicate_entry_time ) ) ); |
| 56 | 56 | |
| 57 | - unset( $check_val['created_at'], $check_val['updated_at'], $check_val['is_draft'], $check_val['id'], $check_val['item_key'] ); | |
| 57 | + unset( $check_val['created_at'], $check_val['updated_at'] ); | |
| 58 | + unset( $check_val['is_draft'], $check_val['id'], $check_val['item_key'] ); | |
| 58 | 59 | |
| 59 | 60 | if ( $new_values['item_key'] == $new_values['name'] ) { |
| 60 | 61 | unset( $check_val['name'] ); |
| 61 | 62 | } |
| 62 | 63 | |
| 63 | - $check_val = apply_filters( 'frm_duplicate_check_val', $check_val ); | |
| 64 | - | |
| 65 | 64 | global $wpdb; |
| 66 | 65 | $entry_exists = FrmDb::get_col( $wpdb->prefix . 'frm_items', $check_val, 'id', array( 'order_by' => 'created_at DESC' ) ); |
| 67 | 66 | |
| 68 | - if ( ! $entry_exists || ! isset( $values['item_meta'] ) ) { | |
| 67 | + if ( ! $entry_exists || empty( $entry_exists ) || ! isset( $values['item_meta'] ) ) { | |
| 69 | 68 | return false; |
| 70 | 69 | } |
| 71 | 70 | |
| 72 | - global $frm_vars; | |
| 73 | - $frm_vars['checking_duplicates'] = true; | |
| 74 | - | |
| 75 | 71 | $is_duplicate = false; |
| 76 | 72 | foreach ( $entry_exists as $entry_exist ) { |
| 77 | 73 | $is_duplicate = true; |
| 78 | 74 | |
| @@ -82,13 +78,11 @@ | ||
| 82 | 78 | foreach ( $metas as $meta ) { |
| 83 | 79 | $field_metas[ $meta->field_id ] = $meta->meta_value; |
| 84 | 80 | } |
| 85 | 81 | |
| 82 | + // If prev entry is empty and current entry is not, they are not duplicates | |
| 86 | 83 | $filtered_vals = array_filter( $values['item_meta'] ); |
| 87 | - $filtered_vals = self::convert_values_to_their_saved_value( $filtered_vals, $entry_exist ); | |
| 88 | 84 | $field_metas = array_filter( $field_metas ); |
| 89 | - | |
| 90 | - // If prev entry is empty and current entry is not, they are not duplicates | |
| 91 | 85 | if ( empty( $field_metas ) && ! empty( $filtered_vals ) ) { |
| 92 | 86 | return false; |
| 93 | 87 | } |
| 94 | 88 | |
| @@ -118,35 +112,12 @@ | ||
| 118 | 112 | break; |
| 119 | 113 | } |
| 120 | 114 | } |
| 121 | 115 | |
| 122 | - $frm_vars['checking_duplicates'] = false; | |
| 123 | - | |
| 124 | 116 | return $is_duplicate; |
| 125 | 117 | } |
| 126 | 118 | |
| 127 | 119 | /** |
| 128 | - * Convert form data to the actual value that would be saved into the database. | |
| 129 | - * This is important for the duplicate check as something like 'a:2:{s:5:"typed";s:0:"";s:6:"output";s:0:"";}' (a signature value) is actually an empty string and does not get saved. | |
| 130 | - * | |
| 131 | - * @param array $filter_vals | |
| 132 | - * @param int $entry_id | |
| 133 | - * @return array | |
| 134 | - */ | |
| 135 | - private static function convert_values_to_their_saved_value( $filter_vals, $entry_id ) { | |
| 136 | - $reduced = array(); | |
| 137 | - foreach ( $filter_vals as $field_id => $value ) { | |
| 138 | - $field = FrmFieldFactory::get_field_object( $field_id ); | |
| 139 | - $reduced[ $field_id ] = $field->get_value_to_save( $value, array( 'entry_id' => $entry_id ) ); | |
| 140 | - $reduced[ $field_id ] = $field->set_value_before_save( $reduced[ $field_id ] ); | |
| 141 | - if ( '' === $reduced[ $field_id ] || ( is_array( $reduced[ $field_id ] ) && 0 === count( $reduced[ $field_id ] ) ) ) { | |
| 142 | - unset( $reduced[ $field_id ] ); | |
| 143 | - } | |
| 144 | - } | |
| 145 | - return $reduced; | |
| 146 | - } | |
| 147 | - | |
| 148 | - /** | |
| 149 | 120 | * Determine if an entry needs to be checked as a possible duplicate |
| 150 | 121 | * |
| 151 | 122 | * @since 2.0.23 |
| 152 | 123 | * |
| @@ -250,30 +221,19 @@ | ||
| 250 | 221 | |
| 251 | 222 | return $query_results; |
| 252 | 223 | } |
| 253 | 224 | |
| 254 | - /** | |
| 255 | - * Delete an entry. | |
| 256 | - * | |
| 257 | - * @param string|int $id | |
| 258 | - * @return bool True on success, false if nothing was deleted. | |
| 259 | - */ | |
| 260 | 225 | public static function destroy( $id ) { |
| 261 | 226 | global $wpdb; |
| 262 | 227 | $id = (int) $id; |
| 263 | 228 | |
| 264 | - $entry = self::getOne( $id, true ); // Item meta is required for conditional logic in actions with 'delete' events. | |
| 229 | + $entry = self::getOne( $id ); | |
| 265 | 230 | if ( ! $entry ) { |
| 266 | 231 | $result = false; |
| 232 | + | |
| 267 | 233 | return $result; |
| 268 | 234 | } |
| 269 | 235 | |
| 270 | - /** | |
| 271 | - * Trigger an action to run custom logic before the entry is deleted. | |
| 272 | - * | |
| 273 | - * @param int $id The id of the entry that was destroyed. | |
| 274 | - * @param stdClass $entry The entry object. | |
| 275 | - */ | |
| 276 | 236 | do_action( 'frm_before_destroy_entry', $id, $entry ); |
| 277 | 237 | |
| 278 | 238 | $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_item_metas WHERE item_id=%d', $id ) ); |
| 279 | 239 | $result = $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_items WHERE id=%d', $id ) ); |
| @@ -279,19 +239,8 @@ | ||
| 279 | 239 | $result = $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_items WHERE id=%d', $id ) ); |
| 280 | 240 | |
| 281 | 241 | self::clear_cache(); |
| 282 | 242 | |
| 283 | - /** | |
| 284 | - * Trigger an action to run custom logic after the entry is deleted. | |
| 285 | - * Use this hook if you need to update caching after an entry is deleted. | |
| 286 | - * | |
| 287 | - * @since 5.4.1 | |
| 288 | - * | |
| 289 | - * @param int $id The id of the entry that was destroyed. | |
| 290 | - * @param stdClass $entry The entry object. | |
| 291 | - */ | |
| 292 | - do_action( 'frm_after_destroy_entry', $id, $entry ); | |
| 293 | - | |
| 294 | 243 | return $result; |
| 295 | 244 | } |
| 296 | 245 | |
| 297 | 246 | public static function update_form( $id, $value, $form_id ) { |
| @@ -355,9 +304,9 @@ | ||
| 355 | 304 | LEFT OUTER JOIN {$wpdb->prefix}frm_forms fr ON it.form_id=fr.id WHERE "; |
| 356 | 305 | |
| 357 | 306 | $query .= is_numeric( $id ) ? 'it.id=%d' : 'it.item_key=%s'; |
| 358 | 307 | $query_args = array( $id ); |
| 359 | - $query = $wpdb->prepare( $query, $query_args ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared | |
| 308 | + $query = $wpdb->prepare( $query, $query_args ); // WPCS: unprepared SQL ok. | |
| 360 | 309 | |
| 361 | 310 | if ( ! $meta ) { |
| 362 | 311 | $entry = FrmDb::check_cache( $id . '_nometa', 'frm_entry', $query, 'get_row' ); |
| 363 | 312 | self::prepare_entry( $entry ); |
| @@ -369,9 +318,9 @@ | ||
| 369 | 318 | self::prepare_entry( $entry ); |
| 370 | 319 | return $entry; |
| 371 | 320 | } |
| 372 | 321 | |
| 373 | - $entry = $wpdb->get_row( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared | |
| 322 | + $entry = $wpdb->get_row( $query ); // WPCS: unprepared SQL ok. | |
| 374 | 323 | $entry = self::get_meta( $entry ); |
| 375 | 324 | self::prepare_entry( $entry ); |
| 376 | 325 | |
| 377 | 326 | return $entry; |
| @@ -414,9 +363,9 @@ | ||
| 414 | 363 | array( |
| 415 | 364 | 'item_id' => $entry->id, |
| 416 | 365 | 'field_id !' => 0, |
| 417 | 366 | ), |
| 418 | - 'field_id, meta_value, field_key, item_id, f.type' | |
| 367 | + 'field_id, meta_value, field_key, item_id' | |
| 419 | 368 | ); |
| 420 | 369 | |
| 421 | 370 | $entry->metas = array(); |
| 422 | 371 | |
| @@ -421,11 +370,10 @@ | ||
| 421 | 370 | $entry->metas = array(); |
| 422 | 371 | |
| 423 | 372 | $include_key = apply_filters( 'frm_include_meta_keys', false, array( 'form_id' => $entry->form_id ) ); |
| 424 | 373 | foreach ( $metas as $meta_val ) { |
| 425 | - FrmFieldsHelper::prepare_field_value( $meta_val->meta_value, $meta_val->type ); | |
| 426 | - | |
| 427 | 374 | if ( $meta_val->item_id == $entry->id ) { |
| 375 | + FrmAppHelper::unserialize_or_decode( $meta_val->meta_value ); | |
| 428 | 376 | $entry->metas[ $meta_val->field_id ] = $meta_val->meta_value; |
| 429 | 377 | if ( $include_key ) { |
| 430 | 378 | $entry->metas[ $meta_val->field_key ] = $entry->metas[ $meta_val->field_id ]; |
| 431 | 379 | } |
| @@ -432,12 +380,13 @@ | ||
| 432 | 380 | continue; |
| 433 | 381 | } |
| 434 | 382 | |
| 435 | 383 | // include sub entries in an array |
| 436 | - if ( ! isset( $entry->metas[ $meta_val->field_id ] ) ) { | |
| 384 | + if ( ! isset( $entry_metas[ $meta_val->field_id ] ) ) { | |
| 437 | 385 | $entry->metas[ $meta_val->field_id ] = array(); |
| 438 | 386 | } |
| 439 | 387 | |
| 388 | + FrmAppHelper::unserialize_or_decode( $meta_val->meta_value ); | |
| 440 | 389 | $entry->metas[ $meta_val->field_id ][] = $meta_val->meta_value; |
| 441 | 390 | |
| 442 | 391 | unset( $meta_val ); |
| 443 | 392 | } |
| @@ -478,9 +427,9 @@ | ||
| 478 | 427 | $cache_key = FrmAppHelper::maybe_json_encode( $where ) . $order_by . $limit . $inc_form; |
| 479 | 428 | $entries = wp_cache_get( $cache_key, 'frm_entry' ); |
| 480 | 429 | |
| 481 | 430 | 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'; | |
| 431 | + $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'; | |
| 483 | 432 | $table = $wpdb->prefix . 'frm_items it '; |
| 484 | 433 | |
| 485 | 434 | if ( $inc_form ) { |
| 486 | 435 | $fields = 'it.*, fr.name as form_name,fr.form_key as form_key'; |
| @@ -487,16 +436,18 @@ | ||
| 487 | 436 | $table .= 'LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_forms fr ON it.form_id=fr.id '; |
| 488 | 437 | } |
| 489 | 438 | |
| 490 | 439 | if ( preg_match( '/ meta_([0-9]+)/', $order_by, $order_matches ) ) { |
| 491 | - $fields .= self::sort_by_field( $order_matches[1] ); | |
| 492 | - unset( $order_matches ); | |
| 440 | + // sort by a requested field | |
| 441 | + $field_id = (int) $order_matches[1]; | |
| 442 | + $fields .= ', (SELECT meta_value FROM ' . $wpdb->prefix . 'frm_item_metas WHERE field_id = ' . $field_id . ' AND item_id = it.id) as meta_' . $field_id; | |
| 443 | + unset( $order_matches, $field_id ); | |
| 493 | 444 | } |
| 494 | 445 | |
| 495 | 446 | // prepare the query |
| 496 | 447 | $query = 'SELECT ' . $fields . ' FROM ' . $table . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit; |
| 497 | 448 | |
| 498 | - $entries = $wpdb->get_results( $query, OBJECT_K ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared | |
| 449 | + $entries = $wpdb->get_results( $query, OBJECT_K ); // WPCS: unprepared SQL ok. | |
| 499 | 450 | unset( $query ); |
| 500 | 451 | |
| 501 | 452 | FrmDb::set_cache( $cache_key, $entries, 'frm_entry' ); |
| 502 | 453 | } |
| @@ -517,13 +468,9 @@ | ||
| 517 | 468 | } else { |
| 518 | 469 | $meta_where['item_id'] = array_keys( $entries ); |
| 519 | 470 | } |
| 520 | 471 | |
| 521 | - $metas = FrmDb::get_results( | |
| 522 | - $wpdb->prefix . 'frm_item_metas it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id = fi.id', | |
| 523 | - $meta_where, | |
| 524 | - 'item_id, meta_value, field_id, field_key, form_id, fi.type' | |
| 525 | - ); | |
| 472 | + $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' ); | |
| 526 | 473 | |
| 527 | 474 | unset( $meta_where ); |
| 528 | 475 | |
| 529 | 476 | if ( ! $metas ) { |
| @@ -539,9 +486,9 @@ | ||
| 539 | 486 | if ( ! isset( $entries[ $meta_val->item_id ]->metas ) ) { |
| 540 | 487 | $entries[ $meta_val->item_id ]->metas = array(); |
| 541 | 488 | } |
| 542 | 489 | |
| 543 | - FrmFieldsHelper::prepare_field_value( $meta_val->meta_value, $meta_val->type ); | |
| 490 | + FrmAppHelper::unserialize_or_decode( $meta_val->meta_value ); | |
| 544 | 491 | $entries[ $meta_val->item_id ]->metas[ $meta_val->field_id ] = $meta_val->meta_value; |
| 545 | 492 | unset( $m_key, $meta_val ); |
| 546 | 493 | } |
| 547 | 494 | |
| @@ -555,28 +502,8 @@ | ||
| 555 | 502 | self::prepare_entries( $entries ); |
| 556 | 503 | return $entries; |
| 557 | 504 | } |
| 558 | 505 | |
| 559 | - /** | |
| 560 | - * @param int $field_id | |
| 561 | - * @return string | |
| 562 | - */ | |
| 563 | - private static function sort_by_field( $field_id ) { | |
| 564 | - global $wpdb; | |
| 565 | - $field_id = (int) $field_id; | |
| 566 | - | |
| 567 | - $field_options = FrmDb::get_var( 'frm_fields', array( 'id' => $field_id ), 'field_options' ); | |
| 568 | - FrmAppHelper::unserialize_or_decode( $field_options ); | |
| 569 | - | |
| 570 | - if ( empty( $field_options['post_field'] ) ) { | |
| 571 | - $sort = ', (SELECT meta_value FROM ' . $wpdb->prefix . 'frm_item_metas WHERE field_id = ' . $field_id . ' AND item_id = it.id) as meta_' . $field_id; | |
| 572 | - } else { | |
| 573 | - $sort = ''; | |
| 574 | - } | |
| 575 | - | |
| 576 | - return apply_filters( 'frm_handle_field_column_sort', $sort, $field_id, $field_options ); | |
| 577 | - } | |
| 578 | - | |
| 579 | 506 | // Pagination Methods |
| 580 | 507 | /** |
| 581 | 508 | * @param int|array|string If int, use the form id. |
| 582 | 509 | */ |
| @@ -880,29 +807,12 @@ | ||
| 880 | 807 | * @since 2.0.16 |
| 881 | 808 | * |
| 882 | 809 | * @param array $values |
| 883 | 810 | * @param int $entry_id |
| 884 | - * @return void | |
| 885 | 811 | */ |
| 886 | 812 | private static function maybe_add_entry_metas( $values, $entry_id ) { |
| 887 | 813 | if ( isset( $values['item_meta'] ) ) { |
| 888 | 814 | FrmEntryMeta::update_entry_metas( $entry_id, $values['item_meta'] ); |
| 889 | - } | |
| 890 | - self::maybe_add_captcha_meta( (int) $values['form_id'], (int) $entry_id ); | |
| 891 | - } | |
| 892 | - | |
| 893 | - /** | |
| 894 | - * @since 5.0.15 | |
| 895 | - * | |
| 896 | - * @param int $form_id | |
| 897 | - * @param int $entry_id | |
| 898 | - * @return void | |
| 899 | - */ | |
| 900 | - private static function maybe_add_captcha_meta( $form_id, $entry_id ) { | |
| 901 | - global $frm_vars; | |
| 902 | - if ( array_key_exists( 'captcha_scores', $frm_vars ) && array_key_exists( $form_id, $frm_vars['captcha_scores'] ) ) { | |
| 903 | - $captcha_score_meta = array( 'captcha_score' => $frm_vars['captcha_scores'][ $form_id ] ); | |
| 904 | - FrmEntryMeta::add_entry_meta( $entry_id, 0, '', maybe_serialize( $captcha_score_meta ) ); | |
| 905 | 815 | } |
| 906 | 816 | } |
| 907 | 817 | |
| 908 | 818 | /** |