This article contains PHP code and is intended for developers. We offer this code as a courtesy, but don't provide support for code customizations or 3rd party development.
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.
This hook is run every time the submit button is clicked.
Usage
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 4); function my_custom_validation($errors, $posted_field, $posted_value, $args)
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
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;
}
Require a minimum number of checked values
This code will allow you to require a minimum number of checked boxes in a Checkbox field. Just replace 25 with the ID of your checkbox field and 4 with the minimum number of boxes.
add_filter('frm_validate_field_entry', 'require_minimum_checkbox_number', 10, 3);
function require_minimum_checkbox_number( $errors, $field, $posted_value ){
if ( $field->id == 25 ) {
$minimum = 4;
if ( ! is_array ( $posted_value ) || ( is_array( $posted_value ) && count( $posted_value ) < $minimum ) ) {
$errors['field' . $field->id] = 'Please select at least ' . $minimum . ' items.';
}
}
return $errors;
}
Conditionally require a field
If you would like a field to be required only when a certain value is selected in another field, you can do it without code by marking the field required and using conditional logic on that field to hide it when it's not required. But if you would like the field to always be available, but only sometimes required, this example will help. Be sure you do not mark the field required in your settings.
add_filter( 'frm_validate_field_entry', 'conditionally_require_a_field', 10, 3 );
function conditionally_require_a_field( $errors, $field, $value ) {
if ( $field->id == 25 && trim( $value ) == '' ) { //change 25 to the ID of the field to require
$other_field_value = $_POST['item_meta'][20]; //Change 20 to the ID of the field to check
if ( $other_field_value == 'Today' ) { // change 'Today' to the value needed to make this required
$errors[ 'field'. $field->id ] = 'That field is required';
}
}
return $errors;
}
Check for an allowed value (coupons)
This code checks if a certain field has an allowed value. If it does not have an allowed value, an error is returned. This can be used to validate coupon codes or responses.
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 3);
function my_custom_validation($errors, $posted_field, $posted_value){
if($posted_field->id == 25){ //change 25 to the ID of the field to validate
if(!in_array($posted_value, array('001','002'))){ //change 001 and 002 to your allowed values
//if it doesn't match up, add an error:
$errors['field'. $posted_field->id] = 'That field is wrong!';
}
}
return $errors;
}
Create a confirmation field
Update: This feature is now built in so this customization is no longer necessary. Read more about using confirmation fields
Use this code to make sure two fields have exactly the same value entered. This is often used to verify that email addresses and passwords are correctly entered.
add_filter('frm_validate_field_entry', 'your_custom_validation', 20, 3);
function your_custom_validation($errors, $field, $value){
if ($field->id == 31){ //change 31 to the ID of the confirmation field (second field)
$first_value = $_POST['item_meta'][30]; //change 30 to the ID of the first field
if ( $first_value != $value && !empty($value) ) {
$errors['field'. $field->id] = 'The email addresses entered do not match.';//Customize your error message
}else{
$_POST['item_meta'][$field->id] = ''; //if it matches, this clears the second field so it won't be saved
}
}
return $errors;
}
Combine multiple fields into one field
Before you begin with custom code, it's very likely that the built-in text calculations will help.
Use this code to combine the values of more than one field into a single field. In this example, 25 is the Field ID of the field that will receive the values of the others, which will be linked together in the order listed, and separated by a comma followed by a single space.
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 destination field
//change the value between the quotes to what should go in-between values
$separator = ", ";
$_POST['item_meta'][25] =
$_POST['item_meta'][20] . $separator .
$_POST['item_meta'][21] . $separator .
$_POST['item_meta'][22] . $separator .
$_POST['item_meta'][23];
//change each number (20, 21, 22, 23) to the ID of the fields to insert
}
return $errors;
}
Limit uploaded file size
Custom code is no longer needed. See the file limit options in the file upload field settings.
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;
}
Limit number of uploaded files
Custom code is no longer needed. See the file limit options in the file upload field settings.
This code can be used to limit the number of files that can be uploaded in a file upload field. This will apply to all multiple file upload fields.
add_filter('frm_validate_field_entry', 'validate_number_of_files', 10, 3);
function validate_number_of_files($errors, $field, $value){
if ( in_array($field->id, array(25,26,27)) && $field->type == 'file' && (isset($_FILES['file'.$field->id])) && !empty($_FILES['file'.$field->id]['name'])){
$files = (array)$_FILES['file'. $field->id]['name'];
$count = 0;
foreach($files as $n){
if(!empty($n))
$count++;
}
$existing = $_POST['item_meta'][$field->id];
if($existing){
foreach($existing as $e){
if(!empty($e))
$count++;
}
}
if ($count > 3){ //change 3 to the allowed number of files
$errors['field'.$field->id] = 'Please limit your selection to 3 files.';
}
}
return $errors;
}
Change 25, 26, and 27 to your file upload field IDs, or remove in_array($field->id, array(25,26,27)) if you want this to apply to all file upload fields.
Limit the number of times a date can be selected
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 date field
$frmpro_settings = FrmProAppHelper::get_settings();
$selected_date = FrmProAppHelper::convert_date($posted_value, $frmpro_settings->date_format, 'Y-m-d');
//get all the entries for that date
$entries_for_date = FrmEntryMeta::get_entry_metas_for_field(125, '', '', array('value'=> $selected_date)); //change 125 to the ID of the date field
if(count($entries_for_date) >= 3) //change allowed count here
$errors['field'. $posted_field->id] = 'That date is full!';
}
return $errors;
}
Limit responses for a set time period
Limit the number of times a response can be used in a field within a certain time period, start with this example. The easiest option would be to go to the settings page for your form and select the option to "Limit number of entries to one per saved cookie" and set your hours in the "Cookie expiration" box. If that option is not strict enough for your needs, this custom code will be required.
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 3);
function my_custom_validation($errors, $posted_field, $posted_value){
if($posted_field->id == 25 and !is_admin()){ //change 25 to thema ID of the field to validate
global $wpdb;
$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 e.created_at > %s AND em.meta_value=%s AND item_id != %d", date('Y-m-d H:i:s', strtotime('-24 hours')), $_POST['item_meta'][$posted_field->id], $entry_id)); //change -24 hours to the time range to allow
//$entries = $wpdb->get_col( $wpdb->prepare( "SELECT item_id FROM " . $wpdb->prefix . "frm_items e WHERE item_id != %d AND form_id = %d", $entry_id, $posted_field->form_id ) ); // use this line instead to limit the form to 3 entries
if(count($entries) >= 3) //change allowed count here
$errors['field'. $posted_field->id] = 'That has been submitted today!';
}
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. You may use the code below to make sure two fields are unique. Please note: This does not currently work with post fields.
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. This example is designed to work with time fields set to show as a single dropdown.
Note: This code example is not designed to work with repeaters.
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 second field
$leading_zero_for_minutes="";
$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.
$leading_zero_for_minutes = $minutes < 10 ? '0' : '';
$difference=$hours." : ". $leading_zero_for_minutes.$minutes." : ".$seconds;
$_POST['item_meta'][25] =$difference;
}
return $errors;
}
Require a minimum/maximum word count
Require a minimum, maximum, or range for a required number of words (or characters) in a field.
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 3);
function my_custom_validation($errors, $posted_field, $posted_value){
if ( $posted_field->id == 25 && $posted_value != '' ){ //change 25 to the ID of the field to validate
//check the $posted_value here
$words = explode(' ', $posted_value); //separate at each space
$count = count($words); //count each word
// $count = strlen($posted_value); //uncomment this line to count characters instead of words
//
//uncomment the next two lines create a minimum value and error message
//if($count < 100) //change "100" to fit your minimum limit //$errors['field'. $posted_field->id] = 'That is not long enough.';
//comment the next two lines if you only want a minimum value and error message
if($count > 300) //change "300" to fit your maximum limit
$errors['field'. $posted_field->id] = 'That is too long.';
//uncomment both pairs above to create a range
}
return $errors;
}
Notes:
- This code example is not written to work with fields that are in Repeatable Sections.
- This is set up for a maximum word count. If you want a minimum word count or range, please uncomment and/or comment the code as indicated.
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;
}
Require minimum age
Make sure a user is at least 18 years old before allowing them to submit your form. First, add a date field to your form for birthdates, then add this custom code to check the selected date.
add_filter('frm_validate_field_entry', 'my_custom_validation', 10, 3);
function my_custom_validation($errors, $posted_field, $posted_value){
if($posted_field->id == 25){ //change 25 to the ID of the field to validate
//check the $posted_value here
if(strtotime("-18 years") < strtotime($posted_value)){ //if birthday is less than 18 years ago
//if it doesn't match up, add an error:
$errors['field'. $posted_field->id] = 'That field is wrong!';
}
}
return $errors;
}
Capitalize all text fields
Use this code to capitalize all values entered in text fields when an entry is submitted.
add_filter('frm_validate_field_entry', 'field_caps_validation', 8, 3);
function field_caps_validation($errors, $posted_field, $posted_value){
if($posted_field->type == 'text'){
$_POST['item_meta'][$posted_field->id] = mb_strtoupper($posted_value);
}
return $errors;
}
If you want it to target a specific field you can replace the
$posted_field->type == 'text'
with this one instead:
$posted_field->id == 49
Where 49 is your field ID.
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;
}
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;
}
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;
}
Calculate final date
Update: This feature is now built in so this customization is no longer necessary. Read more about using date calculations.
If you need to get a second date based on an entered date and number of days, you may use the code below. Replace 25 with the ID of the date field that you want to populate with code. Replace 20 with the ID of the date field that you will use in your calculation. Replace +7 day with any PHP safe date string.
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 and change d/m/Y to the format on your Formidable -> Global settings page
$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.
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
- Replace 120 with the ID of the Dynamic field to copy
- 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;
}
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;
}
Combine date and time
Do you need to filter a view by a date and time? Combine the two into a single field to make this possible.
add_filter( 'frm_validate_field_entry', 'frm_combine_date_time', 8, 2 );
function frm_combine_date_time( $errors, $posted_field ) {
$date_field = 25; // change 25 to the id of your date field
$time_field = 26; // change 26 to the id of your time field
$combo_field = 27; // change 27 to the id of your hidden combo field
if ( $posted_field->id == $combo_field ) {
$date = FrmProAppHelper::maybe_convert_to_db_date( sanitize_text_field( $_POST['item_meta'][ $date_field ] ), 'Y-m-d' );
$time = sanitize_text_field( $_POST['item_meta'][ $time_field ] );
FrmProTimeField::time_array_to_string( $time );
$time = FrmProAppHelper::format_time( $time, 'H:i:s' );
$_POST['item_meta'][ $combo_field ] = $date . ' ' . $time;
}
return $errors;
}
Combine auto increment field with another field
Use this code to combine the text in an auto increment field with the text in another field safely. This code runs after any adjustments to the auto increment field would have been made. (The initial numbers in auto increment fields can be changed on form submission if multiple forms are started around the same time.)
Replace 56 with the ID of the field that holds the combination of the auto increment field and the other field. Replace 54 and 55 with the IDs of the auto increment field and the other field. Enter them in the order you want them combined.
add_filter('frm_validate_field_entry', 'combine_auto_id_with_field', 15, 3);
function combine_auto_id_with_field( $errors, $posted_field, $posted_value ) {
if($posted_field->id == 56){ //change 56 to the ID of the destination field
$_POST['item_meta'][56] = $_POST['item_meta'][54] . $_POST['item_meta'][55];
//change 54 and 55 to the IDs of the auto increment field and the other field, in the order you want them combined.
}
return $errors;
}
Calculate time between dates + times
Use this code to calculate a total time between a start and end date and time. Replace m/d/Y with the format selected in your Formidable Global Settings. Replace 23, 24, 25, and 26 with your field IDs.
add_filter('frm_validate_field_entry', 'calculate_time', 11, 3);
function calculate_time($errors, $field, $value){
if($field->id == 30){ //change 30 to the ID of the hidden or admin only field which will hold the calculation
$start_date = date_create_from_format( 'm/d/Y', $_POST['item_meta'][23] ); // Change 23 to the ID of the first date field
$start_date = date_format( $start_date, 'Y-m-d' );
$start = strtotime( $start_date . ' ' . $_POST['item_meta'][24] ); // Change 24 to the ID of the first time field
$end_date = date_create_from_format( 'm/d/Y', $_POST['item_meta'][25] ); // Change 25 to the ID of the second date field
$end_date = date_format( $end_date, 'Y-m-d' );
$end = strtotime( $end_date . ' ' . $_POST['item_meta'][26] ); // Change 26 to the ID of the second time field
$totaltime = human_time_diff( $start, $end );
$_POST['item_meta'][ $field->id ] = $totaltime;
}
return $errors;
}
Keep the default value
Use the code below to save the default value in a field, even if the user has changed the value using browser developer tools. With this, a user won't be able to change a value in a field that's hidden, set to read only, or otherwise restricted.
This code works with default values that are explicitly set (e.g. "100" or "gold") or that use standard WordPress shortcodes (i.e. a shortcode that works on a WordPress page). It won't work with special Formidable shortcodes, like [get param] or [date], that aren't standard WordPress shortcodes.
add_filter( 'frm_validate_field_entry', 'ff_keep_default_value', 10, 3 );
function ff_keep_default_value( $errors, $posted_field, $posted_value ) {
$fields = array( 166, 168, 169 ); //change 166, 168, 169 to the IDs of the fields whose defaults you want to keep. Include as many fields as you want.
if ( in_array( $posted_field->id, $fields ) ) {
$field_id = $posted_field->id;
$field = FrmField::getOne( $field_id );
$default_value = "";
if ( $field && isset( $field->default_value ) ) {
$default_value = $field->default_value;
}
$default_value = do_shortcode( $default_value );
$_POST['item_meta'][ $field_id ] = $default_value;
}
return $errors;
}
Change 166, 169, and 169 to the IDs of the fields whose defaults you want to keep. You can list as many fields as you like, separated with commas. They can be from different forms.
Validate password field
Use this code if you want to force the user to enter a password with at least 8 characters, including at least one letter and one number.
add_filter('frm_validate_field_entry', 'check_user_pass', 10, 3);
function check_user_pass($errors, $posted_field, $posted_value){
if($posted_field->id == 6369){ //change 6369 to the ID of the password field to validate
if(!preg_match('/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z!@#$%&*\(\)?\d]{8,}$/', $posted_value)) {
$errors['field'. $posted_field->id] = 'Password must be at least 8 characters long and contain at least 1 number and 1 letter';
}
}
return $errors;
}
Round robin assignments
As users submit their forms, you can assign them to two different groups in round robin fashion, with one user assigned to group "orange" and the next assigned to group "green." You can modify this code to have more than two groups. You can also use this code to, say, give a prize to every 100th person who fills out the form.
Your form should have a field with a default value of [auto_id] and a field where the group name (or prize info or whatever you want) will be stored.
add_filter( 'frm_validate_field_entry', 'frm_set_value_based_on_order', 15, 3 );
function frm_set_value_based_on_order( $errors, $posted_field, $posted_value ) {
if ( $posted_field->id == 175 ) { //change 175 to the ID of your group name field
$group_id = $_POST['item_meta'][174] % 2;//change 174 to your auto_id field and 2 to the number of groups you have
$group_name = "unassigned";//change "unassigned" to your default value
switch ( $group_id ) {
case 0:
$group_name = "orange";//change "orange" to the name of your group
break;
case 1:
$group_name = "green";//change "green" to the name of your group
break;
}//add additional cases for additional groups, as you'd like
$_POST['item_meta'][175] = $group_name;//change 175 to the ID of your group name field
}
return $errors;
}
Save day of week
The user selects a date in a Date field. You can save the corresponding day of the week (or other aspects of the date) in a Hidden or text field. This Hidden or text field can be used in Conditionals, among other things.
If you want to save the month or some other aspect of the date, change the format from 'l' to the format you prefer. You can see the other format options here.
Change 847 to the id of the Hidden or text field to hold the day of the week and 846 to the Date field.
add_filter( 'frm_validate_field_entry', 'frm_get_day_of_week', 11, 3 );
function frm_get_day_of_week( $errors, $field, $value ) {
if ( $field->id == 847 ) { //change 847 to the ID of the Hidden or text field which will hold the day of the week
$date = date_create_from_format( 'm/d/Y', $_POST['item_meta'][846] ); // Change 846 to the ID of the Date field
$day_of_the_week = date_format( $date, 'l' );//change 'l' to a different format, if desired
$_POST['item_meta'][ $field->id ] = $day_of_the_week;
}
return $errors;
}
Limit the number of entries by user role
This example depends on the [user_role] shortcode in a hidden field in your form. Using this shortcode and the code below, you can limit the number of entries allowed per user role in a form.
add_filter( 'frm_validate_field_entry', 'limit_by_user_role', 10, 3 );
function limit_by_user_role( $errors, $posted_field, $posted_value ) {
$field_id = 136; //change 136 to the ID of the hidden field
if ( $posted_field->id == $field_id ) {
//get all the entries for that role
$entries_for_role = FrmEntryMeta::get_entry_metas_for_field( $field_id, '', '', array( 'value'=> $posted_value ) );
if ( count( $entries_for_role ) >= 2 ) //change allowed count here
$errors[ 'field' . $posted_field->id ] = 'That role is full!';
}
return $errors;
}
Store file upload URL in another field
Use the following example to get the file URL of an uploaded file and store it in another field in the entry when the form is submitted, and before form actions trigger.
add_filter('frm_validate_field_entry', 'filename_to_field', 10, 3);
function filename_to_field($errors, $posted_field, $posted_value){
if ( $posted_field->id == 25 ) { //change 25 to the ID of the field to store the file url in
$_POST['item_meta'][$posted_field->id] = wp_get_attachment_url( $_POST['item_meta'][20] ); //Change 20 to the ID of the file upload field to copy
}
return $errors;
}
Limit number of times a value can be selected
Use this code example to limit the number of times a particular option can be selected in a field.
add_filter( 'frm_validate_field_entry', 'frm_custom_limit', 10, 3 );
function frm_custom_limit( $errors, $posted_field, $posted_value ) {
if ( $posted_field->id == 3734 && !is_admin() ) { //change 3734 to the ID of the field you want to limit
$entries_with_selected_value = FrmEntryMeta::get_entry_metas_for_field( 3734, '', '', array( 'value' => $posted_value ) ); //change 3734 to the ID of the field you want to limit
if ( count( $entries_with_selected_value ) >= 6 ) //change allowed count here
{
$errors[ 'field' . $posted_field->id ] = 'That selection is full!';//change message as you like
}
}
return $errors;
}
Change:
- 3734 to the id of the field you want to limit (in two places)
- 6 to the limit you want
- That selection is full! to the message you want to show users when the limit has been reached.
Calculate total time inside a repeater
Use this code to calculate a total time inside a repeater. This example is designed to work with time fields set to show as a single dropdown.
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 == 5847 ) {// Please replace 5847 with the ID of your repeater field
$field_to_change = 5846 ; // change 5846 to the ID of the field that will hold the time difference
$start_time=5844 ; // change 5844 to the ID of the first time field
$end_time=5845 ; // change 5845 to the ID of the second time field
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;
}
$start = strtotime($_POST['item_meta'][ $posted_field->id ][ $row_num ][$start_time]);
$end = strtotime($_POST['item_meta'][ $posted_field->id ][ $row_num ][$end_time]);
$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.
$leading_zero_for_minutes = $minutes < 10 ? '0' : '';
$difference= $hours.":".$leading_zero_for_minutes.$minutes;
$_POST['item_meta'][5847][ $row_num ][ $field_to_change ] = $difference; //change 5847 to the ID of your repeater
}
}
}
Check for duplicates in repeating fields
This example will prevent duplicate values in repeater field.
add_filter( 'frm_validate_field_entry', 'check_repeating_value_for_duplicates', 10, 4 );
function check_repeating_value_for_duplicates( $errors, $posted_field, $posted_value, $args ){
if ( $posted_field->id == 12692 ) { //Replace 12692 with the ID of the repeater field.
$field_to_check = 12694; //Replace 12694 with the ID of the field inside the repeater.
$vals = array();
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;
}
array_push( $vals, $_POST['item_meta'][ $posted_field->id ][ $row_num ][ $field_to_check ] );
}
if( count( $vals ) != count(array_unique( $vals ) ) ){
$errors[ $field_to_check ] = 'Please enter unique values';
}
}
return $errors;
}
Entry counter for each user
Use this code to have a field in your form that has a counter for each user. It works similarly to the [auto_id] shortcode, but each user has their own count, starting with 1 and increasing for each entry they submit.
Change 2806 to the counter field in your form.
add_filter('frm_validate_field_entry', 'add_user_entry_counter', 10, 3);
function add_user_entry_counter($errors, $posted_field, $posted_value){
$field_id = 2806; // Change 2806 to the ID of the user entry counter field.
if ( $posted_field->id == $field_id ) {
$previous_value = FrmProEntriesController::get_field_value_shortcode( array( 'field_id' => $field_id, 'user_id' => 'current' ) );
$_POST['item_meta'][$posted_field->id] = $previous_value ? (int)$previous_value + 1 : 1;
}
return $errors;
}
Check for a correct answer
This code checks if a field has the correct answer. If the answer is incorrect, an error message is returned. It can validate answers in a multi-paged form and force them back to the page.
add_filter('frm_validate_field_entry', 'check_correct_answer', 10, 3);
function check_correct_answer( $errors, $posted_field, $value ) {
$target_field_id = 1248; // change 1248 to the ID of the field to check
$expected_answer = 'Answer 1'; // change 'Answer 1' with the expected answer
if ( $target_field_id === (int) $posted_field->id && $expected_answer !== $value ) {
$errors[ 'field' . $posted_field->id ] = 'Error'; // change 'Error' with message as you like
}
return $errors;
}
Validate email address
Use this code example to validate the email address entered in your email field by only allowing submission from a particular domain.
add_filter('frm_validate_field_entry', 'check_valid_email', 10, 3);
function check_valid_email($errors, $posted_field, $posted_value){
if($posted_field->id == 7762){ //change 7762 to the ID of the email field
$postedemail=$_POST['item_meta'][7762]; //Change 7762 to the ID of the email field
$alloweddomain = explode('@',$postedemail)[1];
if (!filter_var($postedemail, FILTER_VALIDATE_EMAIL) || $alloweddomain != 'example.com') { //Change example.com to your domain
$errors['field'. $posted_field->id] = 'Sorry! You are not allowed to submit this form';
}
}
return $errors;
}
Apply Alt text to uploaded images in a repeater
Use this code example to apply Alt text to images uploaded through a repeater.
add_filter('frm_validate_field_entry', 'add_alt_text_form_images', 10, 4);
function add_alt_text_form_images($errors, $posted_field, $posted_value, $args){
if ( $posted_field->id == 14548 ) { // Change 14548 with the ID of your repeater field
$image_field_id=14550; // Change 5844 to the ID of the file upload field
$alt_text_field_id=14551; // Change 14551 to the ID of the alt text field
$vals= array();
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;
}
$uploadedimage = $_POST['item_meta'][ $posted_field->id ][$row_num][$image_field_id];
$alttext = $_POST['item_meta'][ $posted_field->id ][$row_num][$alt_text_field_id];
foreach ( (array)$uploadedimage as $id ) {
if ( ! $id ) {
continue;
}
update_post_meta( $id, '_wp_attachment_image_alt', $alttext );
}
}
}
return $errors;
}
Change email fields to lowercase
Use this code example to set all values entered in email fields to lowercase when an entry is submitted.
add_filter('frm_validate_field_entry', 'email_field_lowercase_validation', 8, 3);
function email_field_lowercase_validation($errors, $posted_field, $posted_value){
if($posted_field->type == 'email'){
$_POST['item_meta'][$posted_field->id] = mb_strtolower($posted_value);
}
return $errors;
}
Save geolocation coordinates from address field
Save the latitude and longitude geolocation information from an address field using this code example. To start, add a hidden field in your form for each coordinate.
add_filter('frm_validate_field_entry', 'store_address_coordinates', 10, 3);
function store_address_coordinates($errors, $posted_field, $posted_value){
$fields = array( 31014, 31015); //Change 31014 and 31015 to IDs of the hidden fields where the longitude and latitude coordinates should be stored.
if ( in_array( $posted_field->id, $fields ) ) {
$address_field_id = 31016; //change 31016 to the ID of the Address field
if ( empty( $_POST['geo_lat'] ) || empty( $_POST['geo_lng'] ) || ! is_array( $_POST['geo_lat'] ) || ! is_array( $_POST['geo_lng'] ) ) {
return;
}
if ( ! array_key_exists( $address_field_id, $_POST['geo_lat'] ) || ! array_key_exists( $address_field_id, $_POST['geo_lng'] ) ) {
return;
}
$lat = floatval( $_POST['geo_lat'][ $address_field_id ] );
$long = floatval( $_POST['geo_lng'][ $address_field_id ] );
$_POST['item_meta'][31014] = $lat; //Change 31014 to the ID of the latitude hidden field
$_POST['item_meta'][31015] = $long; //Change 31015 to the ID of the longtitude hidden field
}
return $errors;
}
Calculate total time in a repeater
Use this code example to calculate a total time value for each repeater entry.
add_filter('frm_validate_field_entry', 'calculate_time', 11, 3);
function calculate_time($errors, $field, $value){
$repeater_id = 1457;
$hidden_field_id = 1456; // The field which will hold the total.
$start_field_id = 1454;
$end_field_id = 1455;
if ( $hidden_field_id !== (int) $field->id ) {
return $errors;
}
$repeater_meta = $_POST['item_meta'][ $repeater_id ];
$row_ids = $repeater_meta['row_ids'];
foreach ( $row_ids as $row_id ) {
$row = $_POST['item_meta'][ $repeater_id ][ $row_id ];
$start = strtotime( $row[ $start_field_id ] );
$end = strtotime( $row[ $end_field_id ] );
$totaltime = ($end - $start);
$hours = intval($totaltime / 3600);
$seconds_remain = ($totaltime - ($hours * 3600));
$minutes = intval($seconds_remain / 60);
$leading_zero_for_minutes = $minutes id ] = $totaltime;
$_POST['item_meta'][ $repeater_id ][ $row_id ] = $row;
}
return $errors;
}
Store address field values in hidden fields
While it's currently not possible to filter entries using the address field value, a workaround would be to use this code snippet to extract the address field values and store them in individual hidden fields in the form.
add_filter('frm_validate_field_entry', 'copy_my_field', 10, 3);
function copy_my_field($errors, $posted_field, $posted_value){
if (in_array($posted_field->id, array(30758, 30759, 30760, 30761)) ) { //change 30758, 30759, 30760, 30761 to the IDs of the hidden fields
$_POST['item_meta'][30758]=$_POST['item_meta'][30757]['state']; //change 30757 to the ID of the address field
$_POST['item_meta'][30759] = $_POST['item_meta'][30757]['city']; //change 30757 to the ID of the address field
$_POST['item_meta'][30760] = $_POST['item_meta'][30757]['country']; //change 30757 to the ID of the address field
$_POST['item_meta'][30761] = $_POST['item_meta'][30757]['zip'];
}
return $errors;
}