Search code examples
databasewordpressvalidationduplicatescontact-form-7

Contact Form 7 allow duplicate after 24 hours


I am using Contact Form 7 for to capture leads on our site. I am also using the CFDB plugin to add a validation rule to prevent all duplicates on the site using.

function is_already_submitted($formName, $fieldName, $fieldValue) {
    require_once(ABSPATH . 'wp-content/plugins/contact-form-7-to-database-extension/CFDBFormIterator.php');
    $exp = new CFDBFormIterator();
    $atts = array();
    $atts['show'] = $fieldName;
    $atts['filter'] = "$fieldName=$fieldValue";
    $atts['unbuffered'] = 'true';
    $exp->export($formName, $atts);
    $found = false;
    while ($row = $exp->nextRow()) {
        $found = true;
    }
    return $found;
}
function my_validate_email($result, $tag) {
    $formName = 'email_form'; // Change to name of the form containing this field
    $fieldName = 'email_123'; // Change to your form's unique field name
    $errorMessage = 'Email has already been submitted'; // Change to your error message
    $name = $tag['name'];
    if ($name == $fieldName) {
        if (is_already_submitted($formName, $fieldName, $_POST[$name])) {
            $result->invalidate($tag, $errorMessage);
        }
    }
    return $result;
}

We are now required to allow a duplicate entry if a user retries after a 24 hour period.

Our Proposal is to run a cron job to flag entries that are older than 24 hours and then allow a user to proceed. We have included a new table column (allow_duplicate) to flag the entry.

Any advice on how to structure the validation on functions.php would be appreciated.


Solution

  • So me personally... I would use the Transient API. With Transients, you can set the expiration to 24 hours, and remove the need for a cron task. First... Set the transient using the hook wpcf7_before_send_mail then check for the existence of the transient with your validate filter. The transient will expire 24 hours after initial submission.

    Set your contact form ID in the function dd_handle_form_submission

    // capture data after contact form submit
    add_action( 'wpcf7_before_send_mail', 'dd_handle_form_submission' ); 
    function dd_handle_form_submission( $contact_form ) {
        // Check Form ID
        if( 2744 !== $contact_form->id() ) return; // Use your form ID here
        $submission = WPCF7_Submission::get_instance();
        if ( $submission ) {
            $posted_data = $submission->get_posted_data();
            // Set the Transient
            $transient_name = 'cf7_has_submitted_' . $posted_data['email_123'];
            set_transient($transient_name, true, 1 * DAY_IN_SECONDS);
        }
        return;
    }
    
    // Custom Validation Filter
    add_filter( 'wpcf7_validate_email*', 'my_validate_email', 20, 2);
    function my_validate_email($result, $tag) {
        $fieldName = 'email_123'; // Change to your form's unique field name
        $errorMessage = 'Email has already been submitted'; // Change to your error message
        $name = $tag['name'];
        if ($name == $fieldName) {
            // Create the Transient Name to lookup with the email field
            $transient = 'cf7_has_submitted_' . $_POST[$name];
            // Lookup transient
            if (false !== get_transient($transient)) $result->invalidate($tag, $errorMessage);
        }
        return $result;
    }