wordpresscontact-form-7

How can I write a hook that restricts one IP address for submitting applications from Contact Form 7?


I have a form for subscription. And I want to limit the number of submits by IP, for example, 3 times a day? How can I do it with hooks?


Solution

  • Use the WordPress do_shortcode_tag filter introduced in v4.7, which get fired when a shortcode is rendered. You can then replace the rendered CF7 form with a notification for users who have reached their submitted limit

    add_filter('do_shortcode_tag', 'restrict_my_form',10,3);
    function restrict_my_form($output, $tag, $attrs){
      //check if this is your form being rendered.
      if($tag=='contact-form-7' and $attrs['id'] == 1){
        //get the IP address of the submission as $ip_address
        $cannot_submit = get_transient('form_submission_from_'.$ip_address);
        if($cannot_submit !== false){
          $cannot_submit = explode('|',$cannot_submit);
          if($cannot_submit[0] > 2){ //already submitted 3 times.
            $cannot_submit = true;
          }else{ //can still submit.
            $cannot_submit = false;
          }
        }//else this is the first submit or transient expired.
    
        if($cannot_submit){ 
          //replace the html for with your notification.
          $output ='<p>You have reached the limit of submissions</p>';
        }
      }
      return $output;
    }
    

    To verify the IP of the user, the question has already been answered here.

    You will also need to track users' submissions per IP, I suggest you store these as transients for 24 hours, this way they will automatically disappear after a day. Something along these lines (I haven't tested this code, so let me know if you're not getting the expected results.)

    add_action('wpcf7_mail_sent', function($form){
      //get the IP address of the submission as $ip_address
      $time = current_time('timestamp');
      $expiry = DAY_IN_SECONDS; //24 hours.
      $value = 1;
      $last_value = get_transient('form_submission_from_'.$ip_address);
      if($last_value !== false){
        $last_value = explode('|',$last_value);
        $expiry = DAY_IN_SECONDS - ($time - $last_value[1]); //remaining time since first submission.
        $time = $last_value[1]; //keep time of first submission.
        $value = ($last_value[0]+1);
        delete_transient('form_submission_from_'.$ip_address);
      }
      $value = "$value|$time";
      set_transient('form_submission_from_'.$ip_address, $value, $expiry);
    });