Created
January 4, 2016 16:41
-
-
Save anonymous/8951cb39d4779e5a0025 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
if ( ! class_exists( 'GFForms' ) ) { | |
die(); | |
} | |
class GFFormDisplay { | |
public static $submission = array(); | |
private static $init_scripts = array(); | |
const ON_PAGE_RENDER = 1; | |
const ON_CONDITIONAL_LOGIC = 2; | |
public static function process_form( $form_id ) { | |
GFCommon::log_debug( "GFFormDisplay::process_form(): Starting to process form (#{$form_id}) submission." ); | |
//reading form metadata | |
$form = GFAPI::get_form( $form_id ); | |
if ( ! $form['is_active'] || $form['is_trash'] ) { | |
return; | |
} | |
if ( rgar( $form, 'requireLogin' ) ) { | |
if ( ! is_user_logged_in() ) { | |
return; | |
} | |
check_admin_referer( 'gform_submit_' . $form_id, '_gform_submit_nonce_' . $form_id ); | |
} | |
//pre process action | |
/** | |
* Fires before a form is processed (You can specify the ID of the form to checK) | |
* | |
* @param array $form The Form Object | |
*/ | |
gf_do_action( 'gform_pre_process', $form['id'], $form ); | |
$lead = array(); | |
$field_values = RGForms::post( 'gform_field_values' ); | |
$confirmation_message = ''; | |
$source_page_number = self::get_source_page( $form_id ); | |
$page_number = $source_page_number; | |
$target_page = self::get_target_page( $form, $page_number, $field_values ); | |
GFCommon::log_debug( "GFFormDisplay::process_form(): Source page number: {$source_page_number}. Target page number: {$target_page}." ); | |
//Loading files that have been uploaded to temp folder | |
$files = GFCommon::json_decode( stripslashes( RGForms::post( 'gform_uploaded_files' ) ) ); | |
if ( ! is_array( $files ) ) { | |
$files = array(); | |
} | |
RGFormsModel::$uploaded_files[ $form_id ] = $files; | |
$saving_for_later = rgpost( 'gform_save' ) ? true : false; | |
$is_valid = true; | |
$failed_validation_page = $page_number; | |
//don't validate when going to previous page or saving for later | |
if ( ! $saving_for_later && ( empty( $target_page ) || $target_page >= $page_number ) ) { | |
$is_valid = self::validate( $form, $field_values, $page_number, $failed_validation_page ); | |
} | |
$log_is_valid = $is_valid ? 'Yes' : 'No'; | |
GFCommon::log_debug( "GFFormDisplay::process_form(): After validation. Is submission valid? {$log_is_valid}." ); | |
//Upload files to temp folder when saving for later, going to the next page or when submitting the form and it failed validation | |
if ( $saving_for_later || $target_page >= $page_number || ( $target_page == 0 && ! $is_valid ) ) { | |
if ( ! empty( $_FILES ) ) { | |
GFCommon::log_debug( 'GFFormDisplay::process_form(): Uploading files...' ); | |
//Uploading files to temporary folder | |
$files = self::upload_files( $form, $files ); | |
RGFormsModel::$uploaded_files[ $form_id ] = $files; | |
} | |
} | |
// Load target page if it did not fail validation or if going to the previous page | |
if ( ! $saving_for_later && $is_valid ) { | |
$page_number = $target_page; | |
} else { | |
$page_number = $failed_validation_page; | |
} | |
$confirmation = ''; | |
if ( ( $is_valid && $page_number == 0 ) || $saving_for_later ) { | |
$ajax = isset( $_POST['gform_ajax'] ); | |
//adds honeypot field if configured | |
if ( rgar( $form, 'enableHoneypot' ) ) { | |
$form['fields'][] = self::get_honeypot_field( $form ); | |
} | |
$failed_honeypot = rgar( $form, 'enableHoneypot' ) && ! self::validate_honeypot( $form ); | |
if ( $failed_honeypot ) { | |
GFCommon::log_debug( 'GFFormDisplay::process_form(): Failed Honeypot validation. Displaying confirmation and aborting.' ); | |
//display confirmation but doesn't process the form when honeypot fails | |
$confirmation = self::handle_confirmation( $form, $lead, $ajax ); | |
$is_valid = false; | |
} elseif ( ! $saving_for_later ) { | |
GFCommon::log_debug( 'GFFormDisplay::process_form(): Submission is valid. Moving forward.' ); | |
$form = self::update_confirmation( $form ); | |
//pre submission action | |
gf_do_action( 'gform_pre_submission', $form['id'], $form ); | |
//pre submission filter | |
$form = gf_apply_filters( 'gform_pre_submission_filter', $form_id, $form ); | |
//handle submission | |
$confirmation = self::handle_submission( $form, $lead, $ajax ); | |
//after submission hook | |
gf_do_action( 'gform_after_submission', $form['id'], $lead, $form ); | |
} elseif ( $saving_for_later ) { | |
GFCommon::log_debug( 'GFFormDisplay::process_form(): Saving for later.' ); | |
$lead = GFFormsModel::get_current_lead(); | |
$form = self::update_confirmation( $form, $lead, 'form_saved' ); | |
$confirmation = rgar( $form['confirmation'], 'message' ); | |
$nl2br = rgar( $form['confirmation'], 'disableAutoformat' ) ? false : true; | |
$confirmation = GFCommon::replace_variables( $confirmation, $form, $lead, false, true, $nl2br ); | |
$form_unique_id = GFFormsModel::get_form_unique_id( $form_id ); | |
$ip = GFFormsModel::get_ip(); | |
$source_url = GFFormsModel::get_current_page_url(); | |
$source_url = esc_url_raw( $source_url ); | |
$resume_token = rgpost( 'gform_resume_token' ); | |
$resume_token = sanitize_key( $resume_token ); | |
$resume_token = GFFormsModel::save_incomplete_submission( $form, $lead, $field_values, $page_number, $files, $form_unique_id, $ip, $source_url, $resume_token ); | |
$notifications_to_send = GFCommon::get_notifications_to_send( 'form_saved', $form, $lead ); | |
$log_notification_event = empty( $notifications_to_send ) ? 'No notifications to process' : 'Processing notifications'; | |
GFCommon::log_debug( "GFFormDisplay::process_form(): {$log_notification_event} for form_saved event." ); | |
foreach ( $notifications_to_send as $notification ) { | |
if ( isset( $notification['isActive'] ) && ! $notification['isActive'] ) { | |
GFCommon::log_debug( "GFFormDisplay::process_form(): Notification is inactive, not processing notification (#{$notification['id']} - {$notification['name']})." ); | |
continue; | |
} | |
$notification['message'] = self::replace_save_variables( $notification['message'], $form, $resume_token ); | |
GFCommon::send_notification( $notification, $form, $lead ); | |
} | |
self::set_submission_if_null( $form_id, 'saved_for_later', true ); | |
self::set_submission_if_null( $form_id, 'resume_token', $resume_token ); | |
GFCommon::log_debug( 'GFFormDisplay::process_form(): Saved incomplete submission.' ); | |
} | |
if ( is_array( $confirmation ) && isset( $confirmation['redirect'] ) ){ | |
header( "Location: {$confirmation["redirect"]}" ); | |
gf_do_action( 'gform_post_submission', $form['id'], $lead, $form ); | |
exit; | |
} | |
} | |
if ( ! isset( self::$submission[ $form_id ] ) ) { | |
self::$submission[ $form_id ] = array(); | |
} | |
self::set_submission_if_null( $form_id, 'is_valid', $is_valid ); | |
self::set_submission_if_null( $form_id, 'form', $form ); | |
self::set_submission_if_null( $form_id, 'lead', $lead ); | |
self::set_submission_if_null( $form_id, 'confirmation_message', $confirmation ); | |
self::set_submission_if_null( $form_id, 'page_number', $page_number ); | |
self::set_submission_if_null( $form_id, 'source_page_number', $source_page_number ); | |
/** | |
* Fires after the form processing is completed. Form processing happens when submitting a page on a multi-page form (i.e. going to the "Next" or "Previous" page), or | |
* when submitting a single page form. | |
* | |
* @param array $form The Form Object | |
* @param int $page_number In a multi-page form, this variable contains the current page number. | |
* @param int $source_page_number In a multi-page form, this parameters contains the number of the page that the submission came from. | |
* For example, when clicking "Next" on page 1, this parameter will be set to 1. When clicking "Previous" on page 2, this parameter will be set to 2. | |
*/ | |
gf_do_action( 'gform_post_process', $form['id'], $form, $page_number, $source_page_number ); | |
} | |
private static function set_submission_if_null( $form_id, $key, $val ) { | |
if ( ! isset( self::$submission[ $form_id ][ $key ] ) ) { | |
self::$submission[ $form_id ][ $key ] = $val; | |
} | |
} | |
private static function upload_files( $form, $files ) { | |
$form_upload_path = GFFormsModel::get_upload_path( $form['id'] ); | |
//Creating temp folder if it does not exist | |
$target_path = $form_upload_path . '/tmp/'; | |
wp_mkdir_p( $target_path ); | |
GFCommon::recursive_add_index_file( $form_upload_path ); | |
foreach ( $form['fields'] as $field ) { | |
$input_name = "input_{$field->id}"; | |
//skip fields that are not file upload fields or that don't have a file to be uploaded or that have failed validation | |
$input_type = RGFormsModel::get_input_type( $field ); | |
if ( ! in_array( $input_type, array( 'fileupload', 'post_image' ) ) || $field->multipleFiles ) { | |
continue; | |
} | |
if ( $field->failed_validation || empty( $_FILES[ $input_name ]['name'] ) ) { | |
GFCommon::log_debug( "GFFormDisplay::upload_files(): Skipping field: {$field->label}({$field->id} - {$field->type})." ); | |
continue; | |
} | |
$file_info = RGFormsModel::get_temp_filename( $form['id'], $input_name ); | |
GFCommon::log_debug( 'GFFormDisplay::upload_files(): Temp file info: ' . print_r( $file_info, true ) ); | |
if ( $file_info && move_uploaded_file( $_FILES[ $input_name ]['tmp_name'], $target_path . $file_info['temp_filename'] ) ) { | |
GFFormsModel::set_permissions( $target_path . $file_info['temp_filename'] ); | |
$files[ $input_name ] = $file_info['uploaded_filename']; | |
GFCommon::log_debug( "GFFormDisplay::upload_files(): File uploaded successfully: {$file_info['uploaded_filename']}" ); | |
} else { | |
GFCommon::log_error( "GFFormDisplay::upload_files(): File could not be uploaded: tmp_name: {$_FILES[ $input_name ]['tmp_name']} - target location: " . $target_path . $file_info['temp_filename'] ); | |
} | |
} | |
return $files; | |
} | |
public static function get_state( $form, $field_values ) { | |
$product_fields = array(); | |
foreach ( $form['fields'] as $field ) { | |
/* @var GF_Field $field */ | |
if ( GFCommon::is_product_field( $field->type ) || $field->type == 'donation' ) { | |
$value = RGFormsModel::get_field_value( $field, $field_values, false ); | |
$value = $field->get_value_default_if_empty( $value ); | |
switch ( $field->inputType ) { | |
case 'calculation' : | |
case 'singleproduct' : | |
case 'hiddenproduct' : | |
$price = ! is_array( $value ) || empty( $value[ $field->id . '.2' ] ) ? $field->basePrice : $value[ $field->id . '.2' ]; | |
if ( empty( $price ) ) { | |
$price = 0; | |
} | |
$price = GFCommon::to_number( $price ); | |
$product_name = ! is_array( $value ) || empty( $value[ $field->id . '.1' ] ) ? $field->label : $value[ $field->id . '.1' ]; | |
$product_fields[ $field->id . '.1' ] = wp_hash( GFFormsModel::maybe_trim_input( $product_name, $form['id'], $field ) ); | |
$product_fields[ $field->id . '.2' ] = wp_hash( GFFormsModel::maybe_trim_input( $price, $form['id'], $field ) ); | |
break; | |
case 'singleshipping' : | |
$price = ! empty( $value ) ? $value : $field->basePrice; | |
$price = ! empty( $price ) ? GFCommon::to_number( $price ) : 0; | |
$product_fields[ $field->id ] = wp_hash( GFFormsModel::maybe_trim_input( $price, $form['id'], $field ) ); | |
break; | |
case 'radio' : | |
case 'select' : | |
$product_fields[ $field->id ] = array(); | |
foreach ( $field->choices as $choice ) { | |
$field_value = ! empty( $choice['value'] ) || $field->enableChoiceValue ? $choice['value'] : $choice['text']; | |
if ( $field->enablePrice ) { | |
$price = rgempty( 'price', $choice ) ? 0 : GFCommon::to_number( rgar( $choice, 'price' ) ); | |
$field_value .= '|' . $price; | |
} | |
$product_fields[ $field->id ][] = wp_hash( GFFormsModel::maybe_trim_input( $field_value, $form['id'], $field ) ); | |
} | |
break; | |
case 'checkbox' : | |
$index = 1; | |
foreach ( $field->choices as $choice ) { | |
$field_value = ! empty( $choice['value'] ) || $field->enableChoiceValue ? $choice['value'] : $choice['text']; | |
if ( $field->enablePrice ) { | |
$price = rgempty( 'price', $choice ) ? 0 : GFCommon::to_number( rgar( $choice, 'price' ) ); | |
$field_value .= '|' . $price; | |
} | |
if ( $index % 10 == 0 ) { //hack to skip numbers ending in 0. so that 5.1 doesn't conflict with 5.10 | |
$index ++; | |
} | |
$product_fields[ $field->id . '.' . $index ++ ] = wp_hash( GFFormsModel::maybe_trim_input( $field_value, $form['id'], $field ) ); | |
} | |
break; | |
} | |
} | |
} | |
$hash = json_encode( $product_fields ); | |
$checksum = wp_hash( crc32( $hash ) ); | |
return base64_encode( json_encode( array( $hash, $checksum ) ) ); | |
} | |
private static function has_pages( $form ) { | |
return GFCommon::has_pages( $form ); | |
} | |
private static function has_character_counter( $form ) { | |
if ( ! is_array( $form['fields'] ) ) { | |
return false; | |
} | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->maxLength && ! $field->inputMask ) { | |
return true; | |
} | |
} | |
return false; | |
} | |
private static function has_placeholder( $form ) { | |
if ( ! is_array( $form['fields'] ) ) { | |
return false; | |
} | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->placeholder != '' ) { | |
return true; | |
} | |
if ( is_array( $field->inputs ) ) { | |
foreach ( $field->inputs as $input ) { | |
if ( rgar( $input, 'placeholder' ) != '' ) { | |
return true; | |
} | |
} | |
} | |
} | |
return false; | |
} | |
private static function has_enhanced_dropdown( $form ) { | |
if ( ! is_array( $form['fields'] ) ) { | |
return false; | |
} | |
foreach ( $form['fields'] as $field ) { | |
if ( in_array( RGFormsModel::get_input_type( $field ), array( 'select', 'multiselect' ) ) && $field->enableEnhancedUI ) { | |
return true; | |
} | |
} | |
return false; | |
} | |
private static function has_password_strength( $form ) { | |
if ( ! is_array( $form['fields'] ) ) { | |
return false; | |
} | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->type == 'password' && $field->passwordStrengthEnabled ) { | |
return true; | |
} | |
} | |
return false; | |
} | |
private static function has_other_choice( $form ) { | |
if ( ! is_array( $form['fields'] ) ) { | |
return false; | |
} | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->type == 'radio' && $field->enableOtherChoice ) { | |
return true; | |
} | |
} | |
return false; | |
} | |
public static function get_target_page( $form, $current_page, $field_values ) { | |
$page_number = RGForms::post( "gform_target_page_number_{$form['id']}" ); | |
$page_number = ! is_numeric( $page_number ) ? 1 : $page_number; | |
$direction = $page_number >= $current_page ? 1 : - 1; | |
//Finding next page that is not hidden by conditional logic | |
while ( RGFormsModel::is_page_hidden( $form, $page_number, $field_values ) ) { | |
$page_number += $direction; | |
} | |
//If all following pages are hidden, submit the form | |
if ( $page_number > self::get_max_page_number( $form ) ) { | |
$page_number = 0; | |
} | |
return $page_number; | |
} | |
public static function get_source_page( $form_id ) { | |
$page_number = RGForms::post( "gform_source_page_number_{$form_id}" ); | |
return ! is_numeric( $page_number ) ? 1 : $page_number; | |
} | |
public static function set_current_page( $form_id, $page_number ) { | |
self::$submission[ $form_id ]['page_number'] = $page_number; | |
} | |
public static function get_current_page( $form_id ) { | |
$page_number = isset( self::$submission[ $form_id ] ) ? intval( self::$submission[ $form_id ]['page_number'] ) : 1; | |
return $page_number; | |
} | |
private static function is_page_active( $form_id, $page_number ) { | |
return intval( self::get_current_page( $form_id ) ) == intval( $page_number ); | |
} | |
/** | |
* Determine if the last page for the current form object is being submitted or rendered (depending on the provided $mode). | |
* | |
* @param array $form A Gravity Forms form object. | |
* @param string $mode Mode to check for: 'submit' or 'render' | |
* | |
* @return boolean | |
*/ | |
public static function is_last_page( $form, $mode = 'submit' ) { | |
$page_number = self::get_source_page( $form['id'] ); | |
$field_values = GFForms::post( 'gform_field_values' ); | |
$target_page = self::get_target_page( $form, $page_number, $field_values ); | |
if ( $mode == 'render' ) { | |
$is_valid = rgars( self::$submission, "{$form['id']}/is_valid" ); | |
$is_last_page = $is_valid && $target_page == self::get_max_page_number( $form ); | |
} else { | |
$is_last_page = (string) $target_page === '0'; | |
} | |
return $is_last_page; | |
} | |
private static function get_limit_period_dates( $period ) { | |
if ( empty( $period ) ) { | |
return array( 'start_date' => null, 'end_date' => null ); | |
} | |
switch ( $period ) { | |
case 'day' : | |
return array( | |
'start_date' => gmdate( 'Y-m-d' ), | |
'end_date' => gmdate( 'Y-m-d 23:59:59' ) | |
); | |
break; | |
case 'week' : | |
return array( | |
'start_date' => gmdate( 'Y-m-d', strtotime( 'Monday this week' ) ), | |
'end_date' => gmdate( 'Y-m-d 23:59:59', strtotime( 'next Sunday' ) ) | |
); | |
break; | |
case 'month' : | |
$month_start = gmdate( 'Y-m-1' ); | |
return array( | |
'start_date' => $month_start, | |
'end_date' => gmdate( 'Y-m-d H:i:s', strtotime( "{$month_start} +1 month -1 second" ) ) | |
); | |
break; | |
case 'year' : | |
return array( | |
'start_date' => gmdate( 'Y-1-1' ), | |
'end_date' => gmdate( 'Y-12-31 23:59:59' ) | |
); | |
break; | |
} | |
} | |
public static function get_form( $form_id, $display_title = true, $display_description = true, $force_display = false, $field_values = null, $ajax = false, $tabindex = 1 ) { | |
/** | |
* Provides the ability to modify the options used to display the form | |
* | |
* @param array An array of Form Arguments when adding it to a page/post (Like the ID, Title, AJAX or not, etc) | |
*/ | |
$form_args = apply_filters( 'gform_form_args', compact( 'form_id', 'display_title', 'display_description', 'force_display', 'field_values', 'ajax', 'tabindex' ) ); | |
extract( $form_args ); | |
//looking up form id by form name | |
if ( ! is_numeric( $form_id ) ) { | |
$form_id = RGFormsModel::get_form_id( $form_id ); | |
} | |
//reading form metadata | |
$form = RGFormsModel::get_form_meta( $form_id, true ); | |
$action = remove_query_arg( 'gf_token' ); | |
//disable ajax if form has a reCAPTCHA field (not supported). | |
if ( $ajax && self::has_recaptcha_field( $form ) ) { | |
$ajax = false; | |
} | |
if ( isset( $_POST['gform_send_resume_link'] ) ) { | |
$save_email_confirmation = self::handle_save_email_confirmation( $form, $ajax ); | |
if ( is_wp_error( $save_email_confirmation ) ) { // Failed email validation | |
$resume_token = rgpost( 'gform_resume_token' ); | |
$resume_token = sanitize_key( $resume_token ); | |
$incomplete_submission_info = GFFormsModel::get_incomplete_submission_values( $resume_token ); | |
if ( $incomplete_submission_info['form_id'] == $form_id ) { | |
$submission_details_json = $incomplete_submission_info['submission']; | |
$submission_details = json_decode( $submission_details_json, true ); | |
$partial_entry = $submission_details['partial_entry']; | |
$form = self::update_confirmation( $form, $partial_entry, 'form_saved' ); | |
$confirmation_message = rgar( $form['confirmation'], 'message' ); | |
$nl2br = rgar( $form['confirmation'], 'disableAutoformat' ) ? false : true; | |
$confirmation_message = GFCommon::replace_variables( $confirmation_message, $form, $partial_entry, false, true, $nl2br ); | |
return self::handle_save_confirmation( $form, $resume_token, $confirmation_message, $ajax ); | |
} | |
} else { | |
return $save_email_confirmation; | |
} | |
} | |
$is_postback = false; | |
$is_valid = true; | |
$confirmation_message = ''; | |
//If form was submitted, read variables set during form submission procedure | |
$submission_info = isset( self::$submission[ $form_id ] ) ? self::$submission[ $form_id ] : false; | |
if ( rgar( $submission_info, 'saved_for_later' ) == true ) { | |
$resume_token = $submission_info['resume_token']; | |
$confirmation_message = rgar( $submission_info, 'confirmation_message' ); | |
return self::handle_save_confirmation( $form, $resume_token, $confirmation_message, $ajax ); | |
} | |
$partial_entry = $submitted_values = false; | |
if ( isset( $_GET['gf_token'] ) ) { | |
$incomplete_submission_info = GFFormsModel::get_incomplete_submission_values( $_GET['gf_token'] ); | |
if ( $incomplete_submission_info['form_id'] == $form_id ) { | |
$submission_details_json = $incomplete_submission_info['submission']; | |
$submission_details = json_decode( $submission_details_json, true ); | |
$partial_entry = $submission_details['partial_entry']; | |
$submitted_values = $submission_details['submitted_values']; | |
$field_values = $submission_details['field_values']; | |
GFFormsModel::$unique_ids[ $form_id ] = $submission_details['gform_unique_id']; | |
GFFormsModel::$uploaded_files[ $form_id ] = $submission_details['files']; | |
self::set_submission_if_null( $form_id, 'resuming_incomplete_submission', true ); | |
self::set_submission_if_null( $form_id, 'form_id', $form_id ); | |
self::set_submission_if_null( $form_id, 'page_number', $submission_details['page_number'] ); | |
} | |
} | |
if ( ! is_array( $partial_entry ) ) { | |
/** | |
* A filter that allows disabling of the form view counter | |
* | |
* @param int $form_id The Form ID to filter when disabling the form view counter | |
* @param bool Default set to false (view counter enabled), can be set to true to disable the counter | |
*/ | |
$view_counter_disabled = gf_apply_filters( 'gform_disable_view_counter', $form_id, false ); | |
if ( $submission_info ) { | |
$is_postback = true; | |
$is_valid = rgar( $submission_info, 'is_valid' ) || rgar( $submission_info, 'is_confirmation' ); | |
$form = $submission_info['form']; | |
$lead = $submission_info['lead']; | |
$confirmation_message = rgget( 'confirmation_message', $submission_info ); | |
if ( $is_valid && ! RGForms::get( 'is_confirmation', $submission_info ) ) { | |
if ( $submission_info['page_number'] == 0 ) { | |
//post submission hook | |
gf_do_action( 'gform_post_submission', $form['id'], $lead, $form ); | |
} else { | |
//change page hook | |
gf_do_action( 'gform_post_paging', $form['id'], $form, $submission_info['source_page_number'], $submission_info['page_number'] ); | |
} | |
} | |
} elseif ( ! current_user_can( 'administrator' ) && ! $view_counter_disabled ) { | |
RGFormsModel::insert_form_view( $form_id, $_SERVER['REMOTE_ADDR'] ); | |
} | |
} | |
if ( rgar( $form, 'enableHoneypot' ) ) { | |
$form['fields'][] = self::get_honeypot_field( $form ); | |
} | |
//Fired right before the form rendering process. Allow users to manipulate the form object before it gets displayed in the front end | |
$form = gf_apply_filters( 'gform_pre_render', $form_id, $form, $ajax, $field_values ); | |
if ( $form == null ) { | |
return '<p>' . esc_html__( 'Oops! We could not locate your form.', 'gravityforms' ) . '</p>'; | |
} | |
$has_pages = self::has_pages( $form ); | |
//calling tab index filter | |
GFCommon::$tab_index = gf_apply_filters( 'gform_tabindex', $form_id, $tabindex, $form ); | |
//Don't display inactive forms | |
if ( ! $force_display && ! $is_postback ) { | |
$form_info = RGFormsModel::get_form( $form_id ); | |
if ( empty( $form_info ) || ! $form_info->is_active ) { | |
return ''; | |
} | |
// If form requires login, check if user is logged in | |
if ( rgar( $form, 'requireLogin' ) ) { | |
if ( ! is_user_logged_in() ) { | |
return empty( $form['requireLoginMessage'] ) ? '<p>' . esc_html__( 'Sorry. You must be logged in to view this form.', 'gravityforms' ) . '</p>' : '<p>' . GFCommon::gform_do_shortcode( $form['requireLoginMessage'] ) . '</p>'; | |
} | |
} | |
} | |
// show the form regardless of the following validations when force display is set to true | |
if ( ! $force_display || $is_postback ) { | |
$form_schedule_validation = self::validate_form_schedule( $form ); | |
// if form schedule validation fails AND this is not a postback, display the validation error | |
// if form schedule validation fails AND this is a postback, make sure is not a valid submission (enables display of confirmation message) | |
if ( ( $form_schedule_validation && ! $is_postback ) || ( $form_schedule_validation && $is_postback && ! $is_valid ) ) { | |
return $form_schedule_validation; | |
} | |
$entry_limit_validation = self::validate_entry_limit( $form ); | |
// refer to form schedule condition notes above | |
if ( ( $entry_limit_validation && ! $is_postback ) || ( $entry_limit_validation && $is_postback && ! $is_valid ) ) { | |
return $entry_limit_validation; | |
} | |
} | |
$form_string = ''; | |
//When called via a template, this will enqueue the proper scripts | |
//When called via a shortcode, this will be ignored (too late to enqueue), but the scripts will be enqueued via the enqueue_scripts event | |
self::enqueue_form_scripts( $form, $ajax ); | |
$is_form_editor = GFCommon::is_form_editor(); | |
$is_entry_detail = GFCommon::is_entry_detail(); | |
$is_admin = $is_form_editor || $is_entry_detail; | |
if ( empty( $confirmation_message ) ) { | |
$wrapper_css_class = GFCommon::get_browser_class() . ' gform_wrapper'; | |
if ( ! $is_valid ) { | |
$wrapper_css_class .= ' gform_validation_error'; | |
} | |
//Hiding entire form if conditional logic is on to prevent 'hidden' fields from blinking. Form will be set to visible in the conditional_logic.php after the rules have been applied. | |
$style = self::has_conditional_logic( $form ) ? "style='display:none'" : ''; | |
$custom_wrapper_css_class = ! empty( $form['cssClass'] ) ? " {$form['cssClass']}_wrapper" : ''; | |
$form_string .= " | |
<div class='{$wrapper_css_class}{$custom_wrapper_css_class}' id='gform_wrapper_$form_id' " . $style . '>'; | |
$default_anchor = $has_pages || $ajax ? true : false; | |
$use_anchor = gf_apply_filters( 'gform_confirmation_anchor', $form_id, $default_anchor ); | |
if ( $use_anchor !== false ) { | |
$form_string .= "<a id='gf_$form_id' class='gform_anchor' ></a>"; | |
$action .= "#gf_$form_id"; | |
} | |
$target = $ajax ? "target='gform_ajax_frame_{$form_id}'" : ''; | |
$form_css_class = ! empty( $form['cssClass'] ) ? "class='{$form['cssClass']}'" : ''; | |
$action = esc_url( $action ); | |
$form_string .= gf_apply_filters( 'gform_form_tag', $form_id, "<form method='post' enctype='multipart/form-data' {$target} id='gform_{$form_id}' {$form_css_class} action='{$action}'>", $form ); | |
if ( $display_title || $display_description ) { | |
$form_string .= " | |
<div class='gform_heading'>"; | |
if ( $display_title ) { | |
$form_string .= " | |
<h3 class='gform_title'>" . $form['title'] . '</h3>'; | |
} | |
if ( $display_description ) { | |
$form_string .= " | |
<span class='gform_description'>" . rgar( $form, 'description' ) . '</span>'; | |
} | |
$form_string .= ' | |
</div>'; | |
} | |
$current_page = self::get_current_page( $form_id ); | |
if ( $has_pages && ! $is_admin ) { | |
if ( $form['pagination']['type'] == 'percentage' ) { | |
$form_string .= self::get_progress_bar( $form, $form_id, $confirmation_message ); | |
} else if ( $form['pagination']['type'] == 'steps' ) { | |
$form_string .= " | |
<div id='gf_page_steps_{$form_id}' class='gf_page_steps'>"; | |
$pages = isset( $form['pagination']['pages'] ) ? $form['pagination']['pages'] : array(); | |
for ( $i = 0, $count = sizeof( $pages ); $i < $count; $i ++ ) { | |
$step_number = $i + 1; | |
$active_class = $step_number == $current_page ? ' gf_step_active' : ''; | |
$first_class = $i == 0 ? ' gf_step_first' : ''; | |
$last_class = $i + 1 == $count ? ' gf_step_last' : ''; | |
$complete_class = $step_number < $current_page ? ' gf_step_completed' : ''; | |
$previous_class = $step_number + 1 == $current_page ? ' gf_step_previous' : ''; | |
$next_class = $step_number - 1 == $current_page ? ' gf_step_next' : ''; | |
$pending_class = $step_number > $current_page ? ' gf_step_pending' : ''; | |
$classes = 'gf_step' . $active_class . $first_class . $last_class . $complete_class . $previous_class . $next_class . $pending_class; | |
$classes = GFCommon::trim_all( $classes ); | |
$form_string .= " | |
<div id='gf_step_{$form_id}_{$step_number}' class='{$classes}'><span class='gf_step_number'>{$step_number}</span> <span class='gf_step_label'>{$pages[ $i ]}</span></div>"; | |
} | |
$form_string .= " | |
<div class='gf_step_clear'></div> | |
</div>"; | |
} | |
} | |
if ( $is_postback && ! $is_valid ) { | |
$validation_message = "<div class='validation_error'>" . esc_html__( 'There was a problem with your submission.', 'gravityforms' ) . ' ' . esc_html__( 'Errors have been highlighted below.', 'gravityforms' ) . '</div>'; | |
$form_string .= gf_apply_filters( 'gform_validation_message', $form_id, $validation_message, $form ); | |
} | |
$form_string .= " | |
<div class='gform_body'>"; | |
//add first page if this form has any page fields | |
if ( $has_pages ) { | |
$style = self::is_page_active( $form_id, 1 ) ? '' : "style='display:none;'"; | |
$class = ! empty( $form['firstPageCssClass'] ) ? " {$form['firstPageCssClass']}" : ''; | |
$form_string .= "<div id='gform_page_{$form_id}_1' class='gform_page{$class}' {$style}> | |
<div class='gform_page_fields'>"; | |
} | |
$description_class = rgar( $form, 'descriptionPlacement' ) == 'above' ? 'description_above' : 'description_below'; | |
$sublabel_class = rgar( $form, 'subLabelPlacement' ) == 'above' ? 'form_sublabel_above' : 'form_sublabel_below'; | |
$form_string .= "<ul id='gform_fields_{$form_id}' class='" . GFCommon::get_ul_classes( $form ) . "'>"; | |
if ( is_array( $form['fields'] ) ) { | |
foreach ( $form['fields'] as $field ) { | |
/* @var GF_Field $field */ | |
$field->conditionalLogicFields = self::get_conditional_logic_fields( $form, $field->id ); | |
if ( is_array( $submitted_values ) ) { | |
$field_value = rgar( $submitted_values, $field->id ); | |
} else { | |
$field_value = GFFormsModel::get_field_value( $field, $field_values ); | |
} | |
$form_string .= self::get_field( $field, $field_value, false, $form, $field_values ); | |
} | |
} | |
$form_string .= ' | |
</ul>'; | |
if ( $has_pages ) { | |
$previous_button = self::get_form_button( $form['id'], "gform_previous_button_{$form['id']}", $form['lastPageButton'], __( 'Previous', 'gravityforms' ), 'gform_previous_button', __( 'Previous Page', 'gravityforms' ), self::get_current_page( $form_id ) - 1 ); | |
/** | |
* Filter through the form previous button when paged | |
* | |
* @param int $form_id The Form ID to filter through | |
* @param string $previous_button The HTML rendered button (rendered with the form ID and the function get_form_button) | |
* @param array $form The Form object to filter through | |
*/ | |
$previous_button = gf_apply_filters( 'gform_previous_button', $form_id, $previous_button, $form ); | |
$form_string .= '</div>' . self::gform_footer( $form, 'gform_page_footer ' . $form['labelPlacement'], $ajax, $field_values, $previous_button, $display_title, $display_description, $is_postback ) . ' | |
</div>'; //closes gform_page | |
} | |
$form_string .= '</div>'; //closes gform_body | |
//suppress form footer for multi-page forms (footer will be included on the last page | |
if ( ! $has_pages ) { | |
$form_string .= self::gform_footer( $form, 'gform_footer ' . $form['labelPlacement'], $ajax, $field_values, '', $display_title, $display_description, $tabindex ); | |
} | |
$form_string .= ' | |
</form> | |
</div>'; | |
if ( $ajax && $is_postback ) { | |
global $wp_scripts; | |
$form_string = apply_filters( | |
'gform_ajax_iframe_content', '<!DOCTYPE html><html><head>' . | |
"<meta charset='UTF-8' /></head><body class='GF_AJAX_POSTBACK'>" . $form_string . '</body></html>' | |
); | |
} | |
if ( $ajax && ! $is_postback ) { | |
$spinner_url = gf_apply_filters( 'gform_ajax_spinner_url', $form_id, GFCommon::get_base_url() . '/images/spinner.gif', $form ); | |
$scroll_position = array( 'default' => '', 'confirmation' => '' ); | |
if ( $use_anchor !== false ) { | |
$scroll_position['default'] = is_numeric( $use_anchor ) ? 'jQuery(document).scrollTop(' . intval( $use_anchor ) . ');' : "jQuery(document).scrollTop(jQuery('#gform_wrapper_{$form_id}').offset().top);"; | |
$scroll_position['confirmation'] = is_numeric( $use_anchor ) ? 'jQuery(document).scrollTop(' . intval( $use_anchor ) . ');' : "jQuery(document).scrollTop(jQuery('#gforms_confirmation_message_{$form_id}').offset().top);"; | |
} | |
$iframe_style = defined( 'GF_DEBUG' ) && GF_DEBUG ? 'display:block;width:600px;height:300px;border:1px solid #eee;' : 'display:none;width:0px;height:0px;'; | |
$is_html5 = RGFormsModel::is_html5_enabled(); | |
$iframe_title = $is_html5 ? " title='Ajax Frame'" : ''; | |
$form_string .= " | |
<iframe style='{$iframe_style}' src='about:blank' name='gform_ajax_frame_{$form_id}' id='gform_ajax_frame_{$form_id}'" . $iframe_title . "></iframe> | |
<script type='text/javascript'>" . apply_filters( 'gform_cdata_open', '' ) . '' . | |
'jQuery(document).ready(function($){' . | |
"gformInitSpinner( {$form_id}, '{$spinner_url}' );" . | |
"jQuery('#gform_ajax_frame_{$form_id}').load( function(){" . | |
"var contents = jQuery(this).contents().find('*').html();" . | |
"var is_postback = contents.indexOf('GF_AJAX_POSTBACK') >= 0;" . | |
'if(!is_postback){return;}' . | |
"var form_content = jQuery(this).contents().find('#gform_wrapper_{$form_id}');" . | |
"var is_confirmation = jQuery(this).contents().find('#gform_confirmation_wrapper_{$form_id}').length > 0;" . | |
"var is_redirect = contents.indexOf('gformRedirect(){') >= 0;" . | |
'var is_form = form_content.length > 0 && ! is_redirect && ! is_confirmation;' . | |
'if(is_form){' . | |
"jQuery('#gform_wrapper_{$form_id}').html(form_content.html());" . | |
"setTimeout( function() { /* delay the scroll by 50 milliseconds to fix a bug in chrome */ {$scroll_position['default']} }, 50 );" . | |
"if(window['gformInitDatepicker']) {gformInitDatepicker();}" . | |
"if(window['gformInitPriceFields']) {gformInitPriceFields();}" . | |
"var current_page = jQuery('#gform_source_page_number_{$form_id}').val();" . | |
"gformInitSpinner( {$form_id}, '{$spinner_url}' );" . | |
"jQuery(document).trigger('gform_page_loaded', [{$form_id}, current_page]);" . | |
"window['gf_submitting_{$form_id}'] = false;" . | |
'}' . | |
'else if(!is_redirect){' . | |
"var confirmation_content = jQuery(this).contents().find('#gforms_confirmation_message_{$form_id}').html();" . | |
'if(!confirmation_content){' . | |
'confirmation_content = contents;' . | |
'}' . | |
'setTimeout(function(){' . | |
"jQuery('#gform_wrapper_{$form_id}').replaceWith('<' + 'div id=\'gforms_confirmation_message_{$form_id}\' class=\'gform_confirmation_message_{$form_id} gforms_confirmation_message\'' + '>' + confirmation_content + '<' + '/div' + '>');" . | |
"{$scroll_position['confirmation']}" . | |
"jQuery(document).trigger('gform_confirmation_loaded', [{$form_id}]);" . | |
"window['gf_submitting_{$form_id}'] = false;" . | |
'}, 50);' . | |
'}' . | |
'else{' . | |
"jQuery('#gform_{$form_id}').append(contents);" . | |
"if(window['gformRedirect']) {gformRedirect();}" . | |
'}' . | |
"jQuery(document).trigger('gform_post_render', [{$form_id}, current_page]);" . | |
'} );' . | |
'} );' . apply_filters( 'gform_cdata_close', '' ) . '</script>'; | |
} | |
$is_first_load = ! $is_postback; | |
if ( ( ! $ajax || $is_first_load ) ) { | |
self::register_form_init_scripts( $form, $field_values, $ajax ); | |
if ( apply_filters( 'gform_init_scripts_footer', false ) ) { | |
add_action( 'wp_footer', create_function( '', 'GFFormDisplay::footer_init_scripts(' . $form['id'] . ');' ), 20 ); | |
add_action( 'gform_preview_footer', create_function( '', 'GFFormDisplay::footer_init_scripts(' . $form['id'] . ');' ) ); | |
} else { | |
$form_string .= self::get_form_init_scripts( $form ); | |
$form_string .= "<script type='text/javascript'>" . apply_filters( 'gform_cdata_open', '' ) . " jQuery(document).ready(function(){jQuery(document).trigger('gform_post_render', [{$form_id}, {$current_page}]) } ); " . apply_filters( 'gform_cdata_close', '' ) . '</script>'; | |
} | |
} | |
return gf_apply_filters( 'gform_get_form_filter', $form_id, $form_string, $form ); | |
} else { | |
$progress_confirmation = ''; | |
//check admin setting for whether the progress bar should start at zero | |
$start_at_zero = rgars( $form, 'pagination/display_progressbar_on_confirmation' ); | |
$start_at_zero = apply_filters( 'gform_progressbar_start_at_zero', $start_at_zero, $form ); | |
//show progress bar on confirmation | |
if ( $start_at_zero && $has_pages && ! $is_admin && ( $form['confirmation']['type'] == 'message' && $form['pagination']['type'] == 'percentage' ) ) { | |
$progress_confirmation = self::get_progress_bar( $form, $form_id, $confirmation_message ); | |
if ( $ajax ) { | |
$progress_confirmation = apply_filters( 'gform_ajax_iframe_content', "<!DOCTYPE html><html><head><meta charset='UTF-8' /></head><body class='GF_AJAX_POSTBACK'>" . $progress_confirmation . '</body></html>' ); | |
} | |
} else { | |
//return regular confirmation message | |
if ( $ajax ) { | |
$progress_confirmation = apply_filters( 'gform_ajax_iframe_content', "<!DOCTYPE html><html><head><meta charset='UTF-8' /></head><body class='GF_AJAX_POSTBACK'>" . $confirmation_message . '</body></html>' ); | |
} else { | |
$progress_confirmation = $confirmation_message; | |
} | |
} | |
return $progress_confirmation; | |
} | |
} | |
public static function footer_init_scripts( $form_id ) { | |
global $_init_forms; | |
$form = RGFormsModel::get_form_meta( $form_id ); | |
$form_string = self::get_form_init_scripts( $form ); | |
$current_page = self::get_current_page( $form_id ); | |
$form_string .= "<script type='text/javascript'>" . apply_filters( 'gform_cdata_open', '' ) . " jQuery(document).ready(function(){jQuery(document).trigger('gform_post_render', [{$form_id}, {$current_page}]) } ); " . apply_filters( 'gform_cdata_close', '' ) . '</script>'; | |
/** | |
* A filter to allow modification of scripts that fire in the footer | |
* | |
* @param int $form_id The Form ID to filter through | |
* @param string $form_string Get the form scripts in a string | |
* @param array $form The Form object to filter through | |
* @param int $current_page The Current form page ID (If paging is enabled) | |
*/ | |
$form_string = gf_apply_filters( 'gform_footer_init_scripts_filter', $form_id, $form_string, $form, $current_page ); | |
if ( ! isset( $_init_forms[ $form_id ] ) ) { | |
echo $form_string; | |
if ( ! is_array( $_init_forms ) ) { | |
$_init_forms = array(); | |
} | |
$_init_forms[ $form_id ] = true; | |
} | |
} | |
public static function add_init_script( $form_id, $script_name, $location, $script ) { | |
$key = $script_name . '_' . $location; | |
if ( ! isset( self::$init_scripts[ $form_id ] ) ) { | |
self::$init_scripts[ $form_id ] = array(); | |
} | |
//add script if it hasn't been added before | |
if ( ! array_key_exists( $key, self::$init_scripts[ $form_id ] ) ) { | |
self::$init_scripts[ $form_id ][ $key ] = array( 'location' => $location, 'script' => $script ); | |
} | |
} | |
private static function get_form_button( $form_id, $button_input_id, $button, $default_text, $class, $alt, $target_page_number, $onclick = '' ) { | |
$tabindex = GFCommon::get_tabindex(); | |
$input_type = 'submit'; | |
if ( ! empty( $target_page_number ) ) { | |
$onclick = "onclick='jQuery(\"#gform_target_page_number_{$form_id}\").val(\"{$target_page_number}\"); {$onclick} jQuery(\"#gform_{$form_id}\").trigger(\"submit\",[true]); '"; | |
$input_type = 'button'; | |
} else { | |
// prevent multiple form submissions when button is pressed multiple times | |
if ( GFFormsModel::is_html5_enabled() ) { | |
$set_submitting = "if( !jQuery(\"#gform_{$form_id}\")[0].checkValidity || jQuery(\"#gform_{$form_id}\")[0].checkValidity()){window[\"gf_submitting_{$form_id}\"]=true;}"; | |
} else { | |
$set_submitting = "window[\"gf_submitting_{$form_id}\"]=true;"; | |
} | |
$onclick_submit = $button['type'] == 'link' ? "jQuery(\"#gform_{$form_id}\").trigger(\"submit\",[true]);" : ''; | |
$onclick = "onclick='if(window[\"gf_submitting_{$form_id}\"]){return false;} {$set_submitting} {$onclick} {$onclick_submit}'"; | |
} | |
if ( $button['type'] == 'text' || $button['type'] == 'link' || empty( $button['imageUrl'] ) ) { | |
$button_text = ! empty( $button['text'] ) ? $button['text'] : $default_text; | |
if ( $button['type'] == 'link' ) { | |
$button_input = "<a href='javascript:void(0);' id='{$button_input_id}_link' class='{$class}' {$tabindex} {$onclick}>{$button_text}</a>"; | |
} else { | |
$class .= ' button'; | |
$button_input = "<input type='{$input_type}' id='{$button_input_id}' class='{$class}' value='" . esc_attr( $button_text ) . "' {$tabindex} {$onclick} />"; | |
} | |
} else { | |
$imageUrl = $button['imageUrl']; | |
$class .= ' gform_image_button'; | |
$button_input = "<input type='image' src='{$imageUrl}' id='{$button_input_id}' class='{$class}' alt='{$alt}' {$tabindex} {$onclick} />"; | |
} | |
return $button_input; | |
} | |
private static function gform_footer( $form, $class, $ajax, $field_values, $previous_button, $display_title, $display_description, $tabindex = 1 ) { | |
$form_id = absint( $form['id'] ); | |
$footer = " | |
<div class='" . esc_attr( $class ) . "'>"; | |
$button_input = self::get_form_button( $form['id'], "gform_submit_button_{$form['id']}", $form['button'], __( 'Submit', 'gravityforms' ), 'gform_button', __( 'Submit', 'gravityforms' ), 0 ); | |
$button_input = gf_apply_filters( 'gform_submit_button', $form_id, $button_input, $form ); | |
$save_button = rgars( $form, 'save/enabled' ) ? self::get_form_button( $form_id, "gform_save_{$form_id}", $form['save']['button'], rgars( $form, 'save/button/text' ), 'gform_save_link', rgars( $form, 'save/button/text' ), 0, "jQuery(\"#gform_save_{$form_id}\").val(1);" ) : ''; | |
$footer .= $previous_button . ' ' . $button_input . ' ' . $save_button; | |
$tabindex = (int) $tabindex; | |
if ( $ajax ) { | |
$footer .= "<input type='hidden' name='gform_ajax' value='" . esc_attr( "form_id={$form_id}&title={$display_title}&description={$display_description}&tabindex={$tabindex}" ) . "' />"; | |
} | |
$current_page = self::get_current_page( $form_id ); | |
$next_page = $current_page + 1; | |
$next_page = $next_page > self::get_max_page_number( $form ) ? 0 : $next_page; | |
$field_values_str = is_array( $field_values ) ? http_build_query( $field_values ) : $field_values; | |
$files_input = ''; | |
if ( GFCommon::has_multifile_fileupload_field( $form ) || ! empty( RGFormsModel::$uploaded_files[ $form_id ] ) ) { | |
$files = ! empty( RGFormsModel::$uploaded_files[ $form_id ] ) ? GFCommon::json_encode( RGFormsModel::$uploaded_files[ $form_id ] ) : ''; | |
$files_input = "<input type='hidden' name='gform_uploaded_files' id='gform_uploaded_files_{$form_id}' value='" . str_replace( "'", ''', $files ) . "' />"; | |
} | |
$save_inputs = ''; | |
if ( rgars( $form, 'save/enabled' ) ) { | |
$resume_token = isset( $_POST['gform_resume_token'] ) ? $_POST['gform_resume_token'] : rgget( 'gf_token' ); | |
$resume_token = sanitize_key( $resume_token ); | |
$save_inputs = "<input type='hidden' class='gform_hidden' name='gform_save' id='gform_save_{$form_id}' value='' /> | |
<input type='hidden' class='gform_hidden' name='gform_resume_token' id='gform_resume_token_{$form_id}' value='{$resume_token}' />"; | |
} | |
if ( rgar( $form, 'requireLogin' ) ) { | |
$footer .= wp_nonce_field( 'gform_submit_' . $form_id, '_gform_submit_nonce_' . $form_id, true, false ); | |
} | |
$unique_id = isset( self::$submission[ $form_id ] ) && rgar( self::$submission[ $form_id ], 'resuming_incomplete_submission' ) == true ? rgar( GFFormsModel::$unique_ids, $form_id ) : GFFormsModel::get_form_unique_id( $form_id ); | |
$footer .= " | |
<input type='hidden' class='gform_hidden' name='is_submit_{$form_id}' value='1' /> | |
<input type='hidden' class='gform_hidden' name='gform_submit' value='{$form_id}' /> | |
{$save_inputs} | |
<input type='hidden' class='gform_hidden' name='gform_unique_id' value='" . esc_attr( $unique_id ) . "' /> | |
<input type='hidden' class='gform_hidden' name='state_{$form_id}' value='" . self::get_state( $form, $field_values ) . "' /> | |
<input type='hidden' class='gform_hidden' name='gform_target_page_number_{$form_id}' id='gform_target_page_number_{$form_id}' value='" . esc_attr( $next_page ) . "' /> | |
<input type='hidden' class='gform_hidden' name='gform_source_page_number_{$form_id}' id='gform_source_page_number_{$form_id}' value='" . esc_attr( $current_page ) . "' /> | |
<input type='hidden' name='gform_field_values' value='" . esc_attr( $field_values_str ) . "' /> | |
{$files_input} | |
</div>"; | |
return $footer; | |
} | |
public static function get_max_page_number( $form ) { | |
$page_number = 0; | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->type == 'page' ) { | |
$page_number ++; | |
} | |
} | |
return $page_number == 0 ? 0 : $page_number + 1; | |
} | |
private static function get_honeypot_field( $form ) { | |
$max_id = self::get_max_field_id( $form ); | |
$labels = self::get_honeypot_labels(); | |
$properties = array( 'type' => 'honeypot', 'label' => $labels[ rand( 0, 3 ) ], 'id' => $max_id + 1, 'cssClass' => 'gform_validation_container', 'description' => __( 'This field is for validation purposes and should be left unchanged.', 'gravityforms' ) ); | |
$field = GF_Fields::create( $properties ); | |
return $field; | |
} | |
private static function get_max_field_id( $form ) { | |
$max = 0; | |
foreach ( $form['fields'] as $field ) { | |
if ( floatval( $field->id ) > $max ) { | |
$max = floatval( $field->id ); | |
} | |
} | |
return $max; | |
} | |
private static function get_honeypot_labels() { | |
return array( 'Name', 'Email', 'Phone', 'Comments' ); | |
} | |
/** | |
* Used to determine the required validation result. | |
* | |
* @param GF_Field $field | |
* @param int $form_id | |
* | |
* @return bool | |
*/ | |
public static function is_empty( $field, $form_id = 0 ) { | |
if ( empty( $_POST[ 'is_submit_' . $field->formId ] ) ) { | |
return true; | |
} | |
return $field->is_value_submission_empty( $form_id ); | |
} | |
private static function validate_honeypot( $form ) { | |
$honeypot_id = self::get_max_field_id( $form ); | |
return rgempty( "input_{$honeypot_id}" ); | |
} | |
public static function handle_submission( $form, &$lead, $ajax = false ){ | |
$lead_id = gf_apply_filters( 'gform_entry_id_pre_save_lead', $form['id'], null, $form ); | |
if ( ! empty( $lead_id ) ) { | |
if ( empty( $lead ) ) { | |
$lead = array(); | |
} | |
$lead['id'] = $lead_id; | |
} | |
//creating entry in DB | |
RGFormsModel::save_lead( $form, $lead ); | |
//reading entry that was just saved | |
$lead = RGFormsModel::get_lead( $lead['id'] ); | |
$lead = GFFormsModel::set_entry_meta( $lead, $form ); | |
//if Akismet plugin is installed, run lead through Akismet and mark it as Spam when appropriate | |
$is_spam = GFCommon::akismet_enabled( $form['id'] ) && GFCommon::is_akismet_spam( $form, $lead ); | |
/** | |
* A filter to set if an entry is spam | |
* | |
* @param int $form['id'] The Form ID to filter through (take directly from the form object) | |
* @param bool $is_spam True or false to filter if the entry is spam | |
* @param array $form The Form object to filer through | |
* @param array $lead The Lead object to filter through | |
*/ | |
$is_spam = gf_apply_filters( 'gform_entry_is_spam', $form['id'], $is_spam, $form, $lead ); | |
if ( GFCommon::spam_enabled( $form['id'] ) ) { | |
GFCommon::log_debug( 'GFFormDisplay::handle_submission(): Akismet integration enabled OR gform_entry_is_spam hook in use.' ); | |
$log_is_spam = $is_spam ? 'Yes' : 'No'; | |
GFCommon::log_debug( "GFFormDisplay::handle_submission(): Is entry considered spam? {$log_is_spam}." ); | |
} | |
if ( $is_spam ) { | |
//marking entry as spam | |
RGFormsModel::update_lead_property( $lead['id'], 'status', 'spam', false, true ); | |
$lead['status'] = 'spam'; | |
} | |
do_action( 'gform_entry_created', $lead, $form ); | |
$lead = gf_apply_filters( 'gform_entry_post_save', $form['id'], $lead, $form ); | |
RGFormsModel::set_current_lead( $lead ); | |
if ( ! $is_spam ) { | |
GFCommon::create_post( $form, $lead ); | |
//send notifications | |
GFCommon::send_form_submission_notifications( $form, $lead ); | |
} | |
self::clean_up_files( $form ); | |
// remove incomplete submission and purge expired | |
if ( rgars( $form, 'save/enabled' ) ) { | |
GFFormsModel::delete_incomplete_submission( rgpost( 'gform_resume_token' ) ); | |
GFFormsModel::purge_expired_incomplete_submissions(); | |
} | |
//display confirmation message or redirect to confirmation page | |
return self::handle_confirmation( $form, $lead, $ajax ); | |
} | |
public static function clean_up_files( $form ) { | |
$unique_form_id = rgpost( 'gform_unique_id' ); | |
if ( ! ctype_alnum( $unique_form_id ) ) { | |
return false; | |
} | |
$target_path = RGFormsModel::get_upload_path( $form['id'] ) . '/tmp/'; | |
$filename = $target_path . $unique_form_id . '_input_*'; | |
$files = glob( $filename ); | |
if ( is_array( $files ) ) { | |
array_map( 'unlink', $files ); | |
} | |
// clean up files from abandoned submissions older than 48 hours (30 days if Save and Continue is enabled) | |
$files = glob( $target_path . '*' ); | |
if ( is_array( $files ) ) { | |
$seconds_in_day = 24 * 60 * 60; | |
/** | |
* Filter through the experiation days of a incomplete form submission | |
*/ | |
$lifespan = rgars( $form, 'save/enabled' ) ? $expiration_days = apply_filters( 'gform_incomplete_submissions_expiration_days', 30 ) * $seconds_in_day : 2 * $seconds_in_day; | |
foreach ( $files as $file ) { | |
if ( is_file( $file ) && time() - filemtime( $file ) >= $lifespan ) { | |
unlink( $file ); | |
} | |
} | |
} | |
} | |
public static function handle_confirmation( $form, $lead, $ajax = false ) { | |
GFCommon::log_debug( 'GFFormDisplay::handle_confirmation(): Sending confirmation.' ); | |
//run the function to populate the legacy confirmation format to be safe | |
$form = self::update_confirmation( $form, $lead ); | |
if ( $form['confirmation']['type'] == 'message' ) { | |
$default_anchor = self::has_pages( $form ) ? 1 : 0; | |
$anchor = gf_apply_filters( 'gform_confirmation_anchor', $form['id'], $default_anchor ) ? "<a id='gf_{$form['id']}' class='gform_anchor' ></a>" : ''; | |
$nl2br = rgar( $form['confirmation'], 'disableAutoformat' ) ? false : true; | |
$cssClass = rgar( $form, 'cssClass' ); | |
$confirmation = empty( $form['confirmation']['message'] ) ? "{$anchor} " : "{$anchor}<div id='gform_confirmation_wrapper_{$form['id']}' class='gform_confirmation_wrapper {$cssClass}'><div id='gform_confirmation_message_{$form['id']}' class='gform_confirmation_message_{$form['id']} gform_confirmation_message'>" . GFCommon::replace_variables( $form['confirmation']['message'], $form, $lead, false, true, $nl2br ) . '</div></div>'; | |
} else { | |
if ( ! empty( $form['confirmation']['pageId'] ) ) { | |
$url = get_permalink( $form['confirmation']['pageId'] ); | |
} else { | |
$url = GFCommon::replace_variables( trim( $form['confirmation']['url'] ), $form, $lead, false, true, true, 'text' ); | |
} | |
$url_info = parse_url( $url ); | |
$query_string = rgar( $url_info, 'query' ); | |
$dynamic_query = GFCommon::replace_variables( trim( $form['confirmation']['queryString'] ), $form, $lead, true, false, false, 'text' ); | |
$dynamic_query = str_replace( array( "\r", "\n" ), '', $dynamic_query ); | |
$query_string .= rgempty( 'query', $url_info ) || empty( $dynamic_query ) ? $dynamic_query : '&' . $dynamic_query; | |
if ( ! empty( $url_info['fragment'] ) ) { | |
$query_string .= '#' . rgar( $url_info, 'fragment' ); | |
} | |
$url = isset( $url_info['scheme'] ) ? $url_info['scheme'] : 'http'; | |
$url .= '://' . rgar( $url_info, 'host' ); | |
if ( ! empty( $url_info['port'] ) ) { | |
$url .= ':' . rgar( $url_info, 'port' ); | |
} | |
$url .= rgar( $url_info, 'path' ); | |
if ( ! empty( $query_string ) ) { | |
$url .= "?{$query_string}"; | |
} | |
if ( headers_sent() || $ajax ) { | |
//Perform client side redirect for AJAX forms, of if headers have already been sent | |
$confirmation = self::get_js_redirect_confirmation( $url, $ajax ); | |
} else { | |
$confirmation = array( 'redirect' => $url ); | |
} | |
} | |
$confirmation = gf_apply_filters( 'gform_confirmation', $form['id'], $confirmation, $form, $lead, $ajax ); | |
if ( ! is_array( $confirmation ) ) { | |
$confirmation = GFCommon::gform_do_shortcode( $confirmation ); //enabling shortcodes | |
} else if ( headers_sent() || $ajax ) { | |
//Perform client side redirect for AJAX forms, of if headers have already been sent | |
$confirmation = self::get_js_redirect_confirmation( $confirmation['redirect'], $ajax ); //redirecting via client side | |
} | |
GFCommon::log_debug( 'GFFormDisplay::handle_confirmation(): Confirmation => ' . print_r( $confirmation, true ) ); | |
return $confirmation; | |
} | |
private static function get_js_redirect_confirmation( $url, $ajax ) { | |
$confirmation = "<script type=\"text/javascript\">" . apply_filters( 'gform_cdata_open', '' ) . " function gformRedirect(){document.location.href='$url';}"; | |
if ( ! $ajax ) { | |
$confirmation .= 'gformRedirect();'; | |
} | |
$confirmation .= apply_filters( 'gform_cdata_close', '' ) . '</script>'; | |
return $confirmation; | |
} | |
public static function send_emails( $form, $lead ) { | |
_deprecated_function( 'send_emails', '1.7', 'GFCommon::send_form_submission_notifications' ); | |
GFCommon::send_form_submission_notifications( $form, $lead ); | |
} | |
public static function validate( &$form, $field_values, $page_number = 0, &$failed_validation_page = 0 ) { | |
$form = gf_apply_filters( 'gform_pre_validation', $form['id'], $form ); | |
// validate form schedule | |
if ( self::validate_form_schedule( $form ) ) { | |
return false; | |
} | |
// validate entry limit | |
if ( self::validate_entry_limit( $form ) ) { | |
return false; | |
} | |
// Prevent tampering with the submitted form | |
if ( empty( $_POST[ 'is_submit_' . $form['id'] ] ) ) { | |
return false; | |
} | |
$is_valid = true; | |
foreach ( $form['fields'] as &$field ) { | |
/* @var GF_Field $field */ | |
//If a page number is specified, only validates fields that are on current page | |
$field_in_other_page = $page_number > 0 && $field->pageNumber != $page_number; | |
//validate fields with 'no duplicate' functionality when they are present on pages before the current page. | |
$validate_duplicate_feature = $field->noDuplicates && $page_number > 0 && $field->pageNumber <= $page_number; | |
if ( $field_in_other_page && ! $validate_duplicate_feature ) { | |
continue; | |
} | |
//ignore validation if field is hidden or admin only | |
if ( RGFormsModel::is_field_hidden( $form, $field, $field_values ) || $field->adminOnly ) { | |
$field->is_field_hidden = true; | |
continue; | |
} | |
$value = RGFormsModel::get_field_value( $field ); | |
$input_type = RGFormsModel::get_input_type( $field ); | |
//display error message if field is marked as required and the submitted value is empty | |
if ( $field->isRequired && self::is_empty( $field, $form['id'] ) ) { | |
$field->failed_validation = true; | |
$field->validation_message = empty( $field->errorMessage ) ? __( 'This field is required.', 'gravityforms' ) : $field->errorMessage; | |
} //display error if field does not allow duplicates and the submitted value already exists | |
else if ( $field->noDuplicates && RGFormsModel::is_duplicate( $form['id'], $field, $value ) ) { | |
$field->failed_validation = true; | |
//set page number so the failed field displays if on multi-page form | |
$failed_validation_page = $field->pageNumber; | |
switch ( $input_type ) { | |
case 'date' : | |
$default_message = __( 'This date has already been taken. Please select a new date.', 'gravityforms' ); | |
break; | |
default: | |
$default_message = is_array( $value ) ? __( 'This field requires a unique entry and the values you entered have been already been used.', 'gravityforms' ) : | |
sprintf( __( "This field requires a unique entry and '%s' has already been used", 'gravityforms' ), $value ); | |
break; | |
} | |
$field->validation_message = gf_apply_filters( 'gform_duplicate_message', $form['id'], $default_message, $form, $field, $value ); | |
} else { | |
if ( self::failed_state_validation( $form['id'], $field, $value ) ) { | |
$field->failed_validation = true; | |
$field->validation_message = in_array( $field->inputType, array( 'singleproduct', 'singleshipping', 'hiddenproduct' ) ) ? __( 'Please enter a valid value.', 'gravityforms' ) : __( 'Invalid selection. Please select one of the available choices.', 'gravityforms' ); | |
} else { | |
$field->validate( $value, $form ); | |
} | |
} | |
$custom_validation_result = gf_apply_filters( 'gform_field_validation', array( | |
$form['id'], | |
$field->id | |
), array( | |
'is_valid' => $field->failed_validation ? false : true, | |
'message' => $field->validation_message | |
), $value, $form, $field ); | |
$field->failed_validation = rgar( $custom_validation_result, 'is_valid' ) ? false : true; | |
$field->validation_message = rgar( $custom_validation_result, 'message' ); | |
if ( $field->failed_validation ) { | |
$is_valid = false; | |
} | |
} | |
$is_last_page = self::get_target_page( $form, $page_number, $field_values ) == '0'; | |
if ( $is_valid && $is_last_page && self::is_form_empty( $form ) ) { | |
foreach ( $form['fields'] as &$field ) { | |
$field->failed_validation = true; | |
$field->validation_message = esc_html__( 'At least one field must be filled out', 'gravityforms' ); | |
$is_valid = false; | |
unset( $field->is_field_hidden ); | |
} | |
} | |
$validation_result = gf_apply_filters( 'gform_validation', $form['id'], array( 'is_valid' => $is_valid, 'form' => $form, 'failed_validation_page' => $failed_validation_page ) ); | |
$is_valid = $validation_result['is_valid']; | |
$form = $validation_result['form']; | |
$failed_validation_page = $validation_result['failed_validation_page']; | |
return $is_valid; | |
} | |
public static function is_form_empty( $form ) { | |
foreach ( $form['fields'] as $field ) { | |
if ( ! self::is_empty( $field, $form['id'] ) && ! $field->is_field_hidden ) { | |
return false; | |
} | |
} | |
return true; | |
} | |
public static function failed_state_validation( $form_id, $field, $value ) { | |
global $_gf_state; | |
//if field can be populated dynamically, disable state validation | |
if ( $field->allowsPrepopulate ) { | |
return false; | |
} else if ( ! GFCommon::is_product_field( $field->type && $field->type != 'donation' ) ) { | |
return false; | |
} else if ( ! in_array( $field->inputType, array( 'singleshipping', 'singleproduct', 'hiddenproduct', 'checkbox', 'radio', 'select' ) ) ) { | |
return false; | |
} | |
if ( ! isset( $_gf_state ) ) { | |
$state = json_decode( base64_decode( $_POST[ "state_{$form_id}" ] ), true ); | |
if ( ! $state || sizeof( $state ) != 2 ) { | |
return true; | |
} | |
//making sure state wasn't tampered with by validating checksum | |
$checksum = wp_hash( crc32( $state[0] ) ); | |
if ( $checksum !== $state[1] ) { | |
return true; | |
} | |
$_gf_state = json_decode( $state[0], true ); | |
} | |
if ( ! is_array( $value ) ) { | |
$value = array( $field->id => $value ); | |
} | |
foreach ( $value as $key => $input_value ) { | |
$state = isset( $_gf_state[ $key ] ) ? $_gf_state[ $key ] : false; | |
//converting price to a number for single product fields and single shipping fields | |
if ( ( in_array( $field->inputType, array( 'singleproduct', 'hiddenproduct' ) ) && $key == $field->id . '.2' ) || $field->inputType == 'singleshipping' ) { | |
$input_value = GFCommon::to_number( $input_value ); | |
} | |
$sanitized_input_value = wp_kses( $input_value, wp_kses_allowed_html( 'post' ) ); | |
$hash = wp_hash( $input_value ); | |
$sanitized_hash = wp_hash( $sanitized_input_value ); | |
$fails_hash = strlen( $input_value ) > 0 && $state !== false && ( ( is_array( $state ) && ! in_array( $hash, $state ) ) || ( ! is_array( $state ) && $hash != $state ) ); | |
$fails_sanitized_hash = strlen( $sanitized_input_value ) > 0 && $state !== false && ( ( is_array( $state ) && ! in_array( $sanitized_hash, $state ) ) || ( ! is_array( $state ) && $sanitized_hash != $state ) ); | |
if ( $fails_hash && $fails_sanitized_hash ) { | |
return true; | |
} | |
} | |
return false; | |
} | |
public static function enqueue_scripts() { | |
global $wp_query; | |
if ( isset( $wp_query->posts ) && is_array( $wp_query->posts ) ) { | |
foreach ( $wp_query->posts as $post ) { | |
$forms = self::get_embedded_forms( $post->post_content, $ajax ); | |
foreach ( $forms as $form ) { | |
if ( isset( $form['id'] ) ) { | |
self::enqueue_form_scripts( $form, $ajax ); | |
} | |
} | |
} | |
} | |
} | |
public static function get_embedded_forms( $post_content, &$ajax ) { | |
$forms = array(); | |
if ( preg_match_all( '/\[gravityform[s]? +.*?((id=.+?)|(name=.+?))\]/is', $post_content, $matches, PREG_SET_ORDER ) ) { | |
$ajax = false; | |
foreach ( $matches as $match ) { | |
//parsing shortcode attributes | |
$attr = shortcode_parse_atts( $match[1] ); | |
$form_id = rgar( $attr, 'id' ); | |
if ( ! is_numeric( $form_id ) ) { | |
$form_id = RGFormsModel::get_form_id( rgar( $attr, 'name' ) ); | |
} | |
if ( ! empty( $form_id ) ){ | |
$forms[] = RGFormsModel::get_form_meta( $form_id ); | |
$ajax = isset( $attr['ajax'] ) && strtolower( substr( $attr['ajax'], 0, 4 ) ) == 'true'; | |
} | |
} | |
} | |
return $forms; | |
} | |
public static function enqueue_form_scripts( $form, $ajax = false ) { | |
// adding pre enqueue scripts hook so that scripts can be added first if a need exists | |
/** | |
* Fires before any scripts are enqueued (form specific using the ID as well) | |
* | |
* @param array $form The Form Object | |
* @param bool $ajax Whether AJAX is on or off (True or False) | |
*/ | |
gf_do_action( 'gform_pre_enqueue_scripts', $form['id'], $form, $ajax ); | |
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; | |
if ( ! get_option( 'rg_gforms_disable_css' ) ) { | |
wp_enqueue_style( 'gforms_reset_css', GFCommon::get_base_url() . "/css/formreset{$min}.css", null, GFCommon::$version ); | |
if ( self::has_datepicker_field( $form ) ) { | |
wp_enqueue_style( 'gforms_datepicker_css', GFCommon::get_base_url() . "/css/datepicker{$min}.css", null, GFCommon::$version ); | |
} | |
wp_enqueue_style( 'gforms_formsmain_css', GFCommon::get_base_url() . "/css/formsmain{$min}.css", null, GFCommon::$version ); | |
wp_enqueue_style( 'gforms_ready_class_css', GFCommon::get_base_url() . "/css/readyclass{$min}.css", null, GFCommon::$version ); | |
wp_enqueue_style( 'gforms_browsers_css', GFCommon::get_base_url() . "/css/browsers{$min}.css", null, GFCommon::$version ); | |
if ( is_rtl() ) { | |
wp_enqueue_style( 'gforms_rtl_css', GFCommon::get_base_url() . "/css/rtl{$min}.css", null, GFCommon::$version ); | |
} | |
} | |
if ( self::has_conditional_logic( $form ) ) { | |
wp_enqueue_script( 'gform_conditional_logic' ); | |
} | |
if ( self::has_datepicker_field( $form ) ) { | |
wp_enqueue_script( 'gform_datepicker_init' ); | |
} | |
if ( $ajax || self::has_price_field( $form ) || self::has_password_strength( $form ) || GFCommon::has_list_field( $form ) || GFCommon::has_credit_card_field( $form ) || self::has_conditional_logic( $form ) || self::has_currency_format_number_field( $form ) || self::has_calculation_field( $form ) ) { | |
wp_enqueue_script( 'gform_gravityforms' ); | |
} | |
if ( GFCommon::has_multifile_fileupload_field( $form ) ) { | |
wp_enqueue_script( 'plupload-all' ); | |
GFCommon::localize_gform_gravityforms_multifile(); | |
} | |
if ( self::has_enhanced_dropdown( $form ) || self::has_pages( $form ) || self::has_fileupload_field( $form ) ) { | |
wp_enqueue_script( 'gform_json' ); | |
wp_enqueue_script( 'gform_gravityforms' ); | |
} | |
if ( self::has_character_counter( $form ) ) { | |
wp_enqueue_script( 'gform_textarea_counter' ); | |
} | |
if ( self::has_input_mask( $form ) ) { | |
wp_enqueue_script( 'gform_masked_input' ); | |
} | |
if ( self::has_enhanced_dropdown( $form ) && ! wp_script_is( 'chosen' ) ) { | |
wp_enqueue_script( 'gform_chosen' ); | |
} | |
if ( self::has_enhanced_dropdown( $form ) ) { | |
if ( wp_script_is( 'chosen', 'registered' ) ) { | |
wp_enqueue_script( 'chosen' ); | |
} else { | |
wp_enqueue_script( 'gform_chosen' ); | |
} | |
} | |
if ( self::has_placeholder( $form ) ) { | |
wp_enqueue_script( 'gform_placeholder' ); | |
} | |
gf_do_action( 'gform_enqueue_scripts', $form['id'], $form, $ajax ); | |
// enqueue jQuery every time form is displayed to allow 'gform_post_render' js hook | |
// to be available to users even when GF is not using it | |
wp_enqueue_script( 'jquery' ); | |
} | |
private static $printed_scripts = array(); | |
public static function print_form_scripts( $form, $ajax ) { | |
if ( ! get_option( 'rg_gforms_disable_css' ) ) { | |
if ( ! wp_style_is( 'gforms_css' ) ) { | |
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; | |
wp_enqueue_style( 'gforms_reset_css', GFCommon::get_base_url() . "/css/formreset{$min}.css", null, GFCommon::$version ); | |
wp_print_styles( array( 'gforms_reset_css' ) ); | |
wp_enqueue_style( 'gforms_formsmain_css', GFCommon::get_base_url() . "/css/formsmain{$min}.css", null, GFCommon::$version ); | |
wp_print_styles( array( 'gforms_formsmain_css' ) ); | |
wp_enqueue_style( 'gforms_ready_class_css', GFCommon::get_base_url() . "/css/readyclass{$min}.css", null, GFCommon::$version ); | |
wp_print_styles( array( 'gforms_ready_class_css' ) ); | |
wp_enqueue_style( 'gforms_browsers_css', GFCommon::get_base_url() . "/css/browsers{$min}.css", null, GFCommon::$version ); | |
wp_print_styles( array( 'gforms_browsers_css' ) ); | |
if ( self::has_datepicker_field( $form ) ) { | |
wp_enqueue_style( 'gforms_datepicker_css', GFCommon::get_base_url() . "/css/datepicker{$min}.css", null, GFCommon::$version ); | |
wp_print_styles( array( 'gforms_datepicker_css' ) ); | |
} | |
if ( is_rtl() ) { | |
wp_enqueue_style( 'gforms_rtl_css', GFCommon::get_base_url() . "/css/rtl{$min}.css", null, GFCommon::$version ); | |
wp_print_styles( array( 'gforms_rtl_css' ) ); | |
} | |
} | |
} | |
$scripts = array(); | |
if ( ( $ajax || self::has_enhanced_dropdown( $form ) || self::has_price_field( $form ) || self::has_password_strength( $form ) || self::has_pages( $form ) || self::has_password_strength( $form ) || GFCommon::has_list_field( $form ) || GFCommon::has_credit_card_field( $form ) || self::has_calculation_field( $form ) ) && ! wp_script_is( 'gform_gravityforms' ) ) { | |
$scripts[] = 'gform_gravityforms'; | |
} | |
if ( self::has_conditional_logic( $form ) && ! wp_script_is( 'gform_conditional_logic' ) ) { | |
$scripts[] = 'gform_conditional_logic'; | |
} | |
if ( self::has_datepicker_field( $form ) && ! wp_script_is( 'gform_datepicker_init' ) ) { | |
$scripts[] = 'gform_datepicker_init'; | |
} | |
if ( self::has_pages( $form ) && ! wp_script_is( 'gform_json' ) ) { | |
$scripts[] = 'gform_json'; | |
} | |
if ( self::has_character_counter( $form ) && ! wp_script_is( 'gform_textarea_counter' ) ) { | |
$scripts[] = 'gform_textarea_counter'; | |
} | |
if ( self::has_input_mask( $form ) && ! wp_script_is( 'gform_masked_input' ) ) { | |
$scripts[] = 'gform_masked_input'; | |
} | |
if ( self::has_enhanced_dropdown( $form ) && ! wp_script_is( 'gform_chosen' ) && ! wp_script_is( 'chosen' ) ) { | |
if ( wp_script_is( 'chosen', 'registered' ) ) { | |
$scripts[] = 'chosen'; | |
} else { | |
$scripts[] = 'gform_chosen'; | |
} | |
} | |
if ( ! wp_script_is( 'jquery' ) ) { | |
$scripts[] = 'jquery'; | |
} | |
foreach ( $scripts as $script ) { | |
wp_enqueue_script( $script ); | |
} | |
wp_print_scripts( $scripts ); | |
if ( wp_script_is( 'gform_gravityforms' ) ) { | |
echo '<script type="text/javascript"> ' . GFCommon::gf_global( false ) . ' </script>'; | |
} | |
} | |
public static function has_conditional_logic( $form ) { | |
$has_conditional_logic = self::has_conditional_logic_legwork( $form ); | |
/** | |
* A filter that runs through a form that has conditional logic | |
* | |
* @param bool $has_conditional_logic True or False if the user has conditional logic active in their current form settings | |
* @param array $form The Current form object | |
*/ | |
return apply_filters( 'gform_has_conditional_logic', $has_conditional_logic, $form ); | |
} | |
private static function has_conditional_logic_legwork( $form ) { | |
if ( empty( $form ) ) { | |
return false; | |
} | |
if ( isset( $form['button']['conditionalLogic'] ) ) { | |
return true; | |
} | |
if ( is_array( rgar( $form, 'fields' ) ) ) { | |
foreach ( rgar( $form, 'fields' ) as $field ) { | |
if ( ! empty( $field->conditionalLogic ) ) { | |
return true; | |
} else if ( isset( $field->nextButton ) && ! empty( $field->nextButton['conditionalLogic'] ) ) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
/** | |
* Get init script and all necessary data for conditional logic. | |
* | |
* @todo: Replace much of the field value retrieval with a get_original_value() method in GF_Field class. | |
* | |
* @param $form | |
* @param array $field_values | |
* | |
* @return string | |
*/ | |
private static function get_conditional_logic( $form, $field_values = array() ) { | |
$logics = ''; | |
$dependents = ''; | |
$fields_with_logic = array(); | |
$default_values = array(); | |
foreach ( $form['fields'] as $field ) { | |
/* @var GF_Field $field */ | |
//use section's logic if one exists | |
$section = RGFormsModel::get_section( $form, $field->id ); | |
$section_logic = ! empty( $section ) ? rgar( $section, 'conditionalLogic' ) : null; | |
$field_logic = $field->type != 'page' ? $field->conditionalLogic : null; //page break conditional logic will be handled during the next button click | |
$next_button_logic = ! empty( $field->nextButton ) && ! empty( $field->nextButton['conditionalLogic'] ) ? $field->nextButton['conditionalLogic'] : null; | |
if ( ! empty( $field_logic ) || ! empty( $next_button_logic ) ) { | |
$field_section_logic = array( 'field' => $field_logic, 'nextButton' => $next_button_logic, 'section' => $section_logic ); | |
$logics .= $field->id . ': ' . GFCommon::json_encode( $field_section_logic ) . ','; | |
$fields_with_logic[] = $field->id; | |
$peers = $field->type == 'section' ? GFCommon::get_section_fields( $form, $field->id ) : array( $field ); | |
$peer_ids = array(); | |
foreach ( $peers as $peer ) { | |
$peer_ids[] = $peer->id; | |
} | |
$dependents .= $field->id . ': ' . GFCommon::json_encode( $peer_ids ) . ','; | |
} | |
//-- Saving default values so that they can be restored when toggling conditional logic --- | |
$field_val = ''; | |
$input_type = $field->get_input_type(); | |
$inputs = $field->get_entry_inputs(); | |
//get parameter value if pre-populate is enabled | |
if ( $field->allowsPrepopulate ) { | |
if ( $input_type == 'checkbox' ) { | |
$field_val = RGFormsModel::get_parameter_value( $field->inputName, $field_values, $field ); | |
if ( ! is_array( $field_val ) ) { | |
$field_val = explode( ',', $field_val ); | |
} | |
} elseif ( is_array( $inputs ) ) { | |
$field_val = array(); | |
foreach ( $inputs as $input ) { | |
$field_val["input_{$input['id']}"] = RGFormsModel::get_parameter_value( rgar( $input, 'name' ), $field_values, $field ); | |
} | |
} elseif ( $input_type == 'time' ) { // maintained for backwards compatibility. The Time field now has an inputs array. | |
$parameter_val = RGFormsModel::get_parameter_value( $field->inputName, $field_values, $field ); | |
if ( ! empty( $parameter_val ) && preg_match( '/^(\d*):(\d*) ?(.*)$/', $parameter_val, $matches ) ) { | |
$field_val = array(); | |
$field_val[] = esc_attr( $matches[1] ); //hour | |
$field_val[] = esc_attr( $matches[2] ); //minute | |
$field_val[] = rgar( $matches, 3 ); //am or pm | |
} | |
} elseif ( $input_type == 'list' ) { | |
$parameter_val = RGFormsModel::get_parameter_value( $field->inputName, $field_values, $field ); | |
$field_val = is_array( $parameter_val ) ? $parameter_val : explode( ',', str_replace( '|', ',', $parameter_val ) ); | |
if ( is_array( rgar( $field_val, 0 ) ) ) { | |
$list_values = array(); | |
foreach ( $field_val as $row ) { | |
$list_values = array_merge( $list_values, array_values( $row ) ); | |
} | |
$field_val = $list_values; | |
} | |
} else { | |
$field_val = RGFormsModel::get_parameter_value( $field->inputName, $field_values, $field ); | |
} | |
} | |
//use default value if pre-populated value is empty | |
$field_val = $field->get_value_default_if_empty( $field_val ); | |
if ( is_array( $field->choices ) && $input_type != 'list' ) { | |
//radio buttons start at 0 and checkboxes start at 1 | |
$choice_index = $input_type == 'radio' ? 0 : 1; | |
$is_pricing_field = GFCommon::is_pricing_field( $field->type ); | |
foreach ( $field->choices as $choice ) { | |
if ( $input_type == 'checkbox' && ( $choice_index % 10 ) == 0 ){ | |
$choice_index++; | |
} | |
$is_prepopulated = is_array( $field_val ) ? in_array( $choice['value'], $field_val ) : $choice['value'] == $field_val; | |
$is_choice_selected = rgar( $choice, 'isSelected' ) || $is_prepopulated; | |
if ( $is_choice_selected && $input_type == 'select' ) { | |
$price = GFCommon::to_number( rgar( $choice, 'price' ) ) == false ? 0 : GFCommon::to_number( rgar( $choice, 'price' ) ); | |
$val = $is_pricing_field && $field->type != 'quantity' ? $choice['value'] . '|' . $price : $choice['value']; | |
$default_values[ $field->id ] = $val; | |
} elseif ( $is_choice_selected ) { | |
if ( ! isset( $default_values[ $field->id ] ) ) { | |
$default_values[ $field->id ] = array(); | |
} | |
$default_values[ $field->id ][] = "choice_{$form['id']}_{$field->id}_{$choice_index}"; | |
} | |
$choice_index ++; | |
} | |
} elseif ( ! empty( $field_val ) ) { | |
switch ( $input_type ) { | |
case 'date': | |
// for date fields; that are multi-input; and where the field value is a string | |
// (happens with prepop, default value will always be an array for multi-input date fields) | |
if ( is_array( $field->inputs ) && ( ! is_array( $field_val ) || ! isset( $field_val['m'] ) ) ) { | |
$format = empty( $field->dateFormat ) ? 'mdy' : esc_attr( $field->dateFormat ); | |
$date_info = GFcommon::parse_date( $field_val, $format ); | |
// converts date to array( 'm' => 1, 'd' => '13', 'y' => '1987' ) | |
$field_val = $field->get_date_array_by_format( array( $date_info['month'], $date_info['day'], $date_info['year'] ) ); | |
} | |
break; | |
case 'time': | |
if ( is_array( $field_val ) ) { | |
$ampm_key = key( array_slice( $field_val, - 1, 1, true ) ); | |
$field_val[ $ampm_key ] = strtolower( $field_val[ $ampm_key ] ); | |
} | |
break; | |
case 'address': | |
$state_input_id = sprintf( '%s.4', $field->id ); | |
if ( isset( $field_val[ $state_input_id ] ) && ! $field_val[ $state_input_id ] ) { | |
$field_val[ $state_input_id ] = $field->defaultState; | |
} | |
$country_input_id = sprintf( '%s.6', $field->id ); | |
if ( isset( $field_val[ $country_input_id ] ) && ! $field_val[ $country_input_id ] ) { | |
$field_val[ $country_input_id ] = $field->defaultCountry; | |
} | |
break; | |
} | |
$default_values[ $field->id ] = $field_val; | |
} | |
} | |
$button_conditional_script = ''; | |
//adding form button conditional logic if enabled | |
if ( isset( $form['button']['conditionalLogic'] ) ) { | |
$logics .= '0: ' . GFCommon::json_encode( array( 'field' => $form['button']['conditionalLogic'], 'section' => null ) ) . ','; | |
$dependents .= '0: ' . GFCommon::json_encode( array( 0 ) ) . ','; | |
$fields_with_logic[] = 0; | |
$button_conditional_script = "jQuery('#gform_{$form['id']}').submit(" . | |
'function(event, isButtonPress){' . | |
' var visibleButton = jQuery(".gform_next_button:visible, .gform_button:visible, .gform_image_button:visible");' . | |
' return visibleButton.length > 0 || isButtonPress == true;' . | |
'}' . | |
');'; | |
} | |
if ( ! empty( $logics ) ) { | |
$logics = substr( $logics, 0, strlen( $logics ) - 1 ); | |
} //removing last comma; | |
if ( ! empty( $dependents ) ) { | |
$dependents = substr( $dependents, 0, strlen( $dependents ) - 1 ); | |
} //removing last comma; | |
$animation = rgar( $form, 'enableAnimation' ) ? '1' : '0'; | |
global $wp_locale; | |
$number_format = $wp_locale->number_format['decimal_point'] == ',' ? 'decimal_comma' : 'decimal_dot'; | |
$str = "if(window['jQuery']){" . | |
"if(!window['gf_form_conditional_logic'])" . | |
"window['gf_form_conditional_logic'] = new Array();" . | |
"window['gf_form_conditional_logic'][{$form['id']}] = {'logic' : {" . $logics . " }, 'dependents' : {" . $dependents . " }, 'animation' : " . $animation . " , 'defaults' : " . json_encode( $default_values ) . ' }; ' . | |
"if(!window['gf_number_format'])" . | |
"window['gf_number_format'] = '" . $number_format . "';" . | |
'jQuery(document).ready(function(){' . | |
"gf_apply_rules({$form['id']}, " . json_encode( $fields_with_logic ) . ', true);' . | |
"jQuery('#gform_wrapper_{$form['id']}').show();" . | |
"jQuery(document).trigger('gform_post_conditional_logic', [{$form['id']}, null, true]);" . | |
$button_conditional_script . | |
'} );' . | |
'} '; | |
return $str; | |
} | |
/** | |
* Enqueue and retrieve all inline scripts that should be executed when the form is rendered. | |
* Use add_init_script() function to enqueue scripts. | |
* | |
* @param array $form | |
* @param array $field_values | |
* @param bool $is_ajax | |
*/ | |
private static function register_form_init_scripts( $form, $field_values = array(), $is_ajax = false ) { | |
// adding conditional logic script if conditional logic is configured for this form. | |
// get_conditional_logic also adds the chosen script for the enhanced dropdown option. | |
// if this form does not have conditional logic, add chosen script separately | |
if ( self::has_conditional_logic( $form ) ) { | |
self::add_init_script( $form['id'], 'conditional_logic', self::ON_PAGE_RENDER, self::get_conditional_logic( $form, $field_values ) ); | |
} | |
//adding currency config if there are any product fields in the form | |
if ( self::has_price_field( $form ) ) { | |
self::add_init_script( $form['id'], 'pricing', self::ON_PAGE_RENDER, self::get_pricing_init_script( $form ) ); | |
} | |
if ( self::has_password_strength( $form ) ) { | |
$password_script = self::get_password_strength_init_script( $form ); | |
self::add_init_script( $form['id'], 'password', self::ON_PAGE_RENDER, $password_script ); | |
} | |
if ( self::has_enhanced_dropdown( $form ) ) { | |
$chosen_script = self::get_chosen_init_script( $form ); | |
self::add_init_script( $form['id'], 'chosen', self::ON_PAGE_RENDER, $chosen_script ); | |
self::add_init_script( $form['id'], 'chosen', self::ON_CONDITIONAL_LOGIC, $chosen_script ); | |
} | |
if ( self::has_character_counter( $form ) ) { | |
self::add_init_script( $form['id'], 'character_counter', self::ON_PAGE_RENDER, self::get_counter_init_script( $form ) ); | |
} | |
if ( self::has_input_mask( $form ) ) { | |
self::add_init_script( $form['id'], 'input_mask', self::ON_PAGE_RENDER, self::get_input_mask_init_script( $form ) ); | |
} | |
if ( self::has_calculation_field( $form ) ) { | |
self::add_init_script( $form['id'], 'calculation', self::ON_PAGE_RENDER, self::get_calculations_init_script( $form ) ); | |
} | |
if ( self::has_currency_format_number_field( $form ) ) { | |
self::add_init_script( $form['id'], 'currency_format', self::ON_PAGE_RENDER, self::get_currency_format_init_script( $form ) ); | |
} | |
if ( self::has_currency_copy_values_option( $form ) ) { | |
self::add_init_script( $form['id'], 'copy_values', self::ON_PAGE_RENDER, self::get_copy_values_init_script( $form ) ); | |
} | |
if ( self::has_placeholder( $form ) ) { | |
self::add_init_script( $form['id'], 'placeholders', self::ON_PAGE_RENDER, self::get_placeholders_init_script( $form ) ); | |
} | |
if ( isset( $form['fields'] ) && is_array( $form['fields'] ) ) { | |
foreach ( $form['fields'] as $field ) { | |
/* @var GF_Field $field */ | |
if ( is_subclass_of( $field, 'GF_Field' ) ) { | |
$field->register_form_init_scripts( $form ); | |
} | |
} | |
} | |
gf_do_action( 'gform_register_init_scripts', $form['id'], $form, $field_values, $is_ajax ); | |
} | |
public static function get_form_init_scripts( $form ) { | |
$script_string = ''; | |
// temporary solution for output gf_global obj until wp min version raised to 3.3 | |
if ( wp_script_is( 'gform_gravityforms' ) ) { | |
$gf_global_script = "if(typeof gf_global == 'undefined') " . GFCommon::gf_global( false ); | |
} | |
/* rendering initialization scripts */ | |
$init_scripts = rgar( self::$init_scripts, $form['id'] ); | |
if ( ! empty( $init_scripts ) ) { | |
$script_string = | |
"<script type='text/javascript'>" . apply_filters( 'gform_cdata_open', '' ) . ' '; | |
$script_string .= isset( $gf_global_script ) ? $gf_global_script : ''; | |
$script_string .= | |
"jQuery(document).bind('gform_post_render', function(event, formId, currentPage){" . | |
"if(formId == {$form['id']}) {"; | |
foreach ( $init_scripts as $init_script ) { | |
if ( $init_script['location'] == self::ON_PAGE_RENDER ) { | |
$script_string .= $init_script['script']; | |
} | |
} | |
$script_string .= | |
"} " . //keep the space. needed to prevent plugins from replacing }} with ]} | |
"} );" . | |
"jQuery(document).bind('gform_post_conditional_logic', function(event, formId, fields, isInit){"; | |
foreach ( $init_scripts as $init_script ) { | |
if ( $init_script['location'] == self::ON_CONDITIONAL_LOGIC ) { | |
$script_string .= $init_script['script']; | |
} | |
} | |
$script_string .= | |
"} );" . apply_filters( 'gform_cdata_close', '' ) . '</script>'; | |
} | |
return $script_string; | |
} | |
public static function get_chosen_init_script( $form ) { | |
$chosen_fields = array(); | |
foreach ( $form['fields'] as $field ) { | |
$input_type = GFFormsModel::get_input_type( $field ); | |
if ( $field->enableEnhancedUI && in_array( $input_type, array( 'select', 'multiselect' ) ) ) { | |
$chosen_fields[] = "#input_{$form['id']}_{$field->id}"; | |
} | |
} | |
return "gformInitChosenFields('" . implode( ',', $chosen_fields ) . "','" . esc_attr( gf_apply_filters( 'gform_dropdown_no_results_text', $form['id'], __( 'No results matched', 'gravityforms' ), $form['id'] ) ) . "');"; | |
} | |
public static function get_currency_format_init_script( $form ) { | |
$currency_fields = array(); | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->numberFormat == 'currency' ) { | |
$currency_fields[] = "#input_{$form['id']}_{$field->id}"; | |
} | |
} | |
return "gformInitCurrencyFormatFields('" . implode( ',', $currency_fields ) . "');"; | |
} | |
public static function get_copy_values_init_script( $form ) { | |
$script = "jQuery('.copy_values_activated').on('click', function(){ | |
var inputId = this.id.replace('_copy_values_activated', ''); | |
jQuery('#' + inputId).toggle(!this.checked); | |
});"; | |
return $script; | |
} | |
public static function get_placeholders_init_script( $form ) { | |
$script = "if(typeof Placeholders != 'undefined'){ | |
Placeholders.enable(); | |
}"; | |
return $script; | |
} | |
public static function get_counter_init_script( $form ) { | |
$script = ''; | |
foreach ( $form['fields'] as $field ) { | |
$max_length = $field->maxLength; | |
$field_id = "input_{$form['id']}_{$field->id}"; | |
if ( ! empty( $max_length ) && ! $field->adminOnly ) { | |
$field_script = | |
"jQuery('#{$field_id}').textareaCount(" . | |
" {" . | |
" 'maxCharacterSize': {$max_length}," . | |
" 'originalStyle': 'ginput_counter'," . | |
" 'displayFormat' : '#input " . esc_js( __( 'of', 'gravityforms' ) ) . ' #max ' . esc_js( __( 'max characters', 'gravityforms' ) ) . "'" . | |
" } );"; | |
$script .= gf_apply_filters( 'gform_counter_script', $form['id'], $field_script, $form['id'], $field_id, $max_length ); | |
} | |
} | |
return $script; | |
} | |
public static function get_pricing_init_script( $form ) { | |
if ( ! class_exists( 'RGCurrency' ) ) { | |
require_once( 'currency.php' ); | |
} | |
return "if(window[\"gformInitPriceFields\"]) jQuery(document).ready(function(){gformInitPriceFields();} );"; | |
} | |
public static function get_password_strength_init_script( $form ) { | |
$field_script = "if(!window['gf_text']){window['gf_text'] = new Array();} window['gf_text']['password_blank'] = '" . esc_js( __( 'Strength indicator', 'gravityforms' ) ) . "'; window['gf_text']['password_mismatch'] = '" . esc_js( __( 'Mismatch', 'gravityforms' ) ) . "';window['gf_text']['password_bad'] = '" . esc_js( __( 'Bad', 'gravityforms' ) ) . "'; window['gf_text']['password_short'] = '" . esc_js( __( 'Short', 'gravityforms' ) ) . "'; window['gf_text']['password_good'] = '" . esc_js( __( 'Good', 'gravityforms' ) ) . "'; window['gf_text']['password_strong'] = '" . esc_js( __( 'Strong', 'gravityforms' ) ) . "';"; | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->type == 'password' && $field->passwordStrengthEnabled ) { | |
$field_id = "input_{$form['id']}_{$field->id}"; | |
$field_script .= "gformShowPasswordStrength(\"$field_id\");"; | |
} | |
} | |
return $field_script; | |
} | |
public static function get_input_mask_init_script( $form ) { | |
$script_str = ''; | |
foreach ( $form['fields'] as $field ) { | |
if ( ! $field->inputMask || ! $field->inputMaskValue ) { | |
continue; | |
} | |
$mask = $field->inputMaskValue; | |
$script = "jQuery('#input_{$form['id']}_{$field->id}').mask('" . esc_js( $mask ) . "').bind('keypress', function(e){if(e.which == 13){jQuery(this).blur();} } );"; | |
$script_str .= gf_apply_filters( 'gform_input_mask_script', $form['id'], $script, $form['id'], $field->id, $mask ); | |
} | |
if ( ! empty( $script_str ) ) { | |
return 'if(!/(android)/i.test(navigator.userAgent)){' . $script_str . '}'; | |
} | |
return $script_str; | |
} | |
public static function get_calculations_init_script( $form ) { | |
require_once( GFCommon::get_base_path() . '/currency.php' ); | |
$formula_fields = array(); | |
foreach ( $form['fields'] as $field ) { | |
if ( ! $field->enableCalculation || ! $field->calculationFormula ) { | |
continue; | |
} | |
$formula_fields[] = array( 'field_id' => $field->id, 'formula' => $field->calculationFormula, 'rounding' => $field->calculationRounding ); | |
} | |
if ( empty( $formula_fields ) ) { | |
return ''; | |
} | |
$script = self::get_number_formats_script( $form ); | |
$script .= 'new GFCalc(' . $form['id'] . ', ' . GFCommon::json_encode( $formula_fields ) . ');'; | |
return $script; | |
} | |
/** | |
* Generates a map of fields IDs and their corresponding number formats used by the GFCalc JS object for correctly | |
* converting field values to clean numbers. | |
* | |
* - Number fields have a 'numberFormat' setting (w/ UI). | |
* - Single-input product fields (i.e. 'singleproduct', 'calculation', 'price' and 'hiddenproduct') should default to | |
* the number format of the configured currency. | |
* - All other product fields will default to 'decimal_dot' for the number format. | |
* - All other fields will have no format (false) and inherit the format of the formula field when the formula is | |
* calculated. | |
* | |
* @param mixed $form | |
* @return string | |
*/ | |
public static function get_number_formats_script( $form ) { | |
$number_formats = array(); | |
$currency = RGCurrency::get_currency( GFCommon::get_currency() ); | |
foreach ( $form['fields'] as $field ) { | |
// default format is false, fields with no format will inherit the format of the formula field when calculated | |
$format = false; | |
switch ( GFFormsModel::get_input_type( $field ) ) { | |
case 'number': | |
$format = $field->numberFormat ? $field->numberFormat : 'decimal_dot'; | |
break; | |
case 'singleproduct': | |
case 'calculation': | |
case 'price': | |
case 'hiddenproduct': | |
case 'singleshipping': | |
$format = $currency['decimal_separator'] == ',' ? 'decimal_comma' : 'decimal_dot'; | |
break; | |
default: | |
// we check above for all single-input product types, for all other products, assume decimal format | |
if ( in_array( $field->type, array( 'product', 'option', 'shipping' ) ) ) { | |
$format = 'decimal_dot'; | |
} | |
} | |
$number_formats[ $field->id ] = $format; | |
} | |
return 'gf_global["number_formats"][' . $form['id'] . '] = ' . json_encode( $number_formats ) . ';'; | |
} | |
private static function has_datepicker_field( $form ) { | |
if ( is_array( $form['fields'] ) ) { | |
foreach ( $form['fields'] as $field ) { | |
if ( RGFormsModel::get_input_type( $field ) == 'date' && $field->dateType == 'datepicker' ) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
private static function has_price_field( $form ) { | |
$price_fields = GFAPI::get_fields_by_type( $form, array( 'product', 'donation' ) ); | |
$has_price_field = ! empty( $price_fields ); | |
return gf_apply_filters( 'gform_has_price_field', $form['id'], $has_price_field, $form ); | |
} | |
private static function has_fileupload_field( $form ) { | |
if ( is_array( $form['fields'] ) ) { | |
foreach ( $form['fields'] as $field ) { | |
$input_type = RGFormsModel::get_input_type( $field ); | |
if ( in_array( $input_type, array( 'fileupload', 'post_image' ) ) ) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
private static function has_currency_format_number_field( $form ) { | |
if ( is_array( $form['fields'] ) ) { | |
foreach ( $form['fields'] as $field ) { | |
$input_type = RGFormsModel::get_input_type( $field ); | |
if ( $input_type == 'number' && $field->numberFormat == 'currency' ) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
private static function has_currency_copy_values_option( $form ) { | |
if ( is_array( $form['fields'] ) ) { | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->enableCopyValuesOption == true ) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
private static function has_recaptcha_field( $form ) { | |
if ( is_array( $form['fields'] ) ) { | |
foreach ( $form['fields'] as $field ) { | |
if ( ( $field->type == 'captcha' || $field->inputType == 'captcha' ) && ! in_array( $field->captchaType, array( 'simple_captcha', 'math' ) ) ) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
public static function has_input_mask( $form, $field = false ) { | |
if ( $field ) { | |
if ( self::has_field_input_mask( $field ) ) { | |
return true; | |
} | |
} else { | |
if ( ! is_array( $form['fields'] ) ) { | |
return false; | |
} | |
foreach ( $form['fields'] as $field ) { | |
if ( self::has_field_input_mask( $field ) ) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
public static function has_field_input_mask( $field ) { | |
$type = GFFormsModel::get_input_type( $field ); | |
if ( $type == 'phone' && $field->phoneFormat == 'standard' ) { | |
return true; | |
} | |
if ( $field->inputMask && $field->inputMaskValue && ! $field->enablePasswordInput ) { | |
return true; | |
} | |
return false; | |
} | |
public static function has_calculation_field( $form ) { | |
if ( ! is_array( $form['fields'] ) ) { | |
return false; | |
} | |
foreach ( $form['fields'] as $field ) { | |
/* @var $field GF_Field */ | |
if ( $field->has_calculation() ) { | |
return true; | |
} | |
} | |
return false; | |
} | |
//Getting all fields that have a rule based on the specified field id | |
public static function get_conditional_logic_fields( $form, $fieldId ) { | |
$fields = array(); | |
//adding submit button field if enabled | |
if ( isset( $form['button']['conditionalLogic'] ) ) { | |
$fields[] = 0; | |
} | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->type != 'page' && ! empty( $field->conditionalLogic ) ) { | |
foreach ( $field->conditionalLogic['rules'] as $rule ) { | |
if ( $rule['fieldId'] == $fieldId ) { | |
$fields[] = floatval( $field->id ); | |
//if field is a section, add all fields in the section that have conditional logic (to support nesting) | |
if ( $field->type == 'section' ) { | |
$section_fields = GFCommon::get_section_fields( $form, $field->id ); | |
foreach ( $section_fields as $section_field ) { | |
if ( ! empty( $section_field['conditionalLogic'] ) ) { | |
$fields[] = floatval( $section_field['id'] ); | |
} | |
} | |
} | |
break; | |
} | |
} | |
} | |
//adding fields with next button logic | |
if ( ! empty( $field->nextButton['conditionalLogic'] ) ) { | |
foreach ( $field->nextButton['conditionalLogic']['rules'] as $rule ) { | |
if ( $rule['fieldId'] == $fieldId && ! in_array( $fieldId, $fields ) ) { | |
$fields[] = floatval( $field->id ); | |
break; | |
} | |
} | |
} | |
} | |
return $fields; | |
} | |
public static function get_field( $field, $value = '', $force_frontend_label = false, $form = null, $field_values = null ) { | |
$is_form_editor = GFCommon::is_form_editor(); | |
$is_entry_detail = GFCommon::is_entry_detail(); | |
$is_admin = $is_form_editor || $is_entry_detail; | |
$custom_class = $is_admin ? '' : $field->cssClass; | |
if ( $field->type == 'page' ) { | |
if ( $is_entry_detail ) { | |
return; //ignore page breaks in the entry detail page | |
} else if ( ! $is_form_editor ) { | |
$save_button = rgars( $form, 'save/enabled' ) ? self::get_form_button( $form['id'], "gform_save_{$form['id']}", $form['save']['button'], rgars( $form, 'save/button/text' ), 'gform_save_link', rgars( $form, 'save/button/text' ), 0, "jQuery(\"#gform_save_{$form['id']}\").val(1);" ) : ''; | |
$next_button = self::get_form_button( $form['id'], "gform_next_button_{$form['id']}_{$field->id}", $field->nextButton, __( 'Next', 'gravityforms' ), 'gform_next_button', __( 'Next Page', 'gravityforms' ), $field->pageNumber ); | |
$next_button = gf_apply_filters( 'gform_next_button', $form['id'], $next_button, $form ); | |
$previous_button = $field->pageNumber == 2 ? '' : self::get_form_button( $form['id'], "gform_previous_button_{$form['id']}_{$field->id}", $field->previousButton, __( 'Previous', 'gravityforms' ), 'gform_previous_button', __( 'Previous Page', 'gravityforms' ), $field->pageNumber - 2 ); | |
if ( ! empty( $previous_button ) ) { | |
$previous_button = gf_apply_filters( 'gform_previous_button', $form['id'], $previous_button, $form ); | |
} | |
$style = self::is_page_active( $form['id'], $field->pageNumber ) ? '' : "style='display:none;'"; | |
$custom_class = ! empty( $custom_class ) ? " {$custom_class}" : ''; | |
$html = "</ul> | |
</div> | |
<div class='gform_page_footer'> | |
{$previous_button} {$next_button} {$save_button} | |
</div> | |
</div> | |
<div id='gform_page_{$form['id']}_{$field->pageNumber}' class='gform_page{$custom_class}' {$style}> | |
<div class='gform_page_fields'> | |
<ul id='gform_fields_{$form['id']}_{$field->pageNumber}' class='" . GFCommon::get_ul_classes( $form ) . "'>"; | |
return $html; | |
} | |
} | |
if ( ! $is_admin && $field->adminOnly ) { | |
if ( $field->allowsPrepopulate ) { | |
$field->inputType = 'adminonly_hidden'; | |
} else { | |
return; | |
} | |
} | |
$id = $field->id; | |
$input_type = GFFormsModel::get_input_type( $field ); | |
$error_class = $field->failed_validation ? 'gfield_error' : ''; | |
$admin_only_class = $field->adminOnly ? 'field_admin_only' : ''; | |
$selectable_class = $is_admin ? 'selectable' : ''; | |
$hidden_class = in_array( $input_type, array( 'hidden', 'hiddenproduct' ) ) ? 'gform_hidden' : ''; | |
$section_class = $field->type == 'section' ? 'gsection' : ''; | |
$page_class = $field->type == 'page' ? 'gpage' : ''; | |
$html_block_class = $field->type == 'html' ? 'gfield_html' : ''; | |
$html_formatted_class = $field->type == 'html' && ! $is_admin && ! $field->disableMargins ? 'gfield_html_formatted' : ''; | |
$html_no_follows_desc_class = $field->type == 'html' && ! $is_admin && ! self::prev_field_has_description( $form, $field->id ) ? 'gfield_no_follows_desc' : ''; | |
$calculation_class = $input_type == 'calculation' || ( $input_type == 'number' && $field->has_calculation() ) ? 'gfield_calculation' : ''; | |
$product_suffix = "_{$form['id']}_" . $field->productField; | |
$option_class = $field->type == 'option' ? "gfield_price gfield_price{$product_suffix} gfield_option{$product_suffix}" : ''; | |
$quantity_class = $field->type == 'quantity' ? "gfield_price gfield_price{$product_suffix} gfield_quantity gfield_quantity{$product_suffix}" : ''; | |
$total_class = $field->type == 'total' ? "gfield_price gfield_price{$product_suffix} gfield_total gfield_total{$product_suffix}" : ''; | |
$shipping_class = $field->type == 'shipping' ? "gfield_price gfield_shipping gfield_shipping_{$form['id']}" : ''; | |
$product_class = $field->type == 'product' ? "gfield_price gfield_price_{$form['id']}_{$field->id} gfield_product_{$form['id']}_{$field->id}" : ''; | |
$hidden_product_class = $input_type == 'hiddenproduct' ? 'gfield_hidden_product' : ''; | |
$donation_class = $field->type == 'donation' ? "gfield_price gfield_price_{$form['id']}_{$field->id} gfield_donation_{$form['id']}_{$field->id}" : ''; | |
$required_class = $field->isRequired ? 'gfield_contains_required' : ''; | |
$creditcard_warning_class = $input_type == 'creditcard' && ! GFCommon::is_ssl() ? 'gfield_creditcard_warning' : ''; | |
$form_sublabel_setting = rgempty( 'subLabelPlacement', $form ) ? 'below' : $form['subLabelPlacement']; | |
$sublabel_setting = ! isset( $field->subLabelPlacement ) || empty( $field->subLabelPlacement ) ? $form_sublabel_setting : $field->subLabelPlacement; | |
$sublabel_class = "field_sublabel_{$sublabel_setting}"; | |
$form_description_setting = rgempty( 'descriptionPlacement', $form ) ? 'below' : $form['descriptionPlacement']; | |
$description_setting = ! isset( $field->descriptionPlacement ) || empty( $field->descriptionPlacement ) ? $form_description_setting : $field->descriptionPlacement; | |
$description_class = "field_description_{$description_setting}"; | |
$field_setting_label_placement = $field->labelPlacement; | |
$label_placement = empty( $field_setting_label_placement ) ? '' : $field_setting_label_placement; | |
$css_class = "$selectable_class gfield $error_class $section_class $admin_only_class $custom_class $hidden_class $html_block_class $html_formatted_class $html_no_follows_desc_class $option_class $quantity_class $product_class $total_class $donation_class $shipping_class $page_class $required_class $hidden_product_class $creditcard_warning_class $calculation_class $sublabel_class $description_class $label_placement"; | |
$css_class = preg_replace( '/\s+/', ' ', $css_class ); //removing extra spaces | |
$css_class = gf_apply_filters( 'gform_field_css_class', $form['id'], trim( $css_class ), $field, $form ); | |
$style = ''; | |
$field_id = $is_admin || empty( $form ) ? "field_$id" : 'field_' . $form['id'] . "_$id"; | |
$field_content = self::get_field_content( $field, $value, $force_frontend_label, $form == null ? 0 : $form['id'], $form ); | |
$field_container = "<li id='$field_id' class='{$css_class}' $style>{FIELD_CONTENT}</li>"; | |
$field_container = gf_apply_filters( 'gform_field_container', array( | |
$form['id'], | |
$field->id | |
), $field_container, $field, $form, $css_class, $style, $field_content ); | |
$field_markup = str_replace( '{FIELD_CONTENT}', $field_content, $field_container ); | |
return $field_markup; | |
} | |
private static function prev_field_has_description( $form, $field_id ) { | |
if ( ! is_array( $form['fields'] ) ) { | |
return false; | |
} | |
$prev = null; | |
foreach ( $form['fields'] as $field ) { | |
if ( $field->id == $field_id ) { | |
return $prev != null && ! empty( $prev['description'] ); | |
} | |
$prev = $field; | |
} | |
return false; | |
} | |
/** | |
* @param GF_Field $field | |
* @param string $value | |
* @param bool $force_frontend_label | |
* @param int $form_id | |
* @param null|array $form | |
* | |
* @return string | |
*/ | |
public static function get_field_content( $field, $value = '', $force_frontend_label = false, $form_id = 0, $form = null ) { | |
$field_label = $field->get_field_label( $form, $value ); | |
$admin_buttons = $field->get_admin_buttons(); | |
$input_type = GFFormsModel::get_input_type( $field ); | |
$is_form_editor = GFCommon::is_form_editor(); | |
$is_entry_detail = GFCommon::is_entry_detail(); | |
$is_admin = $is_form_editor || $is_entry_detail; | |
if ( $input_type == 'adminonly_hidden' ) { | |
$field_content = ! $is_admin ? '{FIELD}' : sprintf( "%s<label class='gfield_label' >%s</label>{FIELD}", $admin_buttons, esc_html( $field_label ) ); | |
} else { | |
$field_content = $field->get_field_content( $value, $force_frontend_label, $form ); | |
} | |
if ( $input_type == 'creditcard' && ! GFCommon::is_ssl() && ! $is_admin ) { | |
$field_content = "<div class='gfield_creditcard_warning_message'><span>" . esc_html__( 'This page is unsecured. Do not enter a real credit card number! Use this field only for testing purposes. ', 'gravityforms' ) . '</span></div>' . $field_content; | |
} | |
$value = $field->get_value_default_if_empty( $value ); | |
$field_content = str_replace( '{FIELD}', GFCommon::get_field_input( $field, $value, 0, $form_id, $form ), $field_content ); | |
$field_content = apply_filters( 'gform_field_content', $field_content, $field, $value, 0, $form_id ); | |
return $field_content; | |
} | |
private static function get_progress_bar( $form, $form_id, $confirmation_message ) { | |
$progress_complete = false; | |
$progress_bar = ''; | |
$page_count = self::get_max_page_number( $form ); | |
$current_page = self::get_current_page( $form_id ); | |
$page_name = rgar( rgar( $form['pagination'], 'pages' ), $current_page - 1 ); | |
$page_name = ! empty( $page_name ) ? ' - ' . $page_name : ''; | |
$style = $form['pagination']['style']; | |
$color = $style == 'custom' ? " color:{$form['pagination']['color']};" : ''; | |
$bgcolor = $style == 'custom' ? " background-color:{$form['pagination']['backgroundColor']};" : ''; | |
if ( ! empty( $confirmation_message ) ) { | |
$progress_complete = true; | |
} | |
//check admin setting for whether the progress bar should start at zero | |
$start_at_zero = rgars( $form, 'pagination/display_progressbar_on_confirmation' ); | |
//check for filter | |
$start_at_zero = apply_filters( 'gform_progressbar_start_at_zero', $start_at_zero, $form ); | |
$progressbar_page_count = $start_at_zero ? $current_page - 1 : $current_page; | |
$percent = ! $progress_complete ? floor( ( ( $progressbar_page_count ) / $page_count ) * 100 ) . '%' : '100%'; | |
$percent_number = ! $progress_complete ? floor( ( ( $progressbar_page_count ) / $page_count ) * 100 ) . '' : '100'; | |
if ( $progress_complete ) { | |
$wrapper_css_class = GFCommon::get_browser_class() . ' gform_wrapper'; | |
//add on surrounding wrapper class when confirmation page | |
$progress_bar = "<div class='{$wrapper_css_class}' id='gform_wrapper_$form_id' >"; | |
$page_name = ! empty( $form['pagination']['progressbar_completion_text'] ) ? $form['pagination']['progressbar_completion_text'] : ''; | |
} | |
$progress_bar .= " | |
<div id='gf_progressbar_wrapper_{$form_id}' class='gf_progressbar_wrapper'> | |
<h3 class='gf_progressbar_title'>"; | |
$progress_bar .= ! $progress_complete ? esc_html__( 'Step', 'gravityforms' ) . " {$current_page} " . esc_html__( 'of', 'gravityforms' ) . " {$page_count}{$page_name}" : "{$page_name}"; | |
$progress_bar .= " | |
</h3> | |
<div class='gf_progressbar'> | |
<div class='gf_progressbar_percentage percentbar_{$style} percentbar_{$percent_number}' style='width:{$percent};{$color}{$bgcolor}'><span>{$percent}</span></div> | |
</div></div>"; | |
//close div for surrounding wrapper class when confirmation page | |
$progress_bar .= $progress_complete ? $confirmation_message . '</div>' : ''; | |
return $progress_bar; | |
} | |
/** | |
* Validates the form's entry limit settings. Returns the entry limit message if entry limit exceeded. | |
* | |
* @param array $form current GF form object | |
* | |
* @return string If entry limit exceeded returns entry limit setting. | |
*/ | |
public static function validate_entry_limit( $form ) { | |
//If form has a limit of entries, check current entry count | |
if ( rgar( $form, 'limitEntries' ) ) { | |
$period = rgar( $form, 'limitEntriesPeriod' ); | |
$range = self::get_limit_period_dates( $period ); | |
$entry_count = RGFormsModel::get_lead_count( $form['id'], '', null, null, $range['start_date'], $range['end_date'], 'active' ); | |
if ( $entry_count >= $form['limitEntriesCount'] ) { | |
return empty( $form['limitEntriesMessage'] ) ? "<div class='gf_submission_limit_message'><p>" . esc_html__( 'Sorry. This form is no longer accepting new submissions.', 'gravityforms' ) . '</p></div>' : '<p>' . GFCommon::gform_do_shortcode( $form['limitEntriesMessage'] ) . '</p>'; | |
} | |
} | |
} | |
public static function validate_form_schedule( $form ) { | |
//If form has a schedule, make sure it is within the configured start and end dates | |
if ( rgar( $form, 'scheduleForm' ) ) { | |
$local_time_start = sprintf( '%s %02d:%02d %s', $form['scheduleStart'], $form['scheduleStartHour'], $form['scheduleStartMinute'], $form['scheduleStartAmpm'] ); | |
$local_time_end = sprintf( '%s %02d:%02d %s', $form['scheduleEnd'], $form['scheduleEndHour'], $form['scheduleEndMinute'], $form['scheduleEndAmpm'] ); | |
$timestamp_start = strtotime( $local_time_start . ' +0000' ); | |
$timestamp_end = strtotime( $local_time_end . ' +0000' ); | |
$now = current_time( 'timestamp' ); | |
if ( ! empty( $form['scheduleStart'] ) && $now < $timestamp_start ) { | |
return empty( $form['schedulePendingMessage'] ) ? '<p>' . esc_html__( 'This form is not yet available.', 'gravityforms' ) . '</p>' : '<p>' . GFCommon::gform_do_shortcode( $form['schedulePendingMessage'] ) . '</p>'; | |
} elseif ( ! empty( $form['scheduleEnd'] ) && $now > $timestamp_end ) { | |
return empty( $form['scheduleMessage'] ) ? '<p>' . esc_html__( 'Sorry. This form is no longer available.', 'gravityforms' ) . '</p>' : '<p>' . GFCommon::gform_do_shortcode( $form['scheduleMessage'] ) . '</p>'; | |
} | |
} | |
} | |
public static function update_confirmation( $form, $lead = null, $event = '' ) { | |
if ( ! is_array( rgar( $form, 'confirmations' ) ) ) { | |
return $form; | |
} | |
if ( ! empty( $event ) ) { | |
$confirmations = wp_filter_object_list( $form['confirmations'], array( 'event' => $event ) ); | |
} else { | |
$confirmations = $form['confirmations']; | |
} | |
// if there is only one confirmation, don't bother with the conditional logic, just return it | |
// this is here mostly to avoid the semi-costly GFFormsModel::create_lead() function unless we really need it | |
if ( is_array( $form['confirmations'] ) && count( $confirmations ) <= 1 ) { | |
$form['confirmation'] = reset( $confirmations ); | |
return $form; | |
} | |
if ( empty( $lead ) ) { | |
$lead = GFFormsModel::create_lead( $form ); | |
} | |
foreach ( $confirmations as $confirmation ) { | |
if ( rgar( $confirmation, 'event' ) != $event ) { | |
continue; | |
} | |
if ( rgar( $confirmation, 'isDefault' ) ) { | |
continue; | |
} | |
if ( isset( $confirmation['isActive'] ) && ! $confirmation['isActive'] ) { | |
continue; | |
} | |
$logic = rgar( $confirmation, 'conditionalLogic' ); | |
if ( GFCommon::evaluate_conditional_logic( $logic, $form, $lead ) ) { | |
$form['confirmation'] = $confirmation; | |
return $form; | |
} | |
} | |
$filtered_list = wp_filter_object_list( $form['confirmations'], array( 'isDefault' => true ) ); | |
$form['confirmation'] = reset( $filtered_list ); | |
return $form; | |
} | |
public static function process_send_resume_link() { | |
$form_id = rgpost( 'gform_send_resume_link' ); | |
$form_id = absint( $form_id ); | |
$email = rgpost( 'gform_resume_email' ); | |
$resume_token = rgpost( 'gform_resume_token' ); | |
$resume_token = sanitize_key( $resume_token ); | |
if ( empty( $form_id ) || empty( $email ) || empty( $resume_token ) || ! GFCommon::is_valid_email( $email ) ) { | |
return; | |
} | |
$form = GFFormsModel::get_form_meta( $form_id ); | |
if ( empty( $form ) ) { | |
return; | |
} | |
if ( rgar( $form, 'requireLogin' ) ) { | |
if ( ! is_user_logged_in() ) { | |
wp_die(); | |
} | |
check_admin_referer( 'gform_send_resume_link', '_gform_send_resume_link_nonce' ); | |
} | |
$incomplete_submission = GFFormsModel::get_incomplete_submission_values( $resume_token ); | |
$submission = json_decode( $incomplete_submission['submission'], true ); | |
$partial_entry = $submission['partial_entry']; | |
$notifications_to_send = GFCommon::get_notifications_to_send( 'form_save_email_requested', $form, $partial_entry ); | |
$log_notification_event = empty( $notifications_to_send ) ? 'No notifications to process' : 'Processing notifications'; | |
GFCommon::log_debug( "GFFormDisplay::process_send_resume_link(): {$log_notification_event} for form_save_email_requested event." ); | |
foreach ( $notifications_to_send as $notification ) { | |
if ( isset( $notification['isActive'] ) && ! $notification['isActive'] ) { | |
GFCommon::log_debug( "GFFormDisplay::process_send_resume_link(): Notification is inactive, not processing notification (#{$notification['id']} - {$notification['name']})." ); | |
continue; | |
} | |
if ( $notification['toType'] == 'hidden' ) { | |
$notification['to'] = $email; | |
} | |
$notification['message'] = self::replace_save_variables( $notification['message'], $form, $resume_token, $email ); | |
GFCommon::send_notification( $notification, $form, $partial_entry ); | |
} | |
GFFormsModel::add_email_to_incomplete_sumbmission( $resume_token, $email ); | |
} | |
public static function replace_save_variables( $text, $form, $resume_token, $email = null ) { | |
$resume_token = sanitize_key( $resume_token ); | |
$form_id = intval( $form['id'] ); | |
$resume_url = apply_filters( 'gform_save_and_continue_resume_url', add_query_arg( array( 'gf_token' => $resume_token ), GFFormsModel::get_current_page_url() ), $form, $resume_token, $email ); | |
$resume_url = esc_url( $resume_url ); | |
$resume_link = "<a href=\"{$resume_url}\" class='resume_form_link'>{$resume_url}</a>"; | |
$text = str_replace( '{save_link}', $resume_link, $text ); | |
$text = str_replace( '{save_token}', $resume_token, $text ); | |
$text = str_replace( '{save_url}', $resume_url, $text ); | |
$email_esc = esc_attr( $email ); | |
$text = str_replace( '{save_email}', $email_esc, $text ); | |
$resume_submit_button_text = esc_html__( 'Send Email', 'gravityforms' ); | |
$resume_email_validation_message = esc_html__( 'Please enter a valid email address.', 'gravityforms' ); | |
// The {save_email_input} accepts shortcode-style options button_text and validation_message. E.g., | |
// {save_email_input: button_text="Send the link to my email address" validation_message="The link couldn't be sent because the email address is not valid."} | |
preg_match_all( '/\{save_email_input:(.*?)\}/', $text, $matches, PREG_SET_ORDER ); | |
if ( is_array( $matches ) && isset( $matches[0] ) && isset( $matches[0][1] ) ) { | |
$options_string = isset( $matches[0][1] ) ? $matches[0][1] : ''; | |
$options = shortcode_parse_atts( $options_string ); | |
if ( isset( $options['button_text'] ) ) { | |
$resume_submit_button_text = $options['button_text']; | |
} | |
if ( isset( $options['validation_message'] ) ) { | |
$resume_email_validation_message = $options['validation_message']; | |
} | |
$full_tag = $matches[0][0]; | |
$text = str_replace( $full_tag, '{save_email_input}', $text ); | |
} | |
$action = esc_url( remove_query_arg( 'gf_token' ) ); | |
$ajax = isset( $_POST['gform_ajax'] ); | |
$has_pages = self::has_pages( $form ); | |
$default_anchor = $has_pages || $ajax ? true : false; | |
$use_anchor = gf_apply_filters( 'gform_confirmation_anchor', $form_id, $default_anchor ); | |
if ( $use_anchor !== false ) { | |
$action .= "#gf_$form_id"; | |
} | |
$html_input_type = RGFormsModel::is_html5_enabled() ? 'email' : 'text'; | |
$resume_token = esc_attr( $resume_token ); | |
$validation_message = ! is_null( $email ) && ! GFCommon::is_valid_email( $email ) ? sprintf( '<div class="validation_message">%s</div>', $resume_email_validation_message ) : ''; | |
$nonce_input = ''; | |
if ( rgar( $form, 'requireLogin' ) ) { | |
$nonce_input = wp_nonce_field( 'gform_send_resume_link', '_gform_send_resume_link_nonce', true, false ); | |
} | |
$target = $ajax ? "target='gform_ajax_frame_{$form_id}'" : ''; | |
$ajax_fields = ''; | |
if ( $ajax ) { | |
$ajax_fields = "<input type='hidden' name='gform_ajax' value='" . esc_attr( "form_id={$form_id}&title=1&description=1&tabindex=1" ) . "' />"; | |
$ajax_fields .= "<input type='hidden' name='gform_field_values' value='' />"; | |
} | |
$resume_form = "<div class='form_saved_message_emailform'> | |
<form action='{$action}' method='POST' id='gform_{$form_id}' {$target}> | |
{$ajax_fields} | |
<input type='{$html_input_type}' name='gform_resume_email' value='{$email_esc}'/> | |
<input type='hidden' name='gform_resume_token' value='{$resume_token}' /> | |
<input type='hidden' name='gform_send_resume_link' value='{$form_id}' /> | |
<input type='submit' name='gform_send_resume_link_button' id='gform_send_resume_link_button_{$form_id}' value='{$resume_submit_button_text}' /> | |
{$validation_message} | |
{$nonce_input} | |
</form> | |
</div>"; | |
$text = str_replace( '{save_email_input}', $resume_form, $text ); | |
return $text; | |
} | |
public static function handle_save_email_confirmation( $form, $ajax ) { | |
$resume_email = $_POST['gform_resume_email']; | |
if ( ! GFCommon::is_valid_email( $resume_email ) ) { | |
GFCommon::log_debug( 'GFFormDisplay::handle_save_email_confirmation(): Invalid email address: ' . $resume_email ); | |
return new WP_Error( 'invalid_email' ); | |
} | |
$resume_token = $_POST['gform_resume_token']; | |
$submission_details = GFFormsModel::get_incomplete_submission_values( $resume_token ); | |
$submission_json = $submission_details['submission']; | |
$submission = json_decode( $submission_json, true ); | |
$entry = $submission['partial_entry']; | |
$form = self::update_confirmation( $form, $entry, 'form_save_email_sent' ); | |
$confirmation = '<div class="form_saved_message_sent"><span>' . rgar( $form['confirmation'], 'message' ) . '</span></div>'; | |
$nl2br = rgar( $form['confirmation'], 'disableAutoformat' ) ? false : true; | |
$save_email_confirmation = self::replace_save_variables( $confirmation, $form, $resume_token, $resume_email ); | |
$save_email_confirmation = GFCommon::replace_variables( $save_email_confirmation, $form, $entry, false, true, $nl2br ); | |
$form_id = absint( $form['id'] ); | |
$has_pages = self::has_pages( $form ); | |
$default_anchor = $has_pages || $ajax ? true : false; | |
$use_anchor = gf_apply_filters( 'gform_confirmation_anchor', $form_id, $default_anchor ); | |
if ( $use_anchor !== false ) { | |
$save_email_confirmation = "<a id='gf_$form_id' class='gform_anchor' ></a>" . $save_email_confirmation; | |
} | |
if ( $ajax ) { | |
$save_email_confirmation = "<!DOCTYPE html><html><head><meta charset='UTF-8' /></head><body class='GF_AJAX_POSTBACK'>" . $save_email_confirmation . '</body></html>'; | |
} | |
GFCommon::log_debug( 'GFFormDisplay::handle_save_email_confirmation(): Confirmation => ' . print_r( $save_email_confirmation, true ) ); | |
return $save_email_confirmation; | |
} | |
public static function handle_save_confirmation( $form, $resume_token, $confirmation_message, $ajax ) { | |
$resume_email = isset( $_POST['gform_resume_email'] ) ? $_POST['gform_resume_email'] : null; | |
$confirmation_message = self::replace_save_variables( $confirmation_message, $form, $resume_token, $resume_email ); | |
$confirmation_message = "<div class='form_saved_message'><span>" . $confirmation_message . '</span></div>'; | |
$form_id = absint( $form['id'] ); | |
$has_pages = self::has_pages( $form ); | |
$default_anchor = $has_pages || $ajax ? true : false; | |
$use_anchor = gf_apply_filters( 'gform_confirmation_anchor', $form_id, $default_anchor ); | |
if ( $use_anchor !== false ) { | |
$confirmation_message = "<a id='gf_{$form_id}' class='gform_anchor' ></a>" . $confirmation_message; | |
} | |
$wrapper_css_class = GFCommon::get_browser_class() . ' gform_wrapper'; | |
$confirmation_message = "<div class='{$wrapper_css_class}' id='gform_wrapper_{$form_id}'>" . $confirmation_message . '</div>'; | |
if ( $ajax ) { | |
$confirmation_message = "<!DOCTYPE html><html><head><meta charset='UTF-8' /></head><body class='GF_AJAX_POSTBACK'>" . $confirmation_message . '</body></html>'; | |
} | |
GFCommon::log_debug( 'GFFormDisplay::handle_save_confirmation(): Confirmation => ' . print_r( $confirmation_message, true ) ); | |
return $confirmation_message; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment