PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.0.10
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.0.10
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/FrmEntryValidate.php +56 -271 6.3.25.0.10 View file →
@@ -3,14 +3,8 @@
3 3 die( 'You are not allowed to call this page directly.' );
4 4 }
5 5
6 6 class FrmEntryValidate {
7 -
8 - /**
9 - * @param array $values
10 - * @param string[]|bool $exclude
11 - * @return array
12 - */
13 7 public static function validate( $values, $exclude = false ) {
14 8 FrmEntry::sanitize_entry_post( $values );
15 9 $errors = array();
16 10
@@ -20,10 +14,9 @@
20 14 return $errors;
21 15 }
22 16
23 17 if ( FrmAppHelper::is_admin() && is_user_logged_in() && ( ! isset( $values[ 'frm_submit_entry_' . $values['form_id'] ] ) || ! wp_verify_nonce( $values[ 'frm_submit_entry_' . $values['form_id'] ], 'frm_submit_entry_nonce' ) ) ) {
24 - $frm_settings = FrmAppHelper::get_settings();
25 - $errors['form'] = $frm_settings->admin_permission;
18 + $errors['form'] = __( 'You do not have permission to do that', 'formidable' );
26 19 }
27 20
28 21 self::set_item_key( $values );
29 22
@@ -49,16 +42,10 @@
49 42 * @param array $errors Errors data.
50 43 * @param array $values Value data of the form.
51 44 * @param array $args Custom arguments. Contains `exclude` and `posted_fields`.
52 45 */
53 - $filtered_errors = apply_filters( 'frm_validate_entry', $errors, $values, compact( 'exclude', 'posted_fields' ) );
46 + $errors = apply_filters( 'frm_validate_entry', $errors, $values, compact( 'exclude', 'posted_fields' ) );
54 47
55 - if ( is_array( $filtered_errors ) ) {
56 - $errors = $filtered_errors;
57 - } else {
58 - _doing_it_wrong( __FUNCTION__, 'Only arrays should be returned when using the frm_validate_entry filter.', '6.3' );
59 - }
60 -
61 48 return $errors;
62 49 }
63 50
64 51 private static function set_item_key( &$values ) {
@@ -124,10 +111,10 @@
124 111 }
125 112
126 113 if ( $posted_field->required == '1' && FrmAppHelper::is_empty_value( $value ) ) {
127 114 $errors[ 'field' . $args['id'] ] = FrmFieldsHelper::get_error_msg( $posted_field, 'blank' );
128 - } elseif ( ! isset( $_POST['item_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
129 - self::maybe_add_item_name( $value, $posted_field );
115 + } elseif ( $posted_field->type == 'text' && ! isset( $_POST['item_name'] ) ) { // WPCS: CSRF ok.
116 + $_POST['item_name'] = $value;
130 117 }
131 118
132 119 FrmEntriesHelper::set_posted_value( $posted_field, $value, $args );
133 120
@@ -145,30 +132,8 @@
145 132 $errors = apply_filters( 'frm_validate_field_entry', $errors, $posted_field, $value, $args );
146 133 }
147 134
148 135 /**
149 - * Maybe add item_name to $_POST to save it in items table.
150 - *
151 - * @since 5.2.02
152 - *
153 - * @param object $field Field object.
154 - */
155 - private static function maybe_add_item_name( $value, $field ) {
156 - $item_name = false;
157 - if ( 'name' === $field->type ) {
158 - $field_obj = FrmFieldFactory::get_field_object( $field );
159 - $item_name = $field_obj->get_display_value( $value );
160 - } elseif ( 'text' === $field->type ) {
161 - $item_name = $value;
162 - }
163 -
164 - if ( false !== $item_name ) {
165 - // Item name has a max length of 255 characters so truncate it so it doesn't fail to save in the database.
166 - $_POST['item_name'] = substr( $item_name, 0, 255 );
167 - }
168 - }
169 -
170 - /**
171 136 * Set $value to an empty string if it matches its label
172 137 *
173 138 * @param object $field
174 139 * @param string $value
@@ -289,37 +254,16 @@
289 254 } elseif ( self::is_honeypot_spam( $values ) || self::is_spam_bot() ) {
290 255 $errors['spam'] = __( 'Your entry appears to be spam!', 'formidable' );
291 256 } elseif ( self::blacklist_check( $values ) ) {
292 257 $errors['spam'] = __( 'Your entry appears to be blocked spam!', 'formidable' );
293 - }
294 -
295 - if ( isset( $errors['spam'] ) || self::form_is_in_progress( $values ) ) {
296 - return;
297 - }
298 -
299 - if ( self::is_akismet_enabled_for_user( $values['form_id'] ) && self::is_akismet_spam( $values ) ) {
258 + } elseif ( self::is_akismet_enabled_for_user( $values['form_id'] ) && self::is_akismet_spam( $values ) ) {
300 259 $errors['spam'] = __( 'Your entry appears to be spam!', 'formidable' );
301 260 }
302 261 }
303 262
304 263 /**
305 - * Checks if form is in progress.
306 - *
307 - * @since 5.0.13
308 - *
309 - * @param array $values The values.
310 - * @return bool
311 - */
312 - private static function form_is_in_progress( $values ) {
313 - return FrmAppHelper::pro_is_installed() &&
314 - ( isset( $values[ 'frm_page_order_' . $values['form_id'] ] ) || FrmAppHelper::get_post_param( 'frm_next_page' ) ) &&
315 - FrmField::get_all_types_in_form( $values['form_id'], 'break' );
316 - }
317 -
318 - /**
319 264 * @param int $form_id
320 - *
321 - * @return bool|string
265 + * @return boolean
322 266 */
323 267 private static function is_antispam_check( $form_id ) {
324 268 $aspm = new FrmAntiSpam( $form_id );
325 269 return $aspm->validate();
@@ -373,10 +317,12 @@
373 317 return false;
374 318 }
375 319
376 320 $content = FrmEntriesHelper::entry_array_to_string( $values );
321 + if ( empty( $content ) ) {
322 + return false;
323 + }
377 324
378 - self::prepare_values_for_spam_check( $values );
379 325 $ip = FrmAppHelper::get_ip_address();
380 326 $user_agent = FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' );
381 327 $user_info = self::get_spam_check_user_info( $values );
382 328
@@ -444,13 +390,10 @@
444 390 * @since 2.0
445 391 */
446 392 private static function parse_akismet_array( &$datas, $values ) {
447 393 self::add_site_info_to_akismet( $datas );
394 + self::add_user_info_to_akismet( $datas, $values );
448 395 self::add_server_values_to_akismet( $datas );
449 -
450 - self::prepare_values_for_spam_check( $values );
451 -
452 - self::add_user_info_to_akismet( $datas, $values );
453 396 self::add_comment_content_to_akismet( $datas, $values );
454 397 }
455 398
456 399 private static function add_site_info_to_akismet( &$datas ) {
@@ -474,127 +417,48 @@
474 417 $datas['user_role'] = Akismet::get_user_roles( $user_info['user_ID'] );
475 418 }
476 419 }
477 420
478 - /**
479 - * Gets user info for Akismet spam check.
480 - *
481 - * @since 5.0.13 Separate code for guest. Handle value of embedded|repeater.
482 - *
483 - * @param array $values Entry values after running through {@see FrmEntryValidate::prepare_values_for_spam_check()}.
484 - * @return array
485 - */
486 421 private static function get_spam_check_user_info( $values ) {
487 - if ( ! is_user_logged_in() ) {
488 - return self::get_spam_check_user_info_for_guest( $values );
489 - }
422 + $datas = array();
490 423
491 - $user = wp_get_current_user();
424 + if ( is_user_logged_in() ) {
425 + $user = wp_get_current_user();
492 426
493 - return array(
494 - 'user_ID' => $user->ID,
495 - 'user_id' => $user->ID,
496 - 'comment_author' => $user->display_name,
497 - 'comment_author_email' => $user->user_email,
498 - 'comment_author_url' => $user->user_url,
499 - );
500 - }
427 + $datas['user_ID'] = $user->ID;
428 + $datas['user_id'] = $user->ID;
429 + $datas['comment_author'] = $user->display_name;
430 + $datas['comment_author_email'] = $user->user_email;
431 + $datas['comment_author_url'] = $user->user_url;
432 + } else {
433 + $datas['comment_author'] = '';
434 + $datas['comment_author_email'] = '';
435 + $datas['comment_author_url'] = '';
501 436
502 - /**
503 - * Gets user info for Akismet spam check for guest.
504 - *
505 - * @since 5.0.13
506 - *
507 - * @param array $values Entry values after flattened.
508 - * @return array
509 - */
510 - private static function get_spam_check_user_info_for_guest( $values ) {
511 - $datas = array(
512 - 'comment_author' => '',
513 - 'comment_author_email' => '',
514 - 'comment_author_url' => '',
515 - 'name_field_ids' => $values['name_field_ids'],
516 - 'missing_keys' => array( 'comment_author_email', 'comment_author_url', 'comment_author' ),
517 - 'frm_duplicated' => array(),
518 - );
519 -
520 - if ( isset( $values['item_meta'] ) ) {
521 - $values = $values['item_meta'];
522 - }
523 -
524 - $values = array_filter( $values );
525 -
526 - self::recursive_add_akismet_guest_info( $datas, $values );
527 - unset( $datas['name_field_ids'] );
528 - unset( $datas['missing_keys'] );
529 -
530 - return $datas;
531 - }
532 -
533 - /**
534 - * Recursive adds akismet guest info.
535 - *
536 - * @since 5.0.13
537 - *
538 - * @param array $datas Guest data.
539 - * @param array $values The values.
540 - * @param int|null $custom_index Custom index (or field ID).
541 - */
542 - private static function recursive_add_akismet_guest_info( &$datas, $values, $custom_index = null ) {
543 - foreach ( $values as $index => $value ) {
544 - if ( ! $datas['missing_keys'] ) {
545 - return; // Found all info.
437 + if ( isset( $values['item_meta'] ) ) {
438 + $values = $values['item_meta'];
546 439 }
547 440
548 - if ( is_array( $value ) ) {
549 - self::recursive_add_akismet_guest_info( $datas, $value, $index );
550 - continue;
551 - }
441 + $values = array_filter( $values );
552 442
553 - $field_id = ! is_null( $custom_index ) ? $custom_index : $index;
554 - foreach ( $datas['missing_keys'] as $key_index => $key ) {
555 - $found = self::is_akismet_guest_info_value( $key, $value, $field_id, $datas['name_field_ids'] );
556 - if ( $found ) {
557 - $datas[ $key ] = $value;
558 - $datas['frm_duplicated'][] = $field_id;
559 - unset( $datas['missing_keys'][ $key_index ] );
443 + $datas['frm_duplicated'] = array();
444 + foreach ( $values as $index => $value ) {
445 + if ( ! is_array( $value ) ) {
446 + if ( $datas['comment_author_email'] == '' && strpos( $value, '@' ) && is_email( $value ) ) {
447 + $datas['comment_author_email'] = $value;
448 + $datas['frm_duplicated'][] = $index;
449 + } elseif ( $datas['comment_author_url'] == '' && strpos( $value, 'http' ) === 0 ) {
450 + $datas['comment_author_url'] = $value;
451 + $datas['frm_duplicated'][] = $index;
452 + } elseif ( $datas['comment_author'] == '' && ! is_numeric( $value ) && strlen( $value ) < 200 ) {
453 + $datas['comment_author'] = $value;
454 + $datas['frm_duplicated'][] = $index;
455 + }
560 456 }
561 457 }
562 458 }
563 - }
564 459
565 - /**
566 - * Checks if given value is an akismet guest info.
567 - *
568 - * @since 5.0.13
569 - *
570 - * @param string $key Guest info key.
571 - * @param string $value Value to check.
572 - * @param int $field_id Field ID.
573 - * @param array $name_field_ids Name field IDs.
574 - * @return bool
575 - */
576 - private static function is_akismet_guest_info_value( $key, $value, $field_id, $name_field_ids ) {
577 - if ( ! $value || is_numeric( $value ) ) {
578 - return false;
579 - }
580 -
581 - switch ( $key ) {
582 - case 'comment_author_email':
583 - return strpos( $value, '@' ) && is_email( $value );
584 -
585 - case 'comment_author_url':
586 - return 0 === strpos( $value, 'http' );
587 -
588 - case 'comment_author':
589 - if ( $name_field_ids ) {
590 - // If there is name field in the form, we should always use it as author name.
591 - return in_array( $field_id, $name_field_ids, true );
592 - }
593 - return strlen( $value ) < 200;
594 - }
595 -
596 - return false;
460 + return $datas;
597 461 }
598 462
599 463 private static function add_server_values_to_akismet( &$datas ) {
600 464 foreach ( $_SERVER as $key => $value ) {
@@ -640,133 +504,62 @@
640 504 *
641 505 * @param array $values Entry values.
642 506 */
643 507 private static function skip_adding_values_to_akismet( &$values ) {
644 - $skipped_fields = self::get_akismet_skipped_field_ids( $values );
645 - foreach ( $skipped_fields as $skipped_field ) {
646 - if ( ! isset( $values['item_meta'][ $skipped_field->id ] ) ) {
647 - continue;
508 + $skipped_field_ids = self::get_akismet_skipped_field_ids( $values );
509 + foreach ( $skipped_field_ids as $field_id ) {
510 + if ( isset( $values['item_meta'][ $field_id ] ) ) {
511 + unset( $values['item_meta'][ $field_id ] );
648 512 }
649 -
650 - if ( self::should_really_skip_field( $skipped_field, $values ) ) {
651 - unset( $values['item_meta'][ $skipped_field->id ] );
652 - if ( isset( $values['item_meta']['other'][ $skipped_field->id ] ) ) {
653 - unset( $values['item_meta']['other'][ $skipped_field->id ] );
654 - }
655 - }
656 513 }
657 514 }
658 515
659 516 /**
660 - * Checks if a skip field should be really skipped.
661 - *
662 - * @since 5.02.04
663 - *
664 - * @param object $field_data Object contains `id` and `options`.
665 - * @param array $values Entry values.
666 - * @return bool
667 - */
668 - private static function should_really_skip_field( $field_data, $values ) {
669 - if ( empty( $field_data->options ) ) { // This is skipped field types.
670 - return true;
671 - }
672 -
673 - FrmAppHelper::unserialize_or_decode( $field_data->options );
674 - if ( ! $field_data->options ) { // Check if an error happens when unserializing, or empty options.
675 - return true;
676 - }
677 -
678 - end( $field_data->options );
679 - $last_key = key( $field_data->options );
680 -
681 - // If a choice field has no Other option.
682 - if ( is_numeric( $last_key ) || 0 !== strpos( $last_key, 'other_' ) ) {
683 - return true;
684 - }
685 -
686 - // If a choice field has Other option, but Other is not selected.
687 - if ( empty( $values['item_meta']['other'][ $field_data->id ] ) ) {
688 - return true;
689 - }
690 -
691 - // Check if submitted value is same as one of field option.
692 - foreach ( $field_data->options as $option ) {
693 - $option_value = ! is_array( $option ) ? $option : ( isset( $option['value'] ) ? $option['value'] : '' );
694 - if ( $values['item_meta']['other'][ $field_data->id ] === $option_value ) {
695 - return true;
696 - }
697 - }
698 -
699 - return false;
700 - }
701 -
702 - /**
703 517 * Gets field IDs that are skipped from sending to Akismet spam check.
704 518 *
705 519 * @since 5.0.09
706 - * @since 5.0.13 Move out get_all_form_ids_and_flatten_meta() call and get `form_ids` from `$values`.
707 - * @since 5.2.04 This method returns array of object contains `id` and `options` instead of array of `id` only.
708 520 *
709 - * @param array $values Entry values after running through {@see FrmEntryValidate::prepare_values_for_spam_check()}.
521 + * @param array $values Entry values.
710 522 * @return array
711 523 */
712 524 private static function get_akismet_skipped_field_ids( $values ) {
713 - if ( empty( $values['form_ids'] ) ) {
714 - return array();
715 - }
716 -
525 + $form_ids = self::get_all_form_ids_and_flatten_meta( $values );
717 526 $skipped_types = array( 'divider', 'form', 'hidden', 'user_id', 'file', 'date', 'time', 'scale', 'star', 'range', 'toggle', 'data', 'lookup', 'likert', 'nps' );
718 527 $has_other_types = array( 'radio', 'checkbox', 'select' );
719 528
720 529 $where = array(
721 530 array(
722 - 'form_id' => $values['form_ids'],
723 - 'type' => array_merge( $skipped_types, $has_other_types ),
531 + 'form_id' => $form_ids,
532 + array(
533 + array(
534 + 'field_options not like' => ';s:5:"other";s:1:"1"',
535 + 'type' => $has_other_types,
536 + ),
537 + 'or' => 1,
538 + 'type' => $skipped_types,
539 + ),
724 540 ),
725 541 );
726 542
727 - return FrmDb::get_results( 'frm_fields', $where, 'id,options' );
543 + return FrmDb::get_col( 'frm_fields', $where );
728 544 }
729 545
730 546 /**
731 - * Prepares values array for spam check.
732 - *
733 - * @since 5.0.13
734 - *
735 - * @param array $values Entry values.
736 - */
737 - private static function prepare_values_for_spam_check( &$values ) {
738 - $form_ids = self::get_all_form_ids_and_flatten_meta( $values );
739 - $values['form_ids'] = $form_ids;
740 - }
741 -
742 - /**
743 547 * Gets all form IDs (include child form IDs) and flatten item_meta array. Used for skipping values sent to Akismet.
744 548 * This also removes some unused data from the item_meta.
745 549 *
746 550 * @since 5.0.09
747 - * @since 5.0.13 Convert name field value to string.
748 551 *
749 552 * @param array $values Entry values.
750 553 * @return array Form IDs.
751 554 */
752 555 private static function get_all_form_ids_and_flatten_meta( &$values ) {
753 - $values['name_field_ids'] = array();
754 -
755 - // Blacklist check for File field in the old version doesn't contain `form_id`.
756 - $form_ids = isset( $values['form_id'] ) ? array( absint( $values['form_id'] ) ) : array();
556 + $form_ids = array( absint( $values['form_id'] ) );
757 557 foreach ( $values['item_meta'] as $field_id => $value ) {
758 558 if ( ! is_numeric( $field_id ) ) { // Maybe `other`.
759 559 continue;
760 560 }
761 561
762 - // Convert name array to string.
763 - if ( isset( $value['first'] ) && isset( $value['last'] ) ) {
764 - $values['item_meta'][ $field_id ] = trim( implode( ' ', $value ) );
765 - $values['name_field_ids'][] = $field_id;
766 - continue;
767 - }
768 -
769 562 if ( ! is_array( $value ) || empty( $value['form'] ) ) {
770 563 continue;
771 564 }
772 565
@@ -784,16 +577,8 @@
784 577
785 578 if ( ! isset( $values['item_meta'][ $subsubindex ] ) ) {
786 579 $values['item_meta'][ $subsubindex ] = array();
787 580 }
788 -
789 - // Convert name array to string.
790 - if ( isset( $subsubvalue['first'] ) && isset( $subsubvalue['last'] ) ) {
791 - $subsubvalue = trim( implode( ' ', $subsubvalue ) );
792 -
793 - $values['name_field_ids'][] = $subsubindex;
794 - }
795 -
796 581 $values['item_meta'][ $subsubindex ][] = $subsubvalue;
797 582 }
798 583 }
799 584