Support » Plugin: Contact Form DB » Custom filter in PHP and CF7 Custom validation

  • Resolved jifola

    (@jifola)


    Hello,
    and thank you for creating this amazing plugin. I have never seen more extensive documentation. Awesome!

    I have been trying to make a custom validation for Contact Form 7, but without luck. I have tried a 100 different configurations but just can`t seem to make it work.

    I only have one form and one input. I wan`t to make sure that a user cannot submit the same link twice, based on current user IP address.

    I have created a custom filter using Shortcodes, Actions and Filters.
    And it works if i apply it to a table. It gets the current user IP address.

    Shortcodes, Actions and Filters custom filter code:

    
    require_once(ABSPATH . 'wp-content/plugins/contact-form-7-to-database-extension/CFDBPermittedFunctions.php');
    function my_ip_sorting() {
        if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
        //check ip from share internet
        $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
        //to check ip is pass from proxy
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else {
        $ip = $_SERVER['REMOTE_ADDR'];
        }
    	return $ip;
    }
    cfdb_register_function('my_ip_sorting');
    

    And the form that it is applied to:

    
    [cfdb-datatable form="url-submit-form" id="from_current_ip_table" show="Submitted From,url-submit-input" header="false" filter="Submitted From=my_ip_sorting()"]
    [/cfdb-datatable]
    

    I have made a test page if you want to take a look. Offcourse you have to make a submission to see your submission. Just copy paste a link from the frontpage if you want to. This only shows the submission made by the current user IP.

    The idea is to apply this filter to the Contact Form 7 custom validation. I have used this example https://cfdbplugin.com/?page_id=904 and had a look at this https://contactform7.com/2015/03/28/custom-validation/ and all relating threads.

    This is the code for the custom Contact Form 7 validation that i enden up with, before i decided to ask on this forum. Didn`t make many changes to the code from page904 in this example, but I did try a lot of variations.

    
    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&&Submitted From=my_ip_sorting";
        $atts['unbuffered'] = 'true';
        $exp->export($formName, $atts);
        $found = false;
        while ($row = $exp->nextRow()) {
            $found = true;
        }
        return $found;
    }
    
    function my_validate_url($result, $tag) {
        $formName = 'url-submit-form'; // Change to name of the form containing this field
        $fieldName = 'url-submit-input'; // 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;
    }
    add_filter('wpcf7_validate_url*', 'my_validate_url', 10, 2);
    

    Even without the custom filter i cant make it work. What am I doing wrong? I can still keep making the same submission over and over again. My form name is “url-submit-form” and my input “url-submit-input”. “Submitted From” shouldn`t be needed because of the current user IP filter.

    I made the filter because as far as i have read you can not search the database in sets. URL and corresponding IP address. So the current user IP filter does that job.

    I have gone through all of your support threads relating to this and still no luck. I hope you can help. Thank you.

    • This topic was modified 5 months ago by  jifola.
    • This topic was modified 4 months, 4 weeks ago by  Jan Dembowski.

    The page I need help with: [log in to see the link]

