This hook can be used to create your own custom field validations and errors. The Pro validation is also run using this hook. It runs with a priority of 10. The Pro validation will remove any error messages for fields that are conditionally hidden, so you may want to run your function with a priority below 10.
Usage
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 4);
Parameters
- $errors (array)
- $posted_field (object)
- $posted_value (string or array)
- $args (array)
- 'id' (int)
- 'parent_field_id' (int)
- 'key_pointer' (int)
- 'exclude' (array)
Examples
Calculate final date
If you need to get a second date based on an entered date and number of days, use the code below.
add_filter('frm_validate_field_entry', 'set_my_expiration_date', 10, 3); function set_my_expiration_date($errors, $posted_field, $posted_value){ if ( $posted_field->id == 25 ) { //change 25 to the ID of the date field to change // Get the first date in a UNIX timestamp $first_date = date_create_from_format( 'd/m/Y', $_POST['item_meta'][20] ); //Change 20 to the ID of the first date field $first_date = date_format( $first_date, 'Y-m-d' ); $first_date = strtotime( $first_date ); // Get the final date in Y-m-d format $final_date = strtotime('+7 day', $first_date); $final_date = date('Y-m-d', $final_date); // Save the final date as the posted value $_POST['item_meta'][$posted_field->id] = $final_date; } return $errors; }
Make sure to change d/m/Y to the date format selected in your Formidable Global Settings.
Limit uploaded file size
Use this code to limit the maximum file size that can be uploaded from a file upload field. This will apply to all file upload fields.
add_filter( 'frm_validate_field_entry', 'validate_custom_file_size', 20, 3 ); function validate_custom_file_size( $errors, $field, $value ) { if ( $field->type == 'file' && ( isset( $_FILES['file'.$field->id] ) ) && ! empty( $_FILES['file'.$field->id]['name'] ) ) { $files = (array) $_FILES['file'. $field->id]['size']; foreach ( $files as $v ) { if ( $v > 100000 ) {//change this number to the max size you would like. 100000 bytes = 100 KB $errors['field'.$field->id] = 'That file is too big. It must be less than 100KB.'; } } } return $errors; }
Set custom value in repeating field
Use the code below to set a custom value in a repeating field. Replace 508 with the ID of the repeating section field. Replace 11700 with the ID of the field that you want to modify.
add_filter('frm_validate_field_entry', 'set_custom_repeating_val', 10, 4); function set_custom_repeating_val($errors, $posted_field, $posted_value, $args){ if ( $posted_field->id == 508 ) { $field_to_change = 11700; if ( ! isset( $_POST['item_meta'][ $posted_field->id ] ) ) { return $errors; } foreach ( $_POST['item_meta'][ $posted_field->id ] as $row_num => $section_vals ) { if ( $row_num === 'form' ) { continue; } $_POST['item_meta'][ $posted_field->id ][ $row_num ][ $field_to_change ] = 'new val'; } } return $errors; }
Validate sum of multiple fields
A useful example of how to check to see if multiple fields (in this particular instance, three dropdowns with values 0-100) combine to equal a given value (in this case 100).
add_filter('frm_validate_field_entry', 'validateStats', 10, 3); function validateStats($errors, $posted_field, $posted_value){ if($posted_field->id == 2031){ //change 25 to the ID of the field to validate $totalValue = $_POST['item_meta'][4138] + $_POST['item_meta'][2031] + $_POST['item_meta'][4141]; if ( $totalValue !== 100 ) { //if it doesn't match up, add an error: $errors['field'. $posted_field->id] = 'The % fields must total exactly 100%.'; } } return $errors; }
Force field value back to previous
It's possible for a malicious user to change the values of hidden fields. Depending on the situation, this may or may not be acceptable. The code will make sure that only an admin user can change the value of this field. Replace 25 with the ID of the field that you want to limit and replace 'No' with the default value that you would like to force when a new entry is created.
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 3); function my_custom_validation($errors, $posted_field, $posted_value){ $featured_field = 25; //change 25 to the ID of the featured field if ( ! current_user_can('administrator') && $posted_field->id == $featured_field ) { if ( isset( $_POST['id'] ) && $_POST['id'] ) { $force_val = FrmProEntriesController::get_field_value_shortcode(array('field_id' => $posted_field->id, 'entry_id' => $_POST['id'])); } else { $force_val = 'No'; } if ( $_POST['item_meta'][$posted_field->id] != $force_val ) { $_POST['item_meta'][$posted_field->id] = $force_val; } } return $errors; }
Verify dropdown/radio options
There are times you may need to be absolutely sure a value saved in your dropdown/radio field is one of the provided options.
add_filter('frm_validate_field_entry', 'frm_check_radio_option', 10, 3); function frm_check_radio_option( $errors, $posted_field, $posted_value ) { $field_ids = array( 25, 26 ); // set your field ids here if ( in_array( $posted_field->id, $field_ids ) && ! empty( $_POST['item_meta'][ $posted_field->id ] ) ) { $options = $posted_field->options; $in_options = false; foreach ( $options as $opt_key => $opt ) { $saved_value = FrmFieldsController::check_value( $opt, $opt_key, $posted_field ); if ( $_POST['item_meta'][ $posted_field->id ] == $saved_value ) { $in_options = true; break; } } if ( ! $in_options ) { $errors[ $posted_field->id ] = 'That is not an option'; } } return $errors; }
Remove special characters
It checks to ensure that no special characters are in the values inputted by the form user.
It was developed to detect and prevent special characters being added to the database.
It was needed to support the Comprehensive Google Map plugin, as that plugin does not like having non-alpha-numeric characters in any field it is displaying. The plugin is here: http://wordpress.org/plugins/comprehensive-google-map-plugin/
If you have dev / test / staging / production instances of WP, be sure to use the production form IDs in your production functions.php.
/* This PHP function validates form fields in Formidable Pro forms to ensure the user inputed values contain no special characters that will blow up the database or other plugins, e.g. Comprehensive Google Maps, which cannot have any special characters in any data field it displays */ add_filter('frm_validate_field_entry', 'my_form_custom_validation', 10, 3); function my_form_custom_validation($errors, $posted_field, $posted_value){ // // Change the following IDs to match the form field IDs in your production WP instance. The IDs show here are samples. // // Custom Display #1 form field IDs // 153 = Event city // 148 = Event Name // 149 = Event cost // 156 = Event duration // 157 = Event Location name // 152 = Event Location street address // 154 = Event Location zip / postal code // 158 = Event Location phone number // 169 = Map Event Location Address (used for geocode plugin) // // Custom Display #2 form field IDs // 198 = Store name // 202 = Store address // 203 = Store city // 204 = Store postal code // 208 = Store phone number // 219 = Map Store address (used for geocode plugin) // // if(in_array($posted_field->id, array('153','148','149','156','157','152','154','158','169','198','202','203','204','208','219'))){ // // //check the $posted_value here //if the input contains an illegal character, add an error: // if(preg_match_all('/[`~@#%*^()+={}|]/', $posted_value, $pccevents_event_form_matches)) { // // You can combine all of these into one test. I did seperate tests to aid debugging. // // You can also add additional PHP to show the user exactly which special character is causing the error. // $errors['field'. $posted_field->id] = "Please use only alpha or numeric characters. Do not include special characters such as `~ @ # % ^ * ( ) + = { } or |"; } elseif (preg_match_all('/[[]]/', $posted_value, $pccevents_event_form_matches)) { $errors['field'. $posted_field->id] = "Please use only alpha or numeric characters. Do not include special characters such as [ ]"; } elseif (preg_match_all('/[>id] = "Please use only alpha or numeric characters. Do not include special characters such as > id] = "Please use only alpha or numeric characters. Do not include special characters such as " or '"; } elseif (preg_match_all('/[/]/', $posted_value, $pccevents_event_form_matches)) { $errors['field'. $posted_field->id] = "Please use only alpha or numeric characters. Do not include special characters such as /"; } } return $errors; }
Combine multiple fields into one field
add_filter('frm_validate_field_entry', 'my_custom_validation', 8, 3); function my_custom_validation( $errors, $posted_field, $posted_value ) { if($posted_field->id == 25){ //change 25 to the ID of the hidden field $_POST['item_meta'][25] = $_POST['item_meta'][20] .' '. $_POST['item_meta'][21] .' '. $_POST['item_meta'][22] .' '. $_POST['item_meta'][23]; //change each number (20, 21, 22, 23) to the ID of the field to insert } return $errors; }
Validate field in repeating section
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 4); function my_custom_validation($errors, $posted_field, $posted_value, $args){ if($posted_field->id == 102){ //change to the ID of the field to validate if(!in_array($posted_value, array(123456,987654,234567))){ //enter your allowed values //if it doesn't match up, add an error: $errors['field'. $args['id']] = 'Not a Valid Serial Number'; } } return $errors; }
Redirect User if Already Registered
This example can be used to redirect a user to a different URL if they try registering (using the Registration plugin) when they have already registered.
add_filter('frm_validate_field_entry', 'maybe_redirect', 10, 3); function maybe_redirect( $errors ){ if ( isset( $errors['field'. 799 ]) && $errors['field'. 799 ] == 'This email address is already registered.' ) { //change 799 to your email field id wp_redirect('http://www.google.com'); //change the url to the URL you want users redirected to exit; } return $errors; }
Change the value in a field
This code will get the value from one field and copy it over to a second field.
add_filter('frm_validate_field_entry', 'copy_my_field', 10, 3); function copy_my_field($errors, $posted_field, $posted_value){ if ( $posted_field->id == 25 ) { //change 25 to the ID of the field to change $_POST['item_meta'][$posted_field->id] = $_POST['item_meta'][20]; //Change 20 to the ID of the field to copy } return $errors; }
Required fields suppression for admin
I had the same problem as BusinessNaples described in this ticket - https://formidablepro.com/help-desk/required-fields-suppression-for-admin/
With some help, I created some code that solves the problems. I want to post it here for anyone else who needs it. Now, Admins can edit forms in backend, while restricting certain fields on frontend.
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 3); function my_custom_validation( $errors, $posted_field, $posted_value ) { if ( in_array($posted_field->id, array(200,204,206) ) ){ // Add Field IDs here. Do not make fields required on form if ( ! current_user_can('administrator') && empty( $posted_value ) ) { //if it doesn't match up, add an error: $errors['field'. $posted_field->id] = 'That field is wrong!'; } } return $errors; }
Copy text value from Dynamic field
This code will get the text value from a Dynamic field and copy it over to a second field. Replace 125 with the ID of the field to change and replace 120 with the ID of the Dynamic field to copy. If you want to copy the value from a Dynamic list field, change 20 to the ID of the Dynamic field that the Dynamic List field depends on. Replace 50 with the ID of the linked field that the Dynamic field loads entries from.
add_filter('frm_validate_field_entry', 'copy_my_dynamic_field', 10, 3); function copy_my_dynamic_field( $errors, $posted_field, $posted_value ) { if ( $posted_field->id == 125 ) { $_POST['item_meta'][ $posted_field->id ] = FrmProEntriesController::get_field_value_shortcode( array( 'field_id' => 50, 'entry' => $_POST['item_meta'][120] ) ); } return $errors; }
Limit each user to one entry per option
If you have a dropdown field with 3 options, the same user will be able to submit the form once for each option. If the same option is selected twice, the form will not pass validation.
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 3); function my_custom_validation($errors, $posted_field, $posted_value){ if($posted_field->id == 125 and !is_admin()){ //change 125 to the ID of the field to validate global $wpdb, $user_ID; $entry_id = (isset($_POST['id'])) ? $_POST['id'] : 0; $entries = $wpdb->get_col($wpdb->prepare("SELECT item_id FROM ". $wpdb->prefix ."frm_item_metas em LEFT JOIN ". $wpdb->prefix ."frm_items e ON (em.item_id = e.id) WHERE em.field_id=%d AND em.meta_value=%s AND item_id != %d AND user_id = %d", $posted_field->id, $_POST['item_meta'][$posted_field->id], $entry_id, $user_ID)); if(count($entries) >= 1) //limit to one entry per option. $errors['field'. $posted_field->id] = 'You have already selected that option'; } return $errors; }
Limit the combination of two fields
You may have the need to require the combination of two fields to be unique.
add_filter('frm_validate_field_entry', 'two_fields_unique', 10, 2); function two_fields_unique( $errors, $posted_field ) { $first_field_id = 125; // change 125 to the id of the first field $second_field_id = 126; // change 126 to the id of the second field if ( $posted_field->id == $first_field_id ) { $entry_id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; $values_used = FrmDb::get_col( 'frm_item_metas', array( 'item_id !' => $entry_id, array( 'or' => 1, array( 'field_id' => $first_field_id, 'meta_value' => $_POST['item_meta'][ $first_field_id ] ), array( 'field_id' => $second_field_id, 'meta_value' => $_POST['item_meta'][ $second_field_id ] ), ) ), 'item_id', array( 'group_by' => 'item_id', 'having' => 'COUNT(*) > 1' ) ); if ( ! empty( $values_used ) ) { $errors[ 'field'. $first_field_id ] = 'You have already selected that option'; $errors[ 'field'. $second_field_id ] = 'You have already selected that option'; } } return $errors; }
Calculate total time
Use this code to calculate a total time from a start and end time.
add_filter('frm_validate_field_entry', 'calculate_time', 11, 3); function calculate_time($errors, $field, $value){ if($field->id == 25){ //change 25 to the ID of the hidden or admin only field which will hold the calculation $start = (strtotime($_POST['item_meta'][23])); //change 23 to the ID of the first field $end = (strtotime($_POST['item_meta'][24])); //change 24 to the ID of the first field $totaltime = ($end - $start); $hours = intval($totaltime / 3600); $seconds_remain = ($totaltime - ($hours * 3600)); $minutes = intval($seconds_remain / 60); //$seconds = ($seconds_remain - ($minutes * 60)); Uncomment this line if you want seconds calculated. $totaltime = $hours . ':' . $minutes; $value = $_POST['item_meta'][25] = $totaltime; //change 25 to the ID of the hidden or admin only field which will hold the calculation } return $errors; }
Clear Javascript
Javascript will not be processed by default, but you can use a bit of added code to strip the javascript before save. No changes are needed to this example.
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 2); function my_custom_validation($errors, $posted_field){ if(!current_user_can('administrator')){ //don't strip javascript submitted by administrators if(!is_array($_POST['item_meta'][$posted_field->id])){ $_POST['item_meta'][$posted_field->id] = wp_kses_post($_POST['item_meta'][$posted_field->id]); }else{ foreach($_POST['item_meta'][$posted_field->id] as $k => $v){ if(!is_array($v)) $_POST['item_meta'][$posted_field->id][$k] = wp_kses_post($v); } } } return $errors; }
Get total time from start and end time
Break out hours and minutes totals from start and end time fields. This may not be pretty but it works, below is my adaption of the time totals hook example changed to add total hours and minutes to their own fields for use later.
// * Hour breakout hook add_filter('frm_validate_field_entry', 'calculate_hour', 11, 3); function calculate_hour($errors, $field, $value){ if($field->id == 25){ $start = (strtotime($_POST['item_meta'][23])); //change 23 to the ID of the first field $end = (strtotime($_POST['item_meta'][24])); //change 24 to the ID of the first field $totaltime = ($end - $start); $hours = intval($totaltime / 3600); $seconds_remain = ($totaltime - ($hours * 3600)); $minutes = intval($seconds_remain / 60); $value = $_POST['item_meta'][25] = $hours; //Change 25 to your field that will store hours, here and above in if statement } return $errors; } // * Minutes breakout hook add_filter('frm_validate_field_entry', 'calculate_minute', 11, 3); function calculate_minute($errors, $field, $value){ if($field->id == 25){ $start = (strtotime($_POST['item_meta'][23])); //change 23 to the ID of the start time field $end = (strtotime($_POST['item_meta'][24])); //change 24 to the ID of the end time field $totaltime = ($end - $start); $hours = intval($totaltime / 3600); $seconds_remain = ($totaltime - ($hours * 3600)); $minutes = intval($seconds_remain / 60); $value = $_POST['item_meta'][25] = $minutes; //Change 25 to your field that will store minutes, here and above in if statement } return $errors; }
The reason for this in my case is I then use these fields to calculate totals depending on the entry in another field on the form so when I do the view I take all forms where subject = x and then total the hours and minutes and create a calculation to take the extra minutes and turn them into hours in the view . This was just a simpler way for me to utilize time totals conditionally.
I am sure someone can combine these two hooks into one, I just hacked out the hour and minutes the best I knew how since I am not a programmer, but maybe this will help someone.
Save the date in a different format
When you integrate with other plugins, some may expect a format other that the standard yyyy-mm-dd the Formidable uses. In this case, you can add a hidden field to your form, and use custom code to fill it with the date in the format you need.
add_filter('frm_validate_field_entry', 'copy_my_field', 10, 3); function copy_my_field($errors, $posted_field, $posted_value){ if ( $posted_field->id == 25 ) { //change 25 to the ID of the hidden field to change $oDate = $_POST['item_meta'][77]; // change 77 to the ID of your date field $_POST['item_meta'][$posted_field->id] = strtotime($oDate); } return $errors; }
Have something to add?
Click here to provide feedback on this page.