Limit the number of form submissions based on previous user submissions
-
Hello, I have a WordPress site and want to use a wordpress form plugin to allow my users to submit a form that sends their writing to be marked. I want to limit the number of writing pieces to a specific number for each user such as 10. The problem is that a user may send more than one piece of writing to be marked together, for e.g. a user may send 2 pieces of writing together. Is there a way I could impose this limit (10 writing pieces in total) on users with forminator? I have thought about asking each user in the form to write the number of pieces of writing they submit this time and then this number be stored later so that the next time the user submits the form, the number of pieces of writing submitted previously is compared to the maximum limit and if exceeded, does not allow the form to submit, but I don’t know how to achieve that. Does forminator allow this to be done in any way?
-
Hi @yyyyy999
Hope you are doing fine.
Currently, feature to limit the number of submissions by user is not available out of the box. But you can use some custom code to accomplish this task, let me explain the code criteria.
- It has been considered to allow just one piece of writing. This can be a Text field or you can allow single file uploads. If the user adds more than one piece of writing in the file, then add also a warning that just one of them will be processed.
- The restriction will be limited to 10 submissions by user. The code will look in the database if the user has submitted other writings before. If the limit of 10 is exceeded, an error message will be displayed:
Form is restricted to 10 submisions by user
To add the code to the site, please add a must-use plugin to your site’s wp-content/mu-plugins folder as explained here https://wpmudev.com/docs/using-wordpress/installing-wordpress-plugins/#installing-mu-plugins, then add the following code to the plugin’s php file:
<?php add_filter( 'forminator_custom_form_submit_errors', function( $submit_errors, $form_id, $field_data_array ) { // Add your form IDs here. $form_ids = array( 249 ); // Change this to the message that you want to show. $message = 'Form is restricted to 10 submissions by user.'; if ( in_array( intval( $form_id ), $form_ids, true ) ) { $last_entry = wpmudev_get_last_few_entries( $form_id ); if ( $last_entry ) { $submit_errors[]['submit'] = $message; $GLOBALS['form_error'] = true; } else { $GLOBALS['form_error'] = false; } } return $submit_errors; } ,15,3); function wpmudev_get_last_few_entries( $form_id ){ global $wpdb; $entry_table_name = Forminator_Database_Tables::get_table_name( Forminator_Database_Tables::FORM_ENTRY ); $meta_table_name = Forminator_Database_Tables::get_table_name( Forminator_Database_Tables::FORM_ENTRY_META ); $user_hidden_field = 'hidden-1'; if ( is_user_logged_in() ) { $user_id = get_current_user_id(); } else { $user_id = 0; } $sql = "SELECT count(*) FROM {$entry_table_name} e LEFT JOIN {$meta_table_name} m ON e.entry_id = m.entry_id WHERE
form_id
= %d ANDmeta_key
LIKE '{$user_hidden_field}' ANDmeta_value
= %d"; $entry_count = $wpdb->get_var( $wpdb->prepare( $sql, $form_id, $user_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared if ( $entry_count >= 10 ) { return true; } return false; } add_filter( 'forminator_custom_form_invalid_form_message', 'wpmudev_invalid_form_error_response_submit', 10, 2 ); function wpmudev_invalid_form_error_response_submit( $invalid_form_message, $form_id ){ if ( $form_id != 249 ) { return $invalid_form_message; } if ( $GLOBALS['form_error'] ) { $invalid_form_message = __( 'Form is restricted to 10 submissions by user.', 'forminator' ); } return $invalid_form_message; }Important: Change the 249 number with the form id you are using.
We recommend to test this on the dev/staging version first before putting it on the live site.
Hope this information helps to get the expected results
Kind Regards
Luis
Hello Luis, thank you for your detailed reply. I have added a mu-plugin and added the code to the plugin’s php file. Also, I changed 249 to the form id I’m using. However, I have tested it and the user can still submit more than 10 forms without any error messages appearing.
Hi @yyyyy999,
Could you please share an export of the form so that we could help you further? Please share the form export using a service like pastebin.com or Google Drive in your next response.
I hope the following guide comes in handy: https://wpmudev.com/docs/wpmu-dev-plugins/forminator/#import-export
Kind Regards,
Nebu JohnThank you for your response Nebu. This link has the export of the form. https://drive.google.com/file/d/1KkGGKnWatqerHm3KED18H1Pb9dtZJXR4/view?usp=sharing
Hi @yyyyy999,
Thanks for sharing the export. However, based on checking the form export, I have a couple more queries to make sure I understood the workflow you are looking for.
The snippet initially shared only helps with limiting the whole form submissions. I could notice the given form has a “Write here” Radio field and an option to enter 3 Writing pieces.
Are you looking to restrict based on these writing pieces? Or the whole form submission? Both are different and will require custom coding and hence double checking.
So is it a total of 10 writing pieces that could be submitted? It would be around 3 Form submissions since its a 3 writing pieces each?
Or is it based on a total of 10 form submissions, where a user can fill 3 writing pieces for each form?
Also, have you considered the “Field Group” field, it provides an out-of-the-box setting to add fields which can appear repeatedly based on user action?
The field also provides an option to set max and minimum fields that could be submitted.
Could you please check and see whether such a workflow helps?
https://wpmudev.com/docs/wpmu-dev-plugins/forminator/#field-group
Please do check and advise so that we could assist further if needed.
Best Regards,
NithinThank you, Nithin. Looking back at my initial question, I see that it was not clear enough. What I want is a way to limit submission to 10 writing pieces per user. So the limit is based on the writing pieces, not the number of form submissions. To elaborate, there is a field called “Number of writing pieces” that the user enters. The user may enter 1,2 or 3. So, for example, a user may submit 2 writing pieces for the 1st time. Then, another 2 the 2nd time. Then, another 3, and finally another 3. So the total writing pieces submitted till now is 2+2+3+3, which equals 10, so the form should reject any further submissions. The user may submit the form any number of times up to 10 (if 1 writing piece is submitted each time), but will only be restricted from submitting once 10 writing pieces are submitted. I know this might be a bit confusing. Hope this makes it clear.
As for the “Field Group” field, I think it’s a new feature; I haven’t seen it before. But I have already set the logic to limit the maximum writing pieces to 3 each time and for text boxes to appear based on the number entered.Hi @yyyyy999
Thanks for additional explanation.
I looked into it and I came up with the code that should help. The code is as follows:
<?php add_filter( 'forminator_custom_form_submit_errors', 'check_form_duplicate_submission_data', 99, 3 ); function check_form_duplicate_submission_data( $submit_errors, $form_id, $field_data_array ) { $form_ids = array( 2948, 123 ); // form IDs - one or more; if more - separate numbers with commas $number_id = 'number-1'; // ID of the number field to count $user_field = 'email-1'; // ID of the field that uniquely identifies user; e-mail seems a good fit here $err_msg = 'No more entries allowed!'; // custom error message $limit = 10; // maximum above which submission is not possible; it's a sum of values of $number_id field for given $user_field value if ( !in_array( $form_id, $form_ids ) ) { return $submit_errors; // just bail out and skip checks } $total_count = 0; foreach( $field_data_array as $key=>$value ) { $field_name = $value['name']; if ( $field_name === $number_id ) { $total_count = $value['value']; } } foreach( $field_data_array as $key => $value ) { $field_name = $value['name']; $field_value = $value['value']; if ( $field_name === $user_field ) { $count = 0; $entries = Forminator_Form_Entry_model::query_entries( array( 'form_id' => $form_id, 'search' => $field_value ), $count ); if ( $entries ) { foreach ($entries as $entry ) { $total_count = $total_count + $entry->meta_data[$number_id]['value']; } if ( $total_count > $limit ) { $submit_errors[][$number_id] = $err_msg; } } } } return $submit_errors; }
You would need to configure it in these lines
$form_ids = array( 2948, 123 ); // form IDs - one or more; if more - separate numbers with commas $number_id = 'number-1'; // ID of the number field to count $user_field = 'email-1'; // ID of the field that uniquely identifies user; e-mail seems a good fit here $err_msg = 'No more entries allowed!'; // custom error message $limit = 10; // maximum above which submission is not possible; it's a sum of values of $number_id field for given $user_field value
but I believe this is pretty self-explanatory.
To add it to the site:
– create an empty file with a .php extension (e.g. “forminator-number-based-sumbission-limit.php”)
– paste code into it
– “configure” code as described in code comments
– upload file to the “/wp-content/mu-plugins” folder of your site’s WordPress install.
It should work out of the box and the way it works is that upon submission it checks entered number and checks all other submissions already made using the same e-mail address – then it sums up values of the number entered and from all previous submissions and blocks sumbission accordingly (or not if the sum is below limit).
Best regards,
AdamThank you so much, Adam! Your solution worked perfectly, and I really appreciate your assistance!
I was just wondering if there is a way to customize the main error message that is displayed above the form which states “Error: Your form is not valid, please fix the errors!”. The custom error message described in the code ($err_msg) is just displayed briefly under the “Number of writing pieces” field.
Also, I just realized that users will not be able to submit the form again forever after the limit (unless with a different email address). I initially intended to limit user submissions, not to completely prohibit them from any further submissions above the limit forever. So, is there a way the limit can be reset monthly (preferably from the date of the first user submission by this email)?
I apologize for any inconvenience, but I would really appreciate your help with these issues. Thank you!Hi @yyyyy999
As for resetting limits:
I’m afraid that with this solution it won’t be possible. I wasn’t aware initially that it needs to be “time-valid” so I didn’t take that into account and it would require a completely different (and more complex) code.
This code doesn’t really store any data on limits but just counts submission data (or rather – calculates values in submissions) in real time so there’s nothing to reset really unless you actually remove submissions.
Probably not the most “convenient” solution but what you could consider to “automate” it would be for example:
– set Forminator to export submission to CSV (and mail to you) on schedule – so you would always have full “backup” of submitted data
– and then for the form in question in its “Settings” section set “Submissions” option under “Privacy” section to “Custom” with e.g. 30 days period.This still wouldn’t reset limit “Monthly” but would automatically “free up” at least “some” submissions for given user in 30 days “since last submission”.
For example:
– I submit 5 on Jul 10th and another 5 on Jul 20th
– on 31st day since Jul 5th I’d have 5 available again and another 5 on 31st day after Jul 20th (as my previous submissions would be automatically deleted.Another option is to actually manually increase the
$limit = 10;
value every month. The downside is that e.g. if somebody submitted only 5 in July, then in September they’d have 15 available.But other than this, I’m afraid this entire code would need to be changed significantly based on a different principle – to actually store the “sum” of the number in DB for each users and to reset it every month with cron. That’s going out of the scope of this support I’m afraid.
—-
As for showing error on top of the form:
Yes, it is doable with a bit of a change. Here are the steps:
1. replace this part of previously shared code
if ( !in_array( $form_id, $form_ids ) ) { return $submit_errors; // just bail out and skip checks }
with this
if ( !in_array( $form_id, $form_ids ) ) { return $submit_errors; // just bail out and skip checks } $GLOBALS['submit_count_error'] = '';
2. replace this part of previously shared code
$submit_errors[][$number_id] = $err_msg;
with this
$submit_errors[][$number_id] = $err_msg; $GLOBALS['submit_count_error'] = $err_msg;
3. and finally, add this entire code to the previously shared one – add it below everything else in the same file:
add_filter( 'forminator_custom_form_invalid_form_message', 'wpmudev_duplicate_invalid_form_error', 10, 2 ); function wpmudev_duplicate_invalid_form_error( $invalid_form_message, $form_id ){ if ( ! empty( $GLOBALS['submit_count_error'] ) ) { $invalid_form_message = $GLOBALS['email_error']; } return $invalid_form_message; }
It will then show the defined error right below the field and also at the top of the form instead of “Error! Your form is not valid…” one.
Note: If you only want to show the error at the top and not below the field, then another change is needed replacing this line in code
$submit_errors[][$number_id] = $err_msg;
with this
$submit_errors[]['submit'] = $err_msg;
Best regards,
AdamThank you, Adam. It didn’t work at first, but after I changed this line ($invalid_form_message = $GLOBALS[’email_error’];) to this one ($invalid_form_message = $GLOBALS[‘submit_count_error’];) it worked. As for resetting the limit, I understand that it’s out of the scope of this support, and I appreciate your willingness to help and your provided solutions, but they won’t work exactly as intended. I have some experience in coding, so I want to experiment with some solutions but I don’t know the correct syntax to interact with forminator forms. Can you tell me where I can find this? Thank you!
Hi @yyyyy999
after I changed this line ($invalid_form_message = $GLOBALS[’email_error’];) to this one ($invalid_form_message = $GLOBALS[‘submit_count_error’];) it worked
Ah, right! I’m sorry about that, that was my mistake – I overlooked it when sharing modification to the code. I’m glad you noticed that.
I have some experience in coding, so I want to experiment with some solutions but I don’t know the correct syntax to interact with forminator forms. Can you tell me where I can find this?
I’d love to but it’s not quite “that simple”. I mean, we do have API docs but that’s a different type of coding and here we are just using built-in action/filter hooks. Those aren’t currently fully documented anywhere in public so to find about them you would need to actually be checking plugin code directly.
What we can help here is that if you come across some hook in plugin code that you cannot make to work or are not sure how it works – we’ll be happy to provide additional tips/information when asked. I’m aware it’s not the ideal situation but we just don’t have docs for that (at least not yet).
Aside from that, if you are into coding – I think what you could actually try instead would be to still use my code as a “base” and try to modify (this wouldn’t really require knowledge of Forminator code) the “core” of how counting is done.
I mean:
In this part
foreach ($entries as $entry ) { $total_count = $total_count + $entry->meta_data[$number_id]['value']; }
the actual sum of submitted numbers is calculated and that it then used directly to throw an error or not. So you could try to modify it to add function to save calculated value to the DB along with user ID and date. Before saving you could check the date and based on that either update stored data or reset it first and then update.
Then after that and before this line
if ( $total_count > $limit ) {
you could read saved data from DB into the total_count variable.
I think this should do the trick without the need to dig much into Forminator itself as the base code would still be the same as shared but the modification would make it store calculated value and update it accordingly instead of simply using it “on the fly” in real time.
Best regards,
AdamThank you Adam for your detailed answer. I think I will use your code as a “base” and modify it as you said. I really appreciate your outstanding support! Can’t thank you enough!
- The topic ‘Limit the number of form submissions based on previous user submissions’ is closed to new replies.