Viewing 3 replies - 1 through 3 (of 3 total)
  • I got something that works. Finally 🙂 But it is with a very different approach. My only problem now is getting the error message to show. Any ideas please?

    This is what i got so far. It is a bit heavy on the commenting, but i want everyone to know what is going on.

    
    // Remember to change url* to what kind of field you are validating. * means it is a required field. Remove the * if it is not.
    add_filter( 'wpcf7_validate_url*', 'my_duplicate_validation', 20, 2 );
    function my_duplicate_validation($result, $tag) {
    
    // Get the existing data
    require_once(ABSPATH . 'wp-content/plugins/contact-form-7-to-database-extension/CFDBFormIterator.php');
    $exp = new CFDBFormIterator();
    $atts = array();
    $atts['show'] = 'url-submit-input'; // Input name from your form
    $atts['filter'] = 'Submitted From=my_ip_sorting()'; // Custom filter sorting by the current users IP address
    $atts['unbuffered'] = 'true';
    $exp->export($atts['url-submit-form'], $atts); // Name of your form
    $rows = array(); // Make $rows to an array
    while ($row = $exp->nextRow()) {
      $rows[] = $row; // Instead of creating output, just save the data into the array $rows made just before
    }
    
    // Get the current contact form
    $wpcf7 = WPCF7_ContactForm::get_current();
    	
    // Get the submission, which is generated when the user hits the submit button
    $submission = WPCF7_Submission::get_instance();
    	
    // if a submission is made
    if ($submission) {
    	
    // Put the content of the submission into a variable called $posted_data
    $posted_data = $submission->get_posted_data();
    	
    // Exit the function if the contact form is empty
    if ( empty ($posted_data))
    return;
    
    // Put the content of a single input into a varible called $tag instead of the whole content from $posted_data
    // You can change the name of $tag, but make sure you change it everywhere
    // The name url-submit-input is the name of a input in my contact form
    $tag = $posted_data['url-submit-input'];
    
    // Check if the value that is submitted is already in the array of values that you pulled from your existing data
    // Url-submit-input is also the name of the field that the data is stored in. Dont confuse it with the name of the input in your form	
    // if(in_array(value to look for, array_column(array to look in, array column to look in)))
    if(in_array($tag, array_column($rows, 'url-submit-input'))) {
    	
        // If value submitted in form is found in the data saved in the array $rows. Then it is a duplicate by the current IP address
        // Invalidate and return error
        $result->invalidate($tag, "error" );
    
    } else {
    	
    	// If value submitted in form is NOT found in the data saved in the array $rows then it is not a duplicate. Allow the form to send
    	// Remember it is based on the IP address of the current user "$atts['filter'] = 'Submitted From=my_ip_sorting()';"
    	return $result;
    	
    } // if in_array end
    	
    } // If $submission end
    	
    } // Function my_duplicate_validation end
    

    And the custom filter made in Shortcodes, Actions and Filters.

    
    require_once(ABSPATH . 'wp-content/plugins/contact-form-7-to-database-extension/CFDBPermittedFunctions.php');
    function my_ip_sorting() {
        if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
        //check ip from share internet
        $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
        //to check ip is pass from proxy
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else {
        $ip = $_SERVER['REMOTE_ADDR'];
        }
    	return $ip;
    }
    cfdb_register_function('my_ip_sorting');
    

    It took me forever to get to this. I have been going at it for a week now. All i need now is to get the damn error message to display. Any help would be greatly appreciated.

    • This reply was modified 4 months, 4 weeks ago by  jifola.

    Holy sh*t it works. If you want to make two factor validation then you can use this. In this case I didn`t want the same IP address to make the same submission twice.

    First create a custom filter using the plugin Shortcodes, Actions and Filters. Only tick of “Activated” NOT shortcode. The following code registers the IP address of the current user.

    
    require_once(ABSPATH . 'wp-content/plugins/contact-form-7-to-database-extension/CFDBPermittedFunctions.php');
    function my_ip_sorting() {
        if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
        //check ip from share internet
        $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
        //to check ip is pass from proxy
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else {
        $ip = $_SERVER['REMOTE_ADDR'];
        }
    	return $ip;
    }
    cfdb_register_function('my_ip_sorting');
    

    Then place the following code in your functions.php.

    
    // Get existing data
    function my_duplicate_validation($found) {
    	
        require_once(ABSPATH . 'wp-content/plugins/contact-form-7-to-database-extension/CFDBFormIterator.php');
        $exp = new CFDBFormIterator();
        $atts = array();
        $atts['show'] = 'url-submit-input'; // The field name
        $atts['filter'] = 'Submitted From=my_ip_sorting()'; // The custom filter
        $exp->export($atts['url-submit-form'], $atts); // The form name
    	$found = true; // Found is set to true, and will only be returned if a duplicate is found
        $rows = array(); // Put the data you extract into an array called $rows
        while ($row = $exp->nextRow()) {
            $rows[] = $row;
        }
    
    	// Get the form that is currently being used
        $wpcf7 = WPCF7_ContactForm::get_current();
    	
    	// Get the current submission which is generated when the user hits the submit button
        $submission = WPCF7_Submission::get_instance();
    
    	// If submission is being made
        if ($submission) {
    	    
    		// Put the values that is being submitted into an array called $posted_data
            $posted_data = $submission->get_posted_data();
    
    		// Exit the function if the form is empty
            if ( empty ($posted_data))
            return;
    
    		// Put the value of the input named url-submit-input into an array called $duplicate
            $duplicate = $posted_data['url-submit-input'];
    
    		// if(in_array(the value to look for, array_column(the array to look in, the column to look in)))
            if(in_array($duplicate, array_column($rows, 'url-submit-input'))) {
    	
    			// If a duplicate is found return $found which is set to true
    			return $found;
    			
            }
    		
        }
    		
    }
    
    // Contact form 7 custom validation
    function my_validate_url($result, $tag) {
    
    	// The error message is related to the field in your form by the name of url-submit-input
    	if ( 'url-submit-input' == $tag->name ) {
    	
    		// Asking the previous function my_duplicate_validation if $found was returned
            if (my_duplicate_validation($found)) {
    			
    			// If $found was returned then the submission is invalidated
    			// If you are using ajax then only .wpcf7-not-valid-tip will show this error message
                $result->invalidate($tag, "Error your submission is a duplicate");
    		
            }
    		
    	}
    	
    	// Return the result
        return $result;
    }
    add_filter('wpcf7_validate_url*', 'my_validate_url', 20, 2);
    

    I tried for a whole damn week to make this thing work 🙂 If you have any questions just ask.

    I have a similar issue, I’m using CFDB plugin and cannot store a unique email field in DB, I’ve tried to add “add shortcode & filters” tool to right this bellow script. but this script is not working for me.
    Please help.

    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;
    }

    /**
    * @param $result WPCF7_Validation
    * @param $tag array
    * @return WPCF7_Validation
    */
    function my_validate_email($result, $tag) {
    $formName = ‘contact-form-1’; // Change to name of the form containing this field
    $fieldName = ‘your-email’; // 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;

    }

    add_filter(‘wpcf7_validate_email*’, ‘my_validate_email’, 10, 2);

Viewing 3 replies - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.