Sid Gifari File Manager
🏠 Root
/
home
/
nradmin
/
public_html
/
wp-content
/
plugins
/
forminator
/
library
/
modules
/
custom-forms
/
front
/
📝 Editing: front-action.php
<?php /** * The Forminator_CForm_Front_Action class. * * @package Forminator */ if ( ! defined( 'ABSPATH' ) ) { die(); } /** * Front ajax for custom forms * * @since 1.0 */ class Forminator_CForm_Front_Action extends Forminator_Front_Action { /** * Module slug * * @var string */ protected static $module_slug = 'form'; /** * Submit errors * * @var array */ public static $submit_errors = array(); /** * Hidden fields * * @var array */ public static $hidden_fields = array(); /** * Not calculable fields * * @var array */ public static $not_calculable = array(); /** * Fields that shoud be replaced to zero if it's hidden * * @var array */ public static $replace_to_zero = array(); /** * Entry type * * @var string */ public static $entry_type = 'custom-forms'; /** * Registration object * * @var string */ public static $registration = null; /** * Plugin instance * * @var null */ private static $instance = null; /** * Flag if form has upload field * * @var false */ private static $has_upload = false; /** * Flag if form has payment fields * * @var false */ private static $has_payment = false; /** * Forminator_CForm_Front_Action constructor */ public function __construct() { parent::__construct(); // Save entries. if ( ! empty( self::$entry_type ) ) { add_action( 'wp_ajax_forminator_pp_create_order', array( $this, 'create_paypal_order' ) ); add_action( 'wp_ajax_nopriv_forminator_pp_create_order', array( $this, 'create_paypal_order' ) ); add_action( 'wp_ajax_forminator_multiple_file_upload', array( $this, 'multiple_file_upload' ) ); add_action( 'wp_ajax_nopriv_forminator_multiple_file_upload', array( $this, 'multiple_file_upload' ) ); } add_action( 'wp_ajax_forminator_email_draft_link', array( $this, 'submit_email_draft_link' ) ); add_action( 'wp_ajax_nopriv_forminator_email_draft_link', array( $this, 'submit_email_draft_link' ) ); } /** * Return the plugin instance * * @since 1.0 * @return Forminator_Front_Action */ public static function get_instance() { if ( is_null( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } /** * Prepare price to pass to PayPal * * @param array $amount Amount array. * @return array */ private static function prepare_pp_price( $amount ) { $integer_currencies = array( 'HUF', 'JPY', 'TWD', ); if ( isset( $amount['currency_code'] ) && in_array( $amount['currency_code'], $integer_currencies, true ) ) { $amount['value'] = number_format( (float) $amount['value'] ); } else { $amount['value'] = number_format( (float) $amount['value'], 2, '.', '' ); } return $amount; } /** * Create PayPal order * * @since 1.14.3 */ public function create_paypal_order() { $body = trim( file_get_contents( 'php://input' ) ); $data = json_decode( $body, true ); $form_id = $data['form_id'] ?? ''; if ( ! isset( $data['nonce'] ) || ! wp_verify_nonce( $data['nonce'], 'forminator_submit_form' . $form_id ) ) { wp_send_json_error( new WP_Error( 'invalid_code' ) ); } // Check if form data is set. if ( isset( $data['form_data'] ) && isset( $data['form_data']['purchase_units'] ) ) { // Check if payment amount is bigger than zero. if ( floatval( $data['form_data']['purchase_units'][0]['amount']['value'] ) <= 0 ) { wp_send_json_error( esc_html__( 'The payment total must be greater than 0.', 'forminator' ) ); } $data['form_data']['purchase_units'][0]['amount'] = self::prepare_pp_price( $data['form_data']['purchase_units'][0]['amount'] ); $data = $this->get_temporary_country_code( $data ); $data = $this->get_state_code( $data ); $paypal = new Forminator_PayPal_Express(); $request = array_merge( array( 'intent' => 'CAPTURE' ), $data['form_data'] ); $request = apply_filters( 'forminator_paypal_create_order_request', $request, $data ); if ( empty( $request['payer'] ) ) { unset( $request['payer'] ); } $order = $paypal->create_order( $request, $data['mode'] ); if ( is_wp_error( $order ) ) { wp_send_json_error( esc_html__( 'Cannot create a new order on PayPal. If the error persists, please contact us for further assistance.', 'forminator' ) ); } $response = array( 'order_id' => $order->id, ); wp_send_json_success( $response ); } } /** * Update payment amount * * @since 1.7.3 */ public function update_payment_amount() { $this->init_properties(); self::check_fields_visibility(); $first_intent = ! empty( self::$prepared_data['stripe_first_payment_intent'] ); $is_intent = ! empty( self::$prepared_data['stripe-intent'] ); if ( ! $first_intent && empty( self::$info['stripe_field'] ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Error: Stripe field doesn\'t exist in your form!', 'forminator' ), 'errors' => array(), ) ); } $forminator_stripe_field = Forminator_Core::get_field_object( 'stripe' ); if ( $forminator_stripe_field instanceof Forminator_Stripe ) { if ( ! $first_intent && $is_intent && isset( self::$prepared_data['paymentPlan'] ) && ( empty( $forminator_stripe_field->payment_plan ) || self::$prepared_data['paymentPlan'] === $forminator_stripe_field->payment_plan_hash ) ) { // No need to update paymentIntent if the plan is not set or it's the same plan. // Do not reset the payment plan if it's already set. $new_plan_hash = empty( $forminator_stripe_field->payment_plan_hash ) && ! empty( self::$prepared_data['paymentPlan'] ) ? self::$prepared_data['paymentPlan'] : $forminator_stripe_field->payment_plan_hash; wp_send_json_success( array( 'paymentPlan' => $new_plan_hash, ) ); } $forminator_stripe_field->update_paymentIntent( self::$prepared_data, self::$info['stripe_field'] ); } wp_send_json_success(); } /** * Add a temporary country code based on currency to prevent errors. * Set country code to Austria if currency is Euro, * else remove the last letter from currency code to get temporary country code. * * This only prevents error from Paypal in case the country is not enabled/required in the Address field. * Users will be able to choose the country again in Paypal window or credit card form. * * @param array $data Data for paypal order. * * @return array */ private function get_temporary_country_code( $data ) { if ( isset( $data['form_data']['payer']['address'] ) ) { if ( empty( $data['form_data']['payer']['address'] ) || ( isset( $data['form_data']['payer']['address']['country_code'] ) && empty( $data['form_data']['payer']['address']['country_code'] ) ) ) { $currency = $data['form_data']['purchase_units'][0]['amount']['currency_code']; if ( 'EUR' === $currency ) { $country_code = 'AT'; } else { $country_code = substr( $currency, 0, -1 ); } $data['form_data']['payer']['address']['country_code'] = $country_code; } } return $data; } /** * Get state code * * @param array $data Data for paypal order. * * @return array */ private function get_state_code( $data ) { if ( ! empty( $data['form_data']['payer']['address']['admin_area_1'] ) ) { $data['form_data']['payer']['address']['admin_area_1'] = forminator_get_state_code( $data['form_data']['payer']['address']['admin_area_1'] ); } return $data; } /** * Get default currency * * @return string */ private function get_default_currency() { try { $stripe = new Forminator_Gateway_Stripe(); return $stripe->get_default_currency(); } catch ( Forminator_Gateway_Exception $e ) { return 'USD'; } } /** * Check reCaptcha * * @return string|null * @throws Exception When there is an error. */ private static function check_captcha() { // Ignore captcha re-check if we have Stripe/PayPal field. if ( self::$is_draft || ! empty( self::$info['stripe_field'] ) || self::is_in_hidden_fields( 'stripe-' ) || ! empty( self::$info['paypal_field'] ) ) { return; } $form_id = self::$module_id; $field_captcha_obj = Forminator_Core::get_field_object( 'captcha' ); if ( self::$info['captcha_settings'] && $field_captcha_obj ) { $field_id = Forminator_Field::get_property( 'element_id', self::$info['captcha_settings'] ); $captcha_user_response = ''; if ( isset( self::$prepared_data['g-recaptcha-response'] ) ) { // Ignore CAPTCHA re-check (only for the v2 checkbox option) during two-factor authentication. if ( isset( self::$module_settings['form-type'] ) && 'login' === self::$module_settings['form-type'] ) { if ( ! empty( self::$prepared_data['auth_method'] ) && 'v2_checkbox' === self::$info['captcha_settings']['captcha_type'] ) { return; } } $captcha_user_response = self::$prepared_data['g-recaptcha-response']; } elseif ( isset( self::$prepared_data['h-captcha-response'] ) ) { $captcha_user_response = self::$prepared_data['h-captcha-response']; } elseif ( isset( self::$prepared_data['forminator-turnstile-response'] ) ) { $captcha_user_response = self::$prepared_data['forminator-turnstile-response']; } /** * Filter captcha user response, default is from `g-recaptcha-response` * * @since 1.5.3 * * @param string $captcha_user_response * @param int $form_id * @param array $submitted_data * * @return string captcha user response */ $captcha_user_response = apply_filters( 'forminator_captcha_user_response', $captcha_user_response, $form_id, self::$prepared_data ); $field_captcha_obj->validate_entry( self::$info['captcha_settings'], $captcha_user_response ); $valid_response = $field_captcha_obj->is_valid_entry(); if ( is_array( $valid_response ) && ! empty( $valid_response[ $field_id ] ) ) { // if captcha invalid. throw new Exception( esc_html( $valid_response[ $field_id ] ) ); } } } /** * Check if field is in $hidden_fields array * * @param string $field Field slug excluding the iterator. * * @return bool */ private static function is_in_hidden_fields( $field ) { foreach ( self::$hidden_fields as $val ) { if ( false !== strpos( $val, $field ) ) { return true; } } return false; } /** * Handle login if it's login form * * @param object $entry Entry. * @return boolean * @throws Exception When there is an error. */ private static function maybe_login( $entry ) { if ( ! isset( self::$module_settings['form-type'] ) || 'login' !== self::$module_settings['form-type'] ) { return; } // Check who can login. if ( is_user_logged_in() ) { return; } $forminator_user_login = new Forminator_CForm_Front_User_Login(); $login_user = $forminator_user_login->process_login( self::$module_object, $entry, self::$info['field_data_array'] ); if ( is_wp_error( $login_user['user'] ) ) { $message = $login_user['user']->get_error_message(); throw new Exception( wp_kses( $message, 'strong' ) ); } if ( ! empty( $login_user['authentication'] ) && 'invalid' === $login_user['authentication'] ) { self::$response_attrs['authentication'] = 'invalid'; throw new Exception( esc_html__( 'Whoops, the passcode you entered was incorrect or expired.', 'forminator' ) ); } if ( isset( $login_user['user']->ID ) ) { self::$response_attrs['user_id'] = $login_user['user']->ID; } if ( isset( $login_user['authentication'] ) ) { self::$response_attrs['authentication'] = $login_user['authentication']; } if ( isset( $login_user['auth_token'] ) ) { self::$response_attrs['auth_token'] = $login_user['auth_token']; } if ( isset( $login_user['auth_method'] ) ) { self::$response_attrs['auth_method'] = $login_user['auth_method']; } if ( isset( $login_user['auth_nav'] ) ) { self::$response_attrs['auth_nav'] = $login_user['auth_nav']; } if ( isset( $login_user['lost_url'] ) ) { self::$response_attrs['lost_url'] = $login_user['lost_url']; } self::remove_password(); return true; } /** * Handle registration form validation separately * * @since 1.17.2 * * @return \WP_Error|boolean * @throws Exception When there is an error. */ private static function validate_registration() { if ( self::$is_draft || self::$is_spam ) { return; } if ( isset( self::$module_settings['form-type'] ) && 'registration' === self::$module_settings['form-type'] ) { // Check who can register new users. if ( ! is_user_logged_in() ) { $can_creat_user = true; } elseif ( isset( self::$module_settings['hide-registration-form'] ) && '' === self::$module_settings['hide-registration-form'] ) { $can_creat_user = true; } else { $can_creat_user = false; } if ( ! $can_creat_user ) { return; } self::$registration = new Forminator_CForm_Front_User_Registration(); $registration_error = self::$registration->process_validation( self::$module_object, self::$info['field_data_array'] ); if ( true !== $registration_error ) { throw new Exception( esc_html( $registration_error ) ); } $custom_error = apply_filters( 'forminator_custom_registration_form_errors', $registration_error, self::$module_id, self::$info['field_data_array'] ); if ( true !== $custom_error ) { throw new Exception( esc_html( $custom_error ) ); } return true; } } /** * Handle registration if it's registration form. * * @param object $entry Entry. * * @return \WP_Error|boolean * @throws Exception When there is an error. */ private static function maybe_registration( $entry ) { if ( self::$is_draft || self::$is_spam ) { return; } if ( isset( self::$module_settings['form-type'] ) && 'registration' === self::$module_settings['form-type'] ) { // Check who can register new users. if ( ! is_user_logged_in() ) { $can_creat_user = true; } elseif ( isset( self::$module_settings['hide-registration-form'] ) && '' === self::$module_settings['hide-registration-form'] ) { $can_creat_user = true; } else { $can_creat_user = false; } if ( ! $can_creat_user ) { return; } $new_user_data = self::$registration->process_registration( self::$module_object, $entry ); if ( ! is_array( $new_user_data ) ) { throw new Exception( esc_html( $new_user_data ) ); } // Do not send emails later. self::$module_object->notifications = array(); return true; } } /** * Prepare fields info */ private static function prepare_fields_info() { self::check_fields_visibility(); self::$is_leads = isset( self::$module_settings['form-type'] ) && 'leads' === self::$module_settings['form-type']; self::$has_payment = empty( self::$info['stripe_field'] ) && empty( self::$info['paypal_field'] ) ? false : true; $fields = self::get_fields(); foreach ( $fields as $field_index => $field ) { self::set_field_data_array( $field_index, $field ); } // Validate User Registration first before any payments. $registration = self::validate_registration(); if ( is_wp_error( $registration ) ) { return self::return_error( $registration->get_error_message() ); } self::check_errors(); self::filter_field_data_array(); } /** * Set field data array * * @param int $field_index Int key. * @param object $field Forminator_Form_Field_Model. * @return null */ private static function set_field_data_array( $field_index, $field ) { $field_array = $field->to_formatted_array(); $field_type = $field_array['type']; $element_id = Forminator_Field::get_property( 'element_id', $field_array ); if ( self::$is_draft ) { if ( in_array( $field_type, array( 'hidden', 'stripe', 'stripe-ocs', 'paypal', 'signature' ), true ) ) { return; } if ( 'group' === $field_type ) { self::$info['field_data_array'][] = array( 'name' => $element_id . '-copies', 'value' => ! empty( self::$prepared_data[ $element_id . '-copies' ] ) ? count( self::$prepared_data[ $element_id . '-copies' ] ) + 1 : 1, ); } } // if certain field types - go to next field. if ( in_array( $field_type, array( 'stripe', 'stripe-ocs', 'paypal', 'calculation', 'group' ), true ) ) { return; } $cloned_suffixes = ! empty( $field->parent_group ) && ! empty( self::$prepared_data[ $field->parent_group . '-copies' ] ) ? self::$prepared_data[ $field->parent_group . '-copies' ] : array(); $all_suffixes = array_map( function ( $str ) { return '-' . $str; }, $cloned_suffixes ); array_unshift( $all_suffixes, '' ); foreach ( $all_suffixes as $original_suffix => $suffix ) { $field_id = $element_id . $suffix; // skip if conditionally hidden. if ( ! $field_id || in_array( $field_id, self::$hidden_fields, true ) ) { continue; } $clonned_field = $field_array; $clonned_field['element_id'] = $field_id; if ( $original_suffix ) { $clonned_field['original_id'] = $element_id . '-' . $original_suffix; } self::set_field_data( $field_id, $clonned_field, $field_index ); } } /** * Set field data * * @param string $field_id Field slug. * @param array $field_array Field settings. * @param int $field_index Field index. * @return null */ private static function set_field_data( $field_id, $field_array, $field_index ) { $field_type = $field_array['type']; $form_field_obj = Forminator_Core::get_field_object( $field_type ); // Skip if field object is not found. if ( empty( $form_field_obj ) ) { return; } if ( isset( self::$prepared_data[ $field_id ] ) ) { $field_data = self::$prepared_data[ $field_id ]; } else { $field_data = array(); } /** * Filter handle specific field types * * @since 1.13 * * @param array $field_data Field data * @param object $form_field_obj Form field object * @param array $field_array field settings * * @return array $field_data Set `return` element of the array as true for returning */ $field_data = apply_filters( 'forminator_handle_specific_field_types', $field_data, $form_field_obj, $field_array ); if ( ! empty( $field_data['return'] ) ) { unset( $field_data['return'] ); self::$info['field_data_array'][] = $field_data; return; } /** * Sanitize data * * @since 1.0.2 * * @param array $field * @param array|string $data - the data to be sanitized. */ $field_data = $form_field_obj->sanitize( $field_array, $field_data ); if ( ! self::$is_draft ) { $field_data = $form_field_obj->validate_entry( $field_array, $field_data ); } $form_field_obj->is_valid_entry(); if ( ! self::is_empty_field( $field_array, $field_data ) ) { self::$info['field_data_array'][] = array( 'name' => $field_id, 'value' => $field_data, 'field_type' => $field_type, 'key' => $field_index, 'field_array' => $field_array, 'form_field_obj' => $form_field_obj, ); } } /** * Check field has empty value. * * @param array $field Field. * @param mixed $field_data Field value. * * @return bool */ private static function is_empty_field( $field, $field_data ) { $is_empty = true; if ( ! empty( $field['type'] ) && 'postdata' === $field['type'] ) { // Check if any post data field has a value. if ( ! empty( $field_data ) && is_array( $field_data ) ) { foreach ( $field_data as $value ) { if ( '' !== $value ) { return false; } } } } elseif ( ! empty( $field_data ) || '0' === $field_data ) { $is_empty = false; } return $is_empty; } /** * Stop submission process if it has errors * * @throws Exception When there is an error. */ private static function check_errors() { /** * Filter submission errors * * @since 1.0.2 * * @param array $submit_errors - the submission errors. * @param int $form_id - the form id. * * @return array $submit_errors */ self::$submit_errors = apply_filters( 'forminator_custom_form_submit_errors', self::$submit_errors, self::$module_id, self::$info['field_data_array'] ); if ( ! empty( self::$submit_errors ) ) { throw new Exception( esc_html( self::get_invalid_form_message() ) ); } } /** * Filter field_data_array property * * @throws Exception When there is an error. */ private static function filter_field_data_array() { if ( empty( self::$info['field_data_array'] ) ) { if ( self::$is_draft ) { throw new Exception( esc_html__( 'The form is empty and cannot be saved as a draft. Please fill out at least one form field and try again.', 'forminator' ) ); } throw new Exception( esc_html__( 'At least one field must be filled out to submit the form.', 'forminator' ) ); } if ( isset( self::$prepared_data['product-shipping'] ) && intval( self::$prepared_data['product-shipping'] > 0 ) ) { self::$info['field_data_array'][] = array( 'name' => 'product_shipping', 'value' => self::$prepared_data['product-shipping'], ); } self::$info['field_data_array'][] = array( 'name' => '_forminator_user_ip', 'value' => Forminator_Geo::get_user_ip(), ); if ( ! self::$is_draft && ! empty( self::$module_settings['logged-users'] ) && ! empty( self::$module_settings['limit-per-user'] ) ) { self::$info['field_data_array'][] = array( 'name' => '_user_id', 'value' => get_current_user_id(), ); } // Add draft_page if present (based on form's pagination index). if ( isset( self::$prepared_data['draft_page'] ) ) { self::$info['field_data_array'][] = array( 'name' => 'draft_page', 'value' => self::$prepared_data['draft_page'], ); } /** * Filter saved data before persisted into the database * * @since 1.0.2 * * @param array $field_data_array - the entry data. * @param int $form_id - the form id. * * @return array $field_data_array */ self::$info['field_data_array'] = apply_filters( 'forminator_custom_form_submit_field_data', self::$info['field_data_array'], self::$module_id ); } /** * Subscriptions payment intent * * @since 1.38 * * @return null|object */ public static function subscription_payment_intent() { if ( class_exists( 'Forminator_Stripe_Subscription' ) ) { return; } try { self::prepare_fields_info(); $stripe_addon = Forminator_Stripe_Subscription::get_instance(); $field_object = Forminator_Core::get_field_object( 'stripe' ); if ( ! $field_object ) { return; } $field = self::$info['stripe_field']; $payment_plan = $field_object->get_payment_plan( $field ); $amount_type = $payment_plan['subscription_amount_type'] ?? 'fixed'; $amount = $payment_plan['subscription_amount'] ?? 0.0; if ( 'fixed' === $amount_type && empty( $amount ) ) { return; // Payment amount should be larger than 0. } return $stripe_addon->create_payment_intent( $field_object, self::$module_object, self::$prepared_data, $field, $payment_plan ); } catch ( Exception $e ) { return; } } /** * Handle stripe single payment * * @since 1.15 * * @param object $field_object Field object. * @param array $field Field data. * @param object $entry Entry. * @param array $payment_plan Entry. * * @return array|WP_ERROR * @throws Exception When there is an error. */ private static function handle_stripe_subscription( $field_object, $field, $entry, $payment_plan ) { if ( class_exists( 'Forminator_Stripe_Subscription' ) ) { try { $stripe_addon = Forminator_Stripe_Subscription::get_instance(); $amount_type = isset( $payment_plan['subscription_amount_type'] ) ? $payment_plan['subscription_amount_type'] : 'fixed'; $amount = isset( $payment_plan['subscription_amount'] ) ? $payment_plan['subscription_amount'] : 0.0; if ( 'fixed' === $amount_type && empty( $amount ) ) { throw new Exception( esc_html__( 'Payment amount should be larger than 0.', 'forminator' ) ); } $entry_data = $stripe_addon->handle_subscription( $field_object, self::$module_object, self::$prepared_data, $field, $entry, $payment_plan ); $stripe_entry_data = array( 'name' => $field['element_id'], 'value' => $entry_data, ); /** * Filter stripe entry data that might be stored/used later * * @since 1.7 * * @param array $calculation_entry_data * @param Forminator_Form_Model $module_object * @param array $field field_properties. * @param array $field_data_array * * @return array */ $stripe_entry_data = apply_filters( 'forminator_custom_form_stripe_entry_data', $stripe_entry_data, self::$module_object, $field, self::$info['field_data_array'] ); forminator_maybe_log( __METHOD__, $stripe_entry_data['value'] ); if ( is_wp_error( $stripe_entry_data['value'] ) ) { throw new Exception( $stripe_entry_data['value']->get_error_message() ); } if ( ! empty( $stripe_entry_data['value']['error'] ) ) { throw new Exception( $stripe_entry_data['value']['error'] ); } return $stripe_entry_data; } catch ( Exception $e ) { // Delete entry if paymentIntent confirmation is not successful. $entry->delete(); return new WP_Error( 'forminator_stripe_error', $e->getMessage() ); } } else { return new WP_Error( 'forminator_stripe_error', esc_html( apply_filters( 'forminator_payment_require_stripe_subscription_addon_error_message', esc_html__( 'Forminator Stripe Subscription Add-on is required to submit this form.', 'forminator' ) ) ) ); } } /** * Handle stripe single payment * * @since 1.15 * * @param array $field_object Field. * @param array $field Field data. * @param object $entry Entry. * @param string $mode Stripe payment mode. * * @return array|WP_ERROR * @throws Exception When there is an error. */ private static function handle_stripe_single( $field_object, $field, $entry, $mode ) { $entry_data = $field_object->process_to_entry_data( $field ); $stripe_entry_data = array( 'name' => $field['element_id'], 'value' => $entry_data, ); /** * Filter stripe entry data that might be stored/used later * * @since 1.7 * * @param array $calculation_entry_data * @param Forminator_Form_Model $module_object * @param array $field field_properties. * @param array $field_data_array * * @return array */ $stripe_entry_data = apply_filters( 'forminator_custom_form_stripe_entry_data', $stripe_entry_data, self::$module_object, $field, self::$info['field_data_array'] ); forminator_maybe_log( __METHOD__, $stripe_entry_data['value'] ); if ( is_wp_error( $stripe_entry_data['value'] ) ) { throw new Exception( esc_html( $stripe_entry_data['value']->get_error_message() ) ); } /** * Fires after charge stripe * * @since 1.7 * * @param Forminator_Form_Model $module_object * @param array $field field properties. * @param array $stripe_entry_data * @param array $submitted_data * @param array $field_data_array */ do_action( 'forminator_custom_form_after_stripe_charge', self::$module_object, $field, $stripe_entry_data, self::$prepared_data, self::$info['field_data_array'] ); // Try to get Payment Intent from submitted date. try { $intent = $field_object->get_paymentIntent( $field ); if ( is_wp_error( $intent ) ) { return $intent; } // Don't process confirm if status is requires_capture as it confirmed already. if ( 'requires_confirmation' === $intent->status ) { $result = $intent->confirm( array( 'return_url' => Forminator_Stripe::get_return_url(), ) ); } else { $result = $intent; } // If we have 3D security on the card return for verification. if ( 'requires_action' === $result->status || 'requires_confirmation' === $result->status ) { $error_data = self::handle_failed_stripe_response( $result, $entry ); self::$response_attrs = array_merge( self::$response_attrs, $error_data ); self::$response_attrs['secret'] = $result->client_secret; return new WP_Error( 'forminator_stripe_error', esc_html( $error_data['message'] ) ); } } catch ( Exception $e ) { // Delete entry if capture is not successful. $entry->delete(); return new WP_Error( 'forminator_stripe_error', $e->getMessage() ); } if ( 'succeeded' !== $intent->status ) { // Delete entry if capture is not successful. $entry->delete(); return new WP_Error( 'forminator_stripe_error', esc_html__( 'Payment failed, please try again!', 'forminator' ) ); } $result = array( 'status' => 'COMPLETED', 'transaction_id' => $intent->id, 'transaction_link' => $field_object::get_transanction_link( $mode, $intent->id ), ); $stripe_entry_data['value'] = array_merge( $stripe_entry_data['value'], $result ); return $stripe_entry_data; } /** * Handle stripe failed response * * @param object $result Stripe result. * @param object $entry Entry object. * * @return array */ public static function handle_failed_stripe_response( $result, $entry ) { // Delete entry if 3d security or additional confirmation is needed, we will store it on next attempt. $entry->delete(); $error_data = array( 'message' => __( 'This payment requires additional authentication! Please follow the instructions.', 'forminator' ), ); if ( ! empty( $result->next_action->redirect_to_url->url ) && 0 !== strpos( $result->next_action->redirect_to_url->url, 'https://hooks.stripe.com' ) ) { $error_data['redirect_to_url'] = $result->next_action->redirect_to_url->url; } elseif ( ! empty( $result->next_action->alipay_handle_redirect->url ) ) { $error_data['redirect_to_url'] = $result->next_action->alipay_handle_redirect->url; } elseif ( ! empty( $result->next_action->wechat_pay_display_qr_code->data ) ) { $error_data['redirect_to_url'] = $result->next_action->wechat_pay_display_qr_code->data; } elseif ( ! empty( $result->next_action->cashapp_handle_redirect_or_display_qr_code->mobile_auth_url ) ) { $error_data['redirect_to_url'] = $result->next_action->cashapp_handle_redirect_or_display_qr_code->mobile_auth_url; } else { $error_data['stripe3d'] = true; $error_data['message'] = __( 'This payment requires 3D Secure authentication! Please follow the instructions.', 'forminator' ); } return apply_filters( 'forminator_stripe_next_action_after_payment_confirmation', $error_data, $result ); } /** * Handle stripe payments * * @param object $entry Entry. * @return array */ private static function handle_stripe( $entry ) { if ( self::$is_draft || self::$is_spam ) { return; } $stripe = new Forminator_Gateway_Stripe(); if ( ! $stripe->is_ready() || ! self::$info['stripe_field'] ) { return; } self::stripe_field_to_entry_data_array( $entry ); } /** * Handle paypal * * @param object $entry Entry. * @return array * @throws Exception When there is an error. */ private static function handle_paypal( $entry ) { if ( self::$is_draft || self::$is_spam ) { return; } if ( ! self::$info['paypal_field'] ) { return; } if ( self::$module_object->is_payment_require_ssl() && ! is_ssl() ) { throw new Exception( esc_html( apply_filters( 'forminator_payment_require_ssl_error_message', esc_html__( 'SSL required to submit this form, please check your URL.', 'forminator' ) ) ) ); } self::paypal_field_to_entry_data_array( $entry ); } /** * Handle form * * @since 1.0 * @since 1.1 change superglobal POST to `get_post_data` * @since 1.5.1 utilize `_post_data` which already defined on submit * * @param bool $preview Is preview. * * @return array|bool */ public function handle_form( $preview = false ) { if ( ! self::$module_object ) { return false; } try { self::can_submit(); self::prepare_fields_info(); self::check_captcha(); $entry = self::get_entry(); self::maybe_login( $entry ); $passed = self::is_honeypot(); if ( ! $passed ) { // show success but dont save form. return self::return_success(); } if ( self::is_spam() ) { $entry->is_spam = 1; self::$is_spam = true; } // If preview, skip integrations. if ( ! $preview ) { self::attach_addons_on_form_submit(); $entry->draft_id = $this->set_entry_draft_id(); if ( self::$is_draft || ! self::prevent_store() ) { $entry->save( null, null, self::$previous_draft_id ); } } self::process_uploads( 'upload' ); self::handle_stripe( $entry ); self::handle_paypal( $entry ); self::process_uploads( 'transfer' ); self::maybe_create_post(); // save field_data_array with password field for registration forms. $data_for_registration = self::$info['field_data_array']; self::save_entry_fields( $entry ); self::attach_addons_after_entry_saved( $entry ); self::maybe_registration( $entry, $data_for_registration ); self::send_email( $entry ); $response = self::get_response( $entry ); } catch ( Exception $e ) { return self::return_error( $e->getMessage() ); } return $response; } /** * Send email * * @param object $entry Entry. */ private static function send_email( $entry ) { if ( ! self::$is_leads && ! self::$is_draft && ! self::$is_spam ) { $forminator_mail_sender = new Forminator_CForm_Front_Mail(); $forminator_mail_sender->process_mail( self::$module_object, $entry ); } } /** * Save entry fields * * @param object $entry Entry object. */ private static function save_entry_fields( $entry ) { self::remove_password(); self::handle_hidden_fields_after_entry_save( $entry, self::$module_id ); /** * Action called before setting fields to database * * @since 1.0.2 * * @param Forminator_Form_Entry_Model $entry - the entry model. * @param int $form_id - the form id. * @param array $field_data_array - the entry data. */ do_action( 'forminator_custom_form_submit_before_set_fields', $entry, self::$module_id, self::$info['field_data_array'] ); // ADDON add_entry_fields. // @since 1.2 Add field_data_array to param. $added_data_array = self::$info['field_data_array']; if ( ! self::$is_draft ) { $added_data_array = self::attach_addons_add_entry_fields( $added_data_array, $entry ); $added_data_array = self::replace_values_to_labels( $added_data_array, $entry ); } else { // remove IP for drafts. $ip_key = array_search( '_forminator_user_ip', array_column( $added_data_array, 'name' ), true ); if ( false !== $ip_key ) { unset( $added_data_array[ $ip_key ] ); } } if ( self::$is_leads ) { self::$response_attrs['entry_id'] = $entry->entry_id; $added_data_array[] = array( 'name' => 'skip_form', 'value' => '0', ); } $entry->set_fields( $added_data_array ); } /** * Prepare submitted data to sending to addons * * @param array $current_entry_fields Entry fields. * @return array */ protected static function get_prepared_submitted_data_for_addons( $current_entry_fields ) { $data = self::get_submitted_data(); foreach ( wp_list_pluck( $current_entry_fields, 'name' ) as $element_id ) { $data[ $element_id ] = Forminator_Integration_Form_Hooks::prepare_field_value_for_addon( $element_id, $current_entry_fields, $data ); } $data = Forminator_Integration_Form_Hooks::prepare_stripe_subscription_id_for_addon( $data, $current_entry_fields ); // Remove technical info. $data = array_filter( $data, function ( $key ) { return 0 !== strpos( $key, 'group-' ) || '-copies' !== substr( $key, -7 ); }, ARRAY_FILTER_USE_KEY ); return $data; } /** * Get post data fields and replace calculation fields placeholders in Custom Fields * * @return array */ private static function get_post_data_fields() { // Get saved postdata fields data. $postdata_fields = self::get_specific_field_data( 'postdata' ); if ( empty( $postdata_fields ) ) { return; } // Replace calculation fields placeholders in Custom Fields. foreach ( $postdata_fields as $field_key => $field ) { if ( empty( $field['field_array']['options'] ) || ! is_array( $field['field_array']['options'] ) ) { continue; } $custom_fields = wp_list_pluck( $field['field_array']['options'], 'value' ); foreach ( $custom_fields as $cf_key => $cf_value ) { if ( strpos( $cf_value, '{calculation-' ) === false ) { continue; } $value = forminator_replace_form_data( $cf_value, self::$module_object ); $postdata_fields[ $field_key ]['value']['post-custom'][ $cf_key ]['value'] = $value; } } return $postdata_fields; } /** * Maybe create post * * @throws Exception When there is an error. */ private static function maybe_create_post() { if ( self::$is_draft || self::$is_spam ) { return; } // Get saved postdata fields data and replace upload tags with uploaded data. $postdata_fields = self::get_post_data_fields(); if ( empty( $postdata_fields ) ) { return; } $postdata_return = self::create_post_from_postdata( $postdata_fields ); if ( isset( $postdata_return['type'] ) && 'error' === $postdata_return['type'] ) { throw new Exception( esc_html( $postdata_return['value'] ) ); } foreach ( $postdata_return as $postdata ) { if ( 'success' === $postdata['type'] ) { foreach ( self::$info['field_data_array'] as $field_key => $field_datum ) { if ( $field_datum['name'] === $postdata['field_id'] ) { self::$info['field_data_array'][ $field_key ] = array( 'name' => $postdata['field_id'], 'value' => $postdata['field_data'], ); } } } else { throw new Exception( esc_html( $postdata['value'] ) ); } } } /** * Get submission response * * @param object $entry Form entry object. * @return mixed */ private static function get_response( $entry ) { if ( self::$is_draft ) { return self::get_draft_response( $entry ); } self::set_behaviour_settings( $entry ); $response = self::return_success(); if ( empty( self::$module_settings['enable-ajax'] ) ) { $is_ajax_enabled = false; } else { $is_ajax_enabled = filter_var( self::$module_settings['enable-ajax'], FILTER_VALIDATE_BOOLEAN ); } if ( $is_ajax_enabled ) { // Hide select options that already are reached limit. $response['select_field'] = self::get_limited_select_values(); } $response = self::handle_product_fields( $response, $entry ); return $response; } /** * Get draft response * * @param object $entry Form entry object. * @return type */ private static function get_draft_response( $entry ) { $setting = self::$module_settings; // Will be used to auto-fill the email field in send draft link form. $first_email = self::get_first_email( self::$prepared_data ); if ( ! is_null( $first_email ) ) { self::$response_attrs['first_email'] = $first_email; } self::$response_attrs['draft_id'] = $entry->draft_id; self::$response_attrs['page_id'] = self::$prepared_data['page_id']; self::$response_attrs['enable_email_link'] = isset( $setting['sc_email_link'] ) ? filter_var( $setting['sc_email_link'], FILTER_VALIDATE_BOOLEAN ) : true; self::$response_attrs['email_label'] = isset( $setting['sc_email_input_label'] ) ? $setting['sc_email_input_label'] : esc_html__( 'Send draft link to', 'forminator' ); self::$response_attrs['email_placeholder'] = isset( $setting['sc_email_placeholder'] ) ? $setting['sc_email_placeholder'] : esc_html__( 'E.g., johndoe@gmail.com', 'forminator' ); self::$response_attrs['email_button_label'] = isset( $setting['sc_email_button_label'] ) ? $setting['sc_email_button_label'] : esc_html__( 'Send draft link', 'forminator' ); self::$response_attrs['retention_period'] = isset( $setting['sc_draft_retention'] ) ? $setting['sc_draft_retention'] : 30; return self::return_success( $setting['sc_message'] ); } /** * Handle product fields * * @param array $response Response. * @param object $entry Form entry object. */ private static function handle_product_fields( $response, $entry ) { $product_fields = self::get_specific_field_data( 'product' ); if ( ! empty( $product_fields ) ) { // Process purchase. $page_id = self::$prepared_data['page_id']; // use page id to get permalink for redirect. $shipping = isset( self::$prepared_data['product-shipping'] ) ? self::$prepared_data['product-shipping'] : 0; /** * Process purchase * * @since 1.0.0 * * @param array $response - the response array. * @param array $product_fields - the product fields. * @param int $entry_id - the entry id ( reference for callback). * @param int $page_id - the page id. Used to generate a return url. * @param int $shipping - the shipping cost. */ $response = apply_filters( 'forminator_cform_process_purchase', $response, $product_fields, self::$info['field_data_array'], $entry->entry_id, $page_id, $shipping ); } return $response; } /** * Get product field data * * @param string $type Field type. * @return array * @throws Exception When there is an error. */ private static function get_specific_field_data( $type ) { $product_fields = array(); foreach ( self::$info['field_data_array'] as $data ) { if ( ! isset( $data['field_type'] ) || $type !== $data['field_type'] ) { continue; } $product_fields[] = $data; } return $product_fields; } /** * Get fields * * @throws Exception When there is an error. */ private static function get_fields() { $fields = self::$module_object->get_real_fields(); if ( ! $fields ) { throw new Exception( esc_html__( 'At least one field must be filled out to submit the form.', 'forminator' ) ); } return $fields; } /** * Check if submission is possible. * * @throws Exception When there is an error. */ private static function can_submit() { $form_submit = self::$module_object->form_can_submit(); if ( ! $form_submit['can_submit'] ) { throw new Exception( esc_html( $form_submit['error'] ) ); } } /** * Honeypot check * * @return boolean */ private static function is_honeypot() { if ( isset( self::$module_settings['honeypot'] ) && filter_var( self::$module_settings['honeypot'], FILTER_VALIDATE_BOOLEAN ) ) { $total_fields = count( self::$module_object->get_real_fields() ) + 1; if ( ! empty( self::$prepared_data[ "input_$total_fields" ] ) ) { return false; } } return true; } /** * Set behavior settings * * @param object $entry Entry. */ private static function set_behaviour_settings( $entry ) { $all_behaviours = array( 'behaviour-thankyou', 'behaviour-hide', 'behaviour-redirect' ); $behavior_options = self::get_relevant_behavior_options(); if ( ! isset( $behavior_options['submission-behaviour'] ) || ! in_array( $behavior_options['submission-behaviour'], $all_behaviours, true ) ) { return; } $custom_form = self::$module_object; self::$response_attrs['behav'] = self::get_submission_behaviour( $behavior_options ); if ( 'behaviour-redirect' === $behavior_options['submission-behaviour'] && ! empty( $behavior_options['redirect-url'] ) ) { self::$response_attrs['redirect'] = true; $url_encode = true; if ( '{' === substr( $behavior_options['redirect-url'], 0, 1 ) && '}' === substr( $behavior_options['redirect-url'], -1 ) ) { $url_encode = false; } // replace form data vars with value. $redirect_url = forminator_replace_form_data( $behavior_options['redirect-url'], $custom_form, $entry, false, $url_encode ); $redirect_url = html_entity_decode( $redirect_url ); $tab_value = isset( $behavior_options['newtab'] ) ? $behavior_options['newtab'] : 'sametab'; $newtab = forminator_replace_form_data( $tab_value, $custom_form, $entry ); // replace misc data vars with value. $redirect_url = forminator_replace_variables( $redirect_url, self::$module_id ); $newtab = forminator_replace_variables( $newtab, self::$module_id ); self::$response_attrs['url'] = esc_url_raw( $redirect_url ); self::$response_attrs['newtab'] = esc_html( $newtab ); } $thankyou_message = self::get_thankyou_message( $custom_form, $behavior_options, $entry ); if ( ( ! isset( $tab_value ) || 'newtab_thankyou' === $tab_value ) && ! empty( $thankyou_message ) ) { self::$response_attrs['message'] = $thankyou_message; if ( ! empty( $behavior_options['autoclose'] ) ) { self::$response_attrs['fadeout'] = $behavior_options['autoclose']; self::$response_attrs['fadeout_time'] = ! empty( $behavior_options['autoclose-time'] ) ? $behavior_options['autoclose-time'] * 1000 : 0; } } } /** * Get "Thank you" message * * @param object $custom_form Custom form. * @param array $behavior_options Releavant behavior options. * @param object $entry Entry object. * @return type */ private static function get_thankyou_message( $custom_form, $behavior_options, $entry ) { if ( ! empty( $custom_form->settings['activation-method'] ) && isset( $behavior_options[ $custom_form->settings['activation-method'] . '-thankyou-message' ] ) ) { $thankyou_message = $behavior_options[ $custom_form->settings['activation-method'] . '-thankyou-message' ]; } elseif ( isset( $behavior_options['thankyou-message'] ) ) { $thankyou_message = $behavior_options['thankyou-message']; } else { $thankyou_message = ''; } /** * Filter thankyou message * * @since 1.11 * * @param string $thankyou_message "Thank you" message. * @param array $submitted_data * @param Forminator_Form_Model $custom_form * * @return string */ $thankyou_message = apply_filters( 'forminator_custom_form_thankyou_message', $thankyou_message, $custom_form ); // replace form data vars with value. $thankyou_message = forminator_replace_form_data( $thankyou_message, $custom_form, $entry, true ); // replace misc data vars with value. $message = forminator_replace_variables( $thankyou_message, self::$module_id ); return $message; } /** * Get submission behavior * * @param array $behavior_options Behavior settings. * @return string */ private static function get_submission_behaviour( $behavior_options ) { $submission_behaviour = 'behaviour-thankyou'; if ( isset( $behavior_options['submission-behaviour'] ) ) { $submission_behaviour = $behavior_options['submission-behaviour']; } // If Stripe field exist & submit is AJAX we fall back to hide to force page reload when form submitted. if ( ! empty( self::$info['stripe_field'] ) && self::$module_object->is_ajax_submit() ) { $submission_behaviour = 'behaviour-hide'; } $submission_behaviour = apply_filters( 'forminator_custom_form_get_submission_behaviour', $submission_behaviour, self::$module_id, $behavior_options ); return $submission_behaviour; } /** * Get the relevant behavior which will be applied according conditions * * @return array|false Return the relevant behavior or false if no behavior found. */ private static function get_relevant_behavior_options() { $behavior_array = self::$module_object->get_behavior_array(); foreach ( $behavior_array as $behavior ) { if ( empty( $behavior['conditions'] ) ) { // If this behavior doesn't have any conditions - return it. return $behavior; } $condition_rule = isset( $behavior['condition_rule'] ) ? $behavior['condition_rule'] : 'all'; $condition_fulfilled = 0; foreach ( $behavior['conditions'] as $condition ) { $is_matched = Forminator_Field::is_condition_matched( $condition ); if ( $is_matched ) { if ( 'any' === $condition_rule ) { // If this behavior is matched the conditions - return it. No need to check others. return $behavior; } ++$condition_fulfilled; } } if ( 'all' === $condition_rule && count( $behavior['conditions'] ) === $condition_fulfilled ) { // Return this behavior if all conditions are matched. return $behavior; } } // If all behaviors aren't matched - return false. return false; } /** * Get select values according limit. * * @return array */ private static function get_limited_select_values() { $result = array(); if ( self::$is_draft || empty( self::$info['select_field_value'] ) ) { return $result; } foreach ( self::$info['select_field_value'] as $select_name => $options ) { $select_value = array(); foreach ( $options as $option ) { if ( Forminator_Form_Entry_Model::is_option_limit_reached( self::$module_id, $select_name, $option['type'], $option ) ) { $select_value[] = $option; } } if ( ! empty( $select_value ) ) { $result[ $select_name ] = $select_value; } } return $result; } /** * Remove a password field. */ private static function remove_password() { foreach ( self::$info['field_data_array'] as $key => $field_arr ) { if ( false !== stripos( $field_arr['name'], 'password-' ) ) { unset( self::$info['field_data_array'][ $key ] ); break; } } } /** * Replace values to labels for radios, selectboxes and checkboxes * * @param array $data Data. * @param array $entry Entry. * @return array */ private static function replace_values_to_labels( $data, $entry ) { foreach ( $data as $key => $value ) { if ( empty( $value['name'] ) ) { continue; } $slug = $value['name']; if ( strpos( $slug, 'radio' ) !== false || strpos( $slug, 'select' ) !== false || strpos( $slug, 'checkbox' ) !== false ) { $data[ $key ]['value'] = forminator_replace_form_data( '{' . $slug . '}', self::$module_object, $entry, true ); } } return $data; } /** * Multiple File upload for ajax multi-upload */ public function multiple_file_upload() { $this->init_properties(); if ( ! isset( self::$prepared_data['nonce'] ) || ! wp_verify_nonce( self::$prepared_data['nonce'], 'forminator_submit_form' . self::$module_id ) ) { wp_send_json_error( new WP_Error( 'invalid_code' ) ); } $fields = self::$module_object->get_fields(); foreach ( $fields as $field ) { $field_array = $field->to_formatted_array(); $element_id = esc_html( $field_array['element_id'] ); $field_type = isset( $field_array['type'] ) ? esc_html( $field_array['type'] ) : ''; if ( isset( self::$prepared_data['element_id'] ) && 'upload' === $field_type && self::$prepared_data['element_id'] === $element_id ) { $upload_field_obj = Forminator_Core::get_field_object( $field_type ); $response = $upload_field_obj->handle_file_upload( self::$module_id, $field_array, self::$prepared_data, 'upload' ); if ( ! $response['success'] || isset( $response['errors'] ) ) { wp_send_json_error( $response ); } else { wp_send_json_success( $response ); } } } } /** * Response message * * @since 1.0 * @since 1.1 change superglobal POST to `get_post_data` * @since 1.5.1 utilize `_post_data` which already defined on submit * * @param int $form_id Form Id. * @param int $render_id Render Id. */ public function form_response_message( $form_id, $render_id ) { $post_render_id = isset( self::$prepared_data['render_id'] ) ? sanitize_text_field( self::$prepared_data['render_id'] ) : 0; $response = self::$response; // only show to related form. if ( ! empty( $response ) && is_array( $response ) && (int) $form_id === (int) self::$module_id && (int) $render_id === (int) $post_render_id ) { $label_class = $response['success'] ? 'forminator-success' : 'forminator-error'; ?> <div class="forminator-response-message forminator-show <?php echo esc_attr( $label_class ); ?>" tabindex="-1"> <label class="forminator-label--<?php echo esc_attr( $label_class ); ?>"><?php echo wp_kses_post( $response['message'] ); ?></label> <?php if ( isset( $response['errors'] ) && ! empty( $response['errors'] ) ) { ?> <ul class="forminator-screen-reader-only"> <?php foreach ( $response['errors'] as $key => $error ) { foreach ( $error as $id => $value ) { ?> <li><?php echo esc_html( $value ); ?></li> <?php } } ?> </ul> <?php } ?> </div> <?php if ( isset( $response['success'] ) && $response['success'] && isset( $response['behav'] ) && ( 'behaviour-hide' === $response['behav'] || ( isset( $response['newtab'] ) && 'newtab_hide' === $response['newtab'] ) ) ) { $selector = '#forminator-module-' . $form_id . '[data-forminator-render="' . $render_id . '"]'; ?> <script type="text/javascript">var ForminatorFormHider = <?php echo wp_json_encode( array( 'selector' => $selector, ) ); ?> </script> <?php } if ( isset( $response['success'] ) && $response['success'] && isset( $response['behav'] ) && 'behaviour-redirect' === $response['behav'] && isset( $response['newtab'] ) && ( 'newtab_hide' === $response['newtab'] || 'newtab_thankyou' === $response['newtab'] ) ) { $url = $response['url']; ?> <script type="text/javascript">var ForminatorFormNewTabRedirect = <?php echo wp_json_encode( array( 'url' => $url, ) ); ?> </script> <?php } } } /** * Get invalid form message * * @since 1.0 * * @return mixed */ private static function get_invalid_form_message() { $invalid_form_message = esc_html__( 'Error: Your form is not valid, please fix the errors!', 'forminator' ); if ( ! empty( self::$module_settings['submitData']['custom-invalid-form-message'] ) ) { $invalid_form_message = self::$module_settings['submitData']['custom-invalid-form-message']; } return apply_filters( 'forminator_custom_form_invalid_form_message', $invalid_form_message, self::$module_id ); } /** * Executor On form submit for attached addons * * @see Forminator_Integration_Form_Hooks::on_module_submit() * @since 1.1 * * @return bool true on success|string error message from addon otherwise * @throws Exception When there is an error. */ private static function attach_addons_on_form_submit() { if ( self::$is_draft || self::$is_spam ) { return; } // find is_form_connected. $connected_addons = forminator_get_addons_instance_connected_with_module( self::$module_id, 'form' ); foreach ( $connected_addons as $connected_addon ) { try { $form_hooks = $connected_addon->get_addon_hooks( self::$module_id, 'form' ); if ( ! $form_hooks instanceof Forminator_Integration_Form_Hooks ) { continue; } $addon_return = $form_hooks->on_module_submit( self::$prepared_data ); } catch ( Exception $e ) { forminator_addon_maybe_log( $connected_addon->get_slug(), 'failed to attach_addons_on_form_submit', $e->getMessage() ); } if ( true !== $addon_return ) { throw new Exception( esc_html( $addon_return ) ); } } return true; } /** * Process stripe charge * * @since 1.7 * @param object $entry Entry. * * @return array * @throws Exception When there is an error. */ private static function stripe_field_to_entry_data_array( $entry ) { $field_object = Forminator_Core::get_field_object( 'stripe' ); if ( ! $field_object ) { return; } $field = self::$info['stripe_field']; /** * Fires before process stripe * * @since 1.7 * * @param Forminator_Form_Model $module_object * @param array $field field properties. * @param array $submitted_data * @param array $field_data_array */ do_action( 'forminator_custom_form_before_stripe_charge', self::$module_object, $field, self::$prepared_data, self::$info['field_data_array'] ); $payment_plan = $field_object->get_payment_plan( $field ); if ( 'single' === $payment_plan['payment_method'] ) { $mode = isset( $field['mode'] ) ? $field['mode'] : 'sandbox'; $plan_data_array = self::handle_stripe_single( $field_object, $field, $entry, $mode ); } else { $plan_data_array = self::handle_stripe_subscription( $field_object, $field, $entry, $payment_plan ); } if ( is_wp_error( $plan_data_array ) ) { throw new Exception( esc_html( $plan_data_array->get_error_message() ) ); } if ( ! empty( $plan_data_array ) ) { self::$info['field_data_array'][] = $plan_data_array; } } /** * Process PayPal charge * * @since 1.7 * @param object $entry Entry. * * @return array * @throws Exception When there is an error. */ private static function paypal_field_to_entry_data_array( $entry ) { $field_object = Forminator_Core::get_field_object( 'paypal' ); if ( ! $field_object ) { return; } $field = self::$info['paypal_field']; /** * Fires before process paypal * * @since 1.7 * * @param Forminator_Form_Model $module_object * @param array $field field properties. * @param array $submitted_data * @param array $field_data_array */ do_action( 'forminator_custom_form_before_paypal_charge', self::$module_object, $field, self::$prepared_data, self::$info['field_data_array'] ); $entry_data = $field_object->process_to_entry_data( $field ); $paypal_entry_data = array( 'name' => $field['element_id'], 'value' => $entry_data, ); /** * Filter paypal entry data that might be stored/used later * * @since 1.7 * * @param array $calculation_entry_data * @param Forminator_Form_Model $module_object * @param array $field field_properties. * @param array $field_data_array * * @return array */ $paypal_entry_data = apply_filters( 'forminator_custom_form_paypal_entry_data', $paypal_entry_data, self::$module_object, $field, self::$info['field_data_array'] ); if ( empty( $paypal_entry_data ) ) { return; } forminator_maybe_log( __METHOD__, $paypal_entry_data['value'] ); if ( ! empty( $paypal_entry_data['value']['error'] ) ) { throw new Exception( esc_html( $paypal_entry_data['value']['error'] ) ); } /** * Fires after charge paypal * * @since 1.7 * * @param Forminator_Form_Model $module_object * @param array $field field properties. * @param array $paypal_entry_data * @param array $submitted_data * @param array $field_data_array */ do_action( 'forminator_custom_form_after_paypal_charge', self::$module_object, $field, $paypal_entry_data, self::$prepared_data, self::$info['field_data_array'] ); $paypal = new Forminator_PayPal_Express(); $mode = isset( $field['mode'] ) ? $field['mode'] : 'sandbox'; $capture = $paypal->capture_order( $entry_data['transaction_id'], $mode ); if ( ! isset( $capture->status ) || 'COMPLETED' !== $capture->status ) { // Delete entry if capture is not successful. $entry->delete(); throw new Exception( esc_html__( 'Payment failed, please try again!', 'forminator' ) ); } $paypal_entry_data['value']['status'] = 'COMPLETED'; if ( isset( $capture->purchase_units[0]->payments->captures[0]->id ) ) { $transaction_id = $capture->purchase_units[0]->payments->captures[0]->id; $paypal_entry_data['value']['transaction_id'] = $transaction_id; $paypal_entry_data['value']['transaction_link'] = $field_object::get_transanction_link( $mode, $transaction_id ); } self::$info['field_data_array'][] = $paypal_entry_data; } /** * Prepare hidden and visible fields */ public static function check_fields_visibility() { $fields = self::$module_object->get_fields(); $visible_fields = array(); // Visible fields with calculable values. $unspecified = array(); // it's not clear these fields are hidden or visible. $field_slugs = wp_list_pluck( $fields, 'slug' ); do { // We do it recursevely because sometimes fields on which visibility depends are placed in the array after dependent fields. $previous_unspecified = $unspecified; $unspecified = array(); foreach ( $fields as $field ) { $field_settings = $field->to_formatted_array(); $field_id = Forminator_Field::get_property( 'element_id', $field_settings ); $group_suffix = ''; $i = 1; $group_copies = ! empty( self::$prepared_data[ $field->parent_group . '-copies' ] ) ? self::$prepared_data[ $field->parent_group . '-copies' ] : array(); do { // Do it recursevely for repeated fields. if ( $i > 1 ) { $group_suffix = '-' . $i; } // Skip if this field is already checked. if ( in_array( $field_id . $group_suffix, array_keys( $visible_fields ), true ) || in_array( $field_id . $group_suffix, self::$hidden_fields, true ) ) { continue; } $conditions = Forminator_Field::get_field_conditions( $field_settings, $group_suffix ); $field_type = Forminator_Field::get_property( 'type', $field_settings ); $field_object = Forminator_Core::get_field_object( $field_type ); // Skip if field object is not found. if ( empty( $field_object ) ) { continue; } // if it's stripe field and there is stripe OCS field - skip it. if ( 'stripe' === $field_type && in_array( 'stripe-ocs-1', $field_slugs, true ) ) { continue; } if ( 'stripe-ocs' === $field_type && 'true' === filter_input( INPUT_POST, 'stripe-intent' ) ) { // Do not skip saving 'stripe_field' - even if they unspecified some code uses them. self::$info['stripe_field'] = $field_settings; } if ( $conditions ) { $dependent_fields = wp_list_pluck( $conditions, 'element_id' ); $depends = self::dependencies_not_ready( $dependent_fields, $visible_fields ); if ( $depends ) { $unspecified[ $field_id . $group_suffix ] = $conditions; continue; } else { $is_hidden = Forminator_Field::is_hidden( $field_settings, array( 'conditions' => $conditions ), $group_suffix ); if ( $is_hidden ) { self::update_hidden_fields_array( $field_id, $group_suffix, $field_settings ); continue; } } } $submitted_field_data = self::$prepared_data[ $field_id . $group_suffix ] ?? null; $calculable_value = $field_object::get_calculable_value( $submitted_field_data, $field_settings ); if ( 'calculation' !== $field_type ) { if ( in_array( $field_type, array( 'stripe', 'stripe-ocs', 'paypal' ), true ) ) { $dependent_fields = $field_object->get_amount_dependent_fields( $field_settings ); $depends = self::dependencies_not_ready( $dependent_fields, $visible_fields ); if ( $depends ) { $unspecified[ $field_id ] = true; continue; } $amount = $field_object->get_payment_amount( $field_settings ); $visible_fields[ $field_id ] = $amount; if ( ! empty( self::$prepared_data[ $field_id ] ) ) { self::$prepared_data['payment_transaction_id'] = self::$prepared_data[ $field_id ]; } self::$prepared_data[ $field_id ] = $amount; // Save 'stripe_field' and 'paypal_field'. $payment_key = str_replace( '-ocs', '', $field_type ) . '_field'; self::$info[ $payment_key ] = $field_settings; } else { $not_calculable = $calculable_value === $field_object::FIELD_NOT_CALCULABLE; $visible_fields[ $field_id . $group_suffix ] = $not_calculable ? $submitted_field_data : $calculable_value; if ( $not_calculable ) { self::$not_calculable[] = $field_id . $group_suffix; } $visible_fields = self::prepare_subfields( $visible_fields, $field_settings, $field_object, $group_suffix ); $method = 'handle_' . $field_type . '_field'; if ( method_exists( self::class, $method ) ) { if ( ! $group_suffix ) { $dependent_fields = self::$method( $field_settings ); } else { $cloned_field_settings = $field_settings; $cloned_field_settings['element_id'] .= $group_suffix; $dependent_fields = self::$method( $cloned_field_settings ); } if ( is_array( $dependent_fields ) && $dependent_fields ) { $depends = self::dependencies_not_ready( $dependent_fields, $visible_fields ); if ( $depends ) { $unspecified[ $field_id . $group_suffix ] = true; unset( $visible_fields[ $field_id . $group_suffix ], self::$prepared_data[ $field_id . $group_suffix ] ); } } } } continue; } elseif ( $field->parent_group ) { $grouped_fields = self::$module_object->get_grouped_fields_slugs( $field->parent_group ); $calculable_value = $field_object::get_calculable_repeater_value( $submitted_field_data, $field_settings, $group_suffix, $grouped_fields ); } // handle calculation field. $formula = $calculable_value; $formula = self::maybe_replace_groupped_fields( $formula ); $fields_in_formula = self::calculator_pull_fields( $formula ); $depends = self::dependencies_not_ready( $fields_in_formula[1], $visible_fields ); if ( $depends ) { $unspecified[ $field_id . $group_suffix ] = $formula; continue; } $result = self::calculate_formula( $formula, $visible_fields, $field_settings ); $visible_fields[ $field_id . $group_suffix ] = $result; // Store result of calculation field. self::$prepared_data[ $field_id . $group_suffix ] = $result; $formatting_result = Forminator_Field::forminator_number_formatting( $field_settings, $result ); $calculation_entry_data = array( 'name' => $field_id . $group_suffix, 'value' => array( 'result' => $result, 'formatting_result' => $formatting_result, ), ); self::$info['field_data_array'][] = $calculation_entry_data; } while ( ! empty( $field->parent_group ) && in_array( ( ++$i ), $group_copies, true ) ); } } while ( $unspecified && $previous_unspecified !== $unspecified ); if ( $unspecified ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log error_log( '[Forminator] Unspecified fields ' . wp_json_encode( array_keys( $unspecified ) ) ); self::$hidden_fields = array_merge( self::$hidden_fields, array_keys( $unspecified ) ); } /** * Filter Handled submitted data on Custom Form * * @param array $prepared_data * @param Forminator_Form_Model $module_object * * @return array */ self::$prepared_data = apply_filters( 'forminator_prepared_data', self::$prepared_data, self::$module_object ); } /** * Add $field_id and its subfields to $hidden_fields array * * @param string $field_id Field slug. * @param string $group_prefix Group prefix. * @param array $field_settings Field settings. */ private static function update_hidden_fields_array( $field_id, $group_prefix, $field_settings ) { $full_id = $field_id . $group_prefix; self::$hidden_fields[] = $full_id; $to_zero = ! empty( $field_settings['hidden_behavior'] ) && 'zero' === $field_settings['hidden_behavior']; if ( $to_zero ) { self::$replace_to_zero[] = $full_id; } if ( 'group-' === substr( $field_id, 0, 6 ) ) { $group_fields = self::$module_object->get_grouped_fields( $field_id ); foreach ( $group_fields as $field ) { $subfield_settings = $field->to_formatted_array(); self::update_hidden_fields_array( $field->slug, '', $subfield_settings ); } return; } unset( self::$prepared_data[ $full_id ] ); $field_suffix = Forminator_Form_Entry_Model::field_suffix(); foreach ( $field_suffix as $suffix ) { $mod_field_id = $field_id . '-' . $suffix . $group_prefix; self::$hidden_fields[] = $mod_field_id; unset( self::$prepared_data[ $mod_field_id ] ); if ( $to_zero ) { self::$replace_to_zero[] = $mod_field_id; } } } /** * Check if all dependent fields are already defined * * @param array $dependent_fields Dependent fields. * @param array $visible_fields Visible fields. * @return boolean */ private static function dependencies_not_ready( $dependent_fields, $visible_fields ) { $unspecified_depend_fields = array_diff( $dependent_fields, array_keys( $visible_fields ), self::$hidden_fields ); if ( $unspecified_depend_fields ) { return true; } return false; } /** * Prepare subfields * * @param array $visible_fields Visible fields. * @param array $field_settings Field settings. * @param object $field_object Field object. * @param string $group_prefix Group prefix. */ private static function prepare_subfields( $visible_fields, $field_settings, $field_object, $group_prefix = '' ) { $base_id = Forminator_Field::get_property( 'element_id', $field_settings ); $field_id = $base_id . $group_prefix; if ( isset( self::$prepared_data[ $field_id ] ) ) { return $visible_fields; } $field_type = Forminator_Field::get_property( 'type', $field_settings ); $field_suffix = Forminator_Form_Entry_Model::field_suffix(); foreach ( $field_suffix as $suffix ) { $mod_field_id = $base_id . '-' . $suffix . $group_prefix; if ( isset( self::$prepared_data[ $mod_field_id ] ) ) { // Add subfield to $visible_fields array. $visible_fields[ $mod_field_id ] = self::$prepared_data[ $mod_field_id ]; self::$prepared_data[ $field_id ][ $suffix ] = self::$prepared_data[ $mod_field_id ]; } elseif ( isset( $_FILES[ $mod_field_id ] ) && // phpcs:ignore WordPress.Security.NonceVerification.Missing 'postdata' === $field_type && 'post-image' === $suffix && ! self::$is_draft ) { $post_image = $field_object->upload_post_image( $field_settings, $mod_field_id ); if ( is_array( $post_image ) && $post_image['attachment_id'] > 0 ) { self::$prepared_data[ $field_id ]['post-image'] = $post_image; self::$prepared_data[ $mod_field_id ] = $post_image; } else { self::$prepared_data[ $field_id ]['post-image'] = ''; self::$prepared_data[ $mod_field_id ] = ''; } } } return $visible_fields; } /** * Maybe replace groupped fields field like {calculation-1-*}, {number-2-*}... to real fields {calculation-1}, {number-1-2} * * @param string $formula Formula. * @return string */ private static function maybe_replace_groupped_fields( $formula ) { $pattern = '/\{((?:calculation|number|slider|currency|radio|select|checkbox)\-\d+(?:-min|-max)?)\-\*\}/'; preg_match_all( $pattern, $formula, $matches ); foreach ( $matches[1] as $main_field ) { $copied_fields = array(); // If there is the main field - add it to the array. if ( isset( self::$prepared_data[ $main_field ] ) ) { $copied_fields = array( $main_field ); } // If there are any field copy - add it to the array. foreach ( array_keys( self::$prepared_data ) as $key ) { if ( 0 === strpos( $key, $main_field . '-' ) ) { $copied_fields[] = $key; } } $value = 0; if ( 'calculation-' === substr( $main_field, 0, 12 ) ) { $value = '{' . $main_field . '}'; } if ( $copied_fields ) { $value = '({' . implode( '}+{', $copied_fields ) . '})'; } $formula = str_replace( '{' . $main_field . '-*}', $value, $formula ); } return $formula; } /** * Pull fields from formula * * @param string $formula Formula. * @return array */ public static function calculator_pull_fields( $formula ) { $field_types = Forminator_Core::get_field_types(); $increment_field_pattern = sprintf( '(%s)-\d+', implode( '|', $field_types ) ); $pattern = '/\{((' . $increment_field_pattern . ')(\-[A-Za-z-_]+)?(\-[A-Za-z0-9-_]+)?)\}/'; preg_match_all( $pattern, $formula, $matches ); return $matches; } /** * Calculate formula. * * @param string $formula Formula. * @param array $visible_fields Not hidden field values. * @param array $field_settings Field settings. * @return int */ public static function calculate_formula( $formula, $visible_fields, $field_settings ) { $formula = self::maybe_replace_groupped_fields( $formula ); // todo: remove it, cuz it was already replaced. $fields_in_formula = self::calculator_pull_fields( $formula ); // later usage for str_replace. $full_matches = $fields_in_formula[0]; $converted_formula = $formula; foreach ( $fields_in_formula[1] as $key => $field_id ) { if ( ! isset( $full_matches[ $key ] ) ) { continue; } if ( in_array( $field_id, self::$hidden_fields, true ) || in_array( $field_id, self::$not_calculable, true ) ) { // skip validation, hidden values = 0 or 1. $value = self::replace_to( $field_id, $converted_formula ); } else { $value = $visible_fields[ $field_id ]; } // Replace only the first occurence. $find_str = $full_matches[ $key ]; $replace_with = '(' . ( $value ) . ')'; $converted_formula = implode( $replace_with, explode( $find_str, $converted_formula, 2 ) ); } $precision = Forminator_Calculation::get_calculable_precision( $field_settings ); $calculator = new Forminator_Calculator( $converted_formula ); $calculator->set_is_throwable( true ); try { $result = round( floatval( $calculator->calculate() ), $precision ); } catch ( Forminator_Calculator_Exception $e ) { $result = round( 0.0, $precision ); } return $result; } /** * Handle captcha field * * @param array $field_settings Field settings. */ private static function handle_captcha_field( $field_settings ) { self::$info['captcha_settings'] = $field_settings; } /** * Handle postdata field * * @param array $field_settings Field settings. */ private static function handle_postdata_field( $field_settings ) { $field_id = Forminator_Field::get_property( 'element_id', $field_settings ); $post_type = Forminator_Field::get_property( 'post_type', $field_settings, 'post' ); $category_list = forminator_post_categories( $post_type ); if ( ! empty( $category_list ) ) { foreach ( $category_list as $category ) { $mod_field_id = $field_id . '-' . $category['value']; if ( isset( self::$prepared_data[ $mod_field_id ] ) ) { self::$prepared_data[ $field_id ][ $category['value'] ] = self::$prepared_data[ $mod_field_id ]; } } } $custom_vars = Forminator_Field::get_property( 'post_custom_fields', $field_settings ); $custom_meta = Forminator_Field::get_property( 'options', $field_settings ); if ( empty( $custom_vars ) || empty( $custom_meta ) || self::$is_draft ) { return; } $dependent_fields = array(); foreach ( $custom_meta as $meta ) { $value = ! empty( $meta['value'] ) ? trim( $meta['value'] ) : ''; $label = $meta['label']; if ( strpos( $value, '{' ) !== false && strpos( $value, '{upload' ) === false ) { $prepared_value = forminator_replace_form_data( $value, self::$module_object ); $replaced_fields = self::get_replaced_fields( $value, $prepared_value ); if ( $replaced_fields ) { $dependent_fields = array_merge( $dependent_fields, $replaced_fields ); } $value = forminator_replace_variables( $prepared_value, self::$module_id ); } elseif ( isset( self::$prepared_data[ $value ] ) ) { $value = self::$prepared_data[ $value ]; } // Store data that will be used later by upload fields. if ( strpos( $value, '{upload' ) !== false ) { self::$info['upload_in_customfield'][] = array( 'postdata_id' => $field_id, 'upload_id' => trim( $value, '{}' ), 'uploads' => '', ); } self::$prepared_data[ $field_id ]['post-custom'][] = array( 'key' => $label, 'value' => $value, ); } return array_unique( $dependent_fields ); } /** * Handle date field * * @param array $field_settings Field settings. */ private static function handle_date_field( $field_settings ) { $file_type = Forminator_Field::get_property( 'field_type', $field_settings ); if ( 'picker' !== $file_type ) { $field_id = Forminator_Field::get_property( 'element_id', $field_settings ); $date_format = Forminator_Field::get_property( 'date_format', $field_settings ); self::$prepared_data[ $field_id ]['format'] = datepicker_default_format( $date_format ); } } /** * Handle Time field * * @param array $field_settings Field settings. */ private static function handle_time_field( $field_settings ) { $time_type = Forminator_Field::get_property( 'time_type', $field_settings, 'twelve' ); if ( 'twelve' === $time_type ) { $field_id = Forminator_Field::get_property( 'element_id', $field_settings ); $time = self::$prepared_data[ $field_id ]; if ( empty( $time['hours'] ) && empty( $time['minutes'] ) ) { unset( self::$prepared_data[ $field_id ] ); } } } /** * Handle url field * * @param array $field_settings Field settings. */ private static function handle_url_field( $field_settings ) { $form_field_obj = Forminator_Core::get_field_object( 'url' ); $field_id = Forminator_Field::get_property( 'element_id', $field_settings ); self::$prepared_data[ $field_id ] = $form_field_obj->add_scheme_url( self::$prepared_data[ $field_id ] ); } /** * Handle upload field * * @param array $field_settings Field settings. */ private static function handle_upload_field( $field_settings ) { if ( self::$is_draft ) { return; } $file_type = Forminator_Field::get_property( 'file-type', $field_settings, 'single' ); $upload_method = Forminator_Field::get_property( 'upload-method', $field_settings, 'ajax' ); $field_id = Forminator_Field::get_property( 'element_id', $field_settings ); $form_upload_data = isset( self::$prepared_data['forminator-multifile-hidden'] ) ? self::$prepared_data['forminator-multifile-hidden'] : array(); if ( 'multiple' === $file_type && 'ajax' === $upload_method ) { $upload_data = isset( $form_upload_data[ $field_id ] ) ? $form_upload_data[ $field_id ] : array(); } else { $upload_data = isset( $_FILES[ $field_id ] ) ? $_FILES[ $field_id ] : array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput } if ( ! empty( $upload_data ) ) { self::$has_upload = true; self::$prepared_data[ $field_id ]['file'] = $upload_data; } else { self::$prepared_data[ $field_id ] = ''; } } /** * Handle rating field * * @param array $field_settings Field settings. */ private static function handle_rating_field( $field_settings ) { $max_rating = Forminator_Field::get_property( 'max_rating', $field_settings, 5 ); $field_id = Forminator_Field::get_property( 'element_id', $field_settings ); $rating_value = self::$prepared_data[ $field_id ] ?? 0; self::$prepared_data[ $field_id ] = $rating_value . '/' . $max_rating; } /** * Upload or transfer uploads * For single and multiple-on-submit uploads, * we upload directly when form doesnt have any payment fields. * If form has payment fields, uploads go to forminator_temp folder first * so that when there is an error, the uploads in the forminator_temp folder * can be cleared after 24hrs. * * @param string $mode - upload/transfer. */ private static function process_uploads( $mode ) { if ( self::$is_draft || ! self::$has_upload ) { return; } $fields = self::$info['field_data_array']; foreach ( $fields as $key => $field ) { if ( ! isset( $field['field_type'] ) || 'upload' !== $field['field_type'] ) { continue; } $field_id = $field['name']; $field_settings = $field['field_array']; $file_type = Forminator_Field::get_property( 'file-type', $field_settings, 'single' ); $upload_method = Forminator_Field::get_property( 'upload-method', $field_settings, 'ajax' ); $form_field_obj = Forminator_Core::get_field_object( 'upload' ); if ( 'upload' === $mode ) { if ( 'multiple' === $file_type && 'ajax' === $upload_method ) { continue; } elseif ( 'multiple' === $file_type && 'submission' === $upload_method ) { $form_upload_data = isset( $_FILES[ $field_id ] ) ? $_FILES[ $field_id ] : array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput $upload_data = $form_field_obj->handle_submission_multifile_upload( self::$module_id, $field_settings, $form_upload_data, self::$has_payment ); } elseif ( 'single' === $file_type ) { $upload_data = $form_field_obj->handle_file_upload( self::$module_id, $field_settings, array(), self::$has_payment ? 'upload' : 'submit' ); } } elseif ( 'transfer' === $mode ) { $form_upload_data = $field['value']; if ( 'multiple' === $file_type && 'ajax' === $upload_method ) { $upload_data = $form_field_obj->handle_ajax_multifile_upload( self::$module_id, $form_upload_data, $field_settings ); } elseif ( self::$has_payment && ( 'single' === $file_type || ( 'multiple' === $file_type && 'ajax' !== $upload_method ) ) ) { $upload_data = $form_field_obj->transfer_upload( self::$module_id, $form_upload_data, $field_settings ); } elseif ( ! self::$has_payment && ! empty( $form_upload_data['file'] ) ) { $upload_data = $form_upload_data['file']; } } if ( isset( $upload_data['success'] ) && $upload_data['success'] ) { self::$prepared_data[ $field_id ]['file'] = $upload_data; self::$info['field_data_array'][ $key ]['value']['file'] = $upload_data; if ( ( 'single' === $file_type && ! self::$has_payment ) || 'transfer' === $mode ) { // If upload is successful, add the upload data to custom field if tag is present. if ( ! empty( self::$info['upload_in_customfield'] ) ) { $file_url = $upload_data['file_url']; if ( 'multiple' === $file_type ) { $file_url = implode( ', ', $upload_data['file_url'] ); } foreach ( self::$info['upload_in_customfield'] as $cf_key => $cf ) { if ( $field_id === $cf['upload_id'] ) { self::$info['upload_in_customfield'][ $cf_key ]['uploads'] = $file_url; } } } } } elseif ( isset( $upload_data['success'] ) && false === $upload_data['success'] ) { $error = isset( $upload_data['message'] ) ? $upload_data['message'] : self::get_invalid_form_message(); self::$submit_errors[][ $field_id ] = $error; } else { // no file uploaded for this field_id. self::$prepared_data[ $field_id ] = ''; } } self::check_errors(); } /** * Handle select field * * @param array $field_settings Field settings. */ private static function handle_select_field( $field_settings ) { $is_limit = Forminator_Field::get_property( 'limit_status', $field_settings ); if ( self::$is_draft || 'enable' !== $is_limit ) { return; } $field_id = Forminator_Field::get_property( 'element_id', $field_settings ); $options = Forminator_Field::get_property( 'options', $field_settings ); $value_type = Forminator_Field::get_property( 'value_type', $field_settings ); $select_array = (array) ( self::$prepared_data[ $field_id ] ?? array() ); foreach ( $options as $o => $option ) { if ( in_array( strval( $option['value'] ), array_map( 'strval', $select_array ), true ) ) { self::$info['select_field_value'][ $field_id ][ $o ] = array( 'limit' => $option['limit'], 'value' => $option['value'], 'label' => $option['label'], 'type' => $value_type, ); } } } /** * Apply updated values to hidden-type fields after submission * * @param array $field_settings Field settings. */ private static function handle_hidden_field( $field_settings ) { if ( ! empty( $field_settings['element_id'] ) && ! empty( $field_settings['default_value'] ) ) { $exclude_key = array( 'query', 'embed_id', 'embed_title', 'embed_url' ); if ( 'submission_time' === $field_settings['default_value'] ) { self::$prepared_data[ $field_settings['element_id'] ] = date_i18n( 'g:i:s a, T', forminator_local_timestamp(), true ); } elseif ( ! in_array( $field_settings['default_value'], $exclude_key, true ) ) { $form_field_obj = Forminator_Core::get_field_object( 'hidden' ); self::$prepared_data[ $field_settings['element_id'] ] = esc_html( $form_field_obj->get_value( $field_settings ) ); } } } /** * Apply updated values to hidden-type fields after entry is saved * * @param array $entry Entry. * @param int $module_id Module Id. */ private static function handle_hidden_fields_after_entry_save( $entry, $module_id = null ) { foreach ( self::$info['field_data_array'] as $key => $field ) { if ( 0 === strpos( $field['name'], 'hidden-' ) ) { switch ( $field['field_array']['default_value'] ) { case 'custom_value': self::$info['field_data_array'][ $key ]['value'] = esc_html( $field['field_array']['custom_value'] ); break; default: self::$info['field_data_array'][ $key ]['value'] = trim( forminator_replace_variables( '{' . $field['value'] . '}', self::$module_id, $entry ), '{}' ); break; } if ( 'submission_id' === $field['value'] ) { self::$info['field_data_array'][ $key ]['value'] = $entry->entry_id; } } } } /** * Get replaved fields by forminator_replace_form_data method * * @param string $old_value Old value. * @param string $new_value New value. * @return array */ private static function get_replaced_fields( $old_value, $new_value ) { $replaced_fields = array(); if ( $old_value === $new_value ) { return $replaced_fields; } $pattern = '/{([^}]+)}/'; preg_match_all( $pattern, $old_value, $matches1 ); preg_match_all( $pattern, $new_value, $matches2 ); $replaced_fields = array_diff( $matches1[1], $matches2[1] ); return $replaced_fields; } /** * Returns what the current field should be replaced to (0 or 1) * * @param string $field_id Field id. * @param string $formula Formula. * @return int 0|1 */ public static function replace_to( $field_id, $formula ) { $replace = 0; if ( in_array( $field_id, self::$replace_to_zero, true ) ) { return $replace; } $quoted_operand = preg_quote( '{' . $field_id . '}', '/' ); $pattern = '/([\\+\\-\\*\\/]?)[^\\+\\-\\*\\/\\(]*' . $quoted_operand . '[^\\)\\+\\-\\*\\/]*([\\+\\-\\*\\/]?)/'; $matches = array(); if ( preg_match( $pattern, $formula, $matches ) ) { // if operand in multiplication or division set value = 1. if ( '*' === $matches[1] || '/' === $matches[1] || '*' === $matches[2] || '/' === $matches[2] ) { $replace = 1; } } return $replace; } /** * Create new post from postdata field * Add upload file urls to postdata custom fields if necessary * * @param array $postdata_fields Fields with postdata type. * @return array */ public static function create_post_from_postdata( $postdata_fields ) { $postdata_result = array(); foreach ( $postdata_fields as $postdata_field ) { $field_id = $postdata_field['name']; $field_data = $postdata_field['value']; $field_array = $postdata_field['field_array']; $form_field_obj = $postdata_field['form_field_obj']; // check if field_data of post values not empty (happen when postdata is not required). $filtered = array_filter( $field_data ); $post_value = $field_data; if ( ! empty( $filtered ) ) { if ( isset( $filtered['post-custom'] ) ) { foreach ( $filtered['post-custom'] as $custom_field_index => $custom_field ) { if ( preg_match( '/\{upload-(\d+)\}/', $custom_field['value'] ) ) { $upload_id = trim( $custom_field['value'], '{}' ); foreach ( self::$info['upload_in_customfield'] as $cf_data ) { if ( $upload_id === $cf_data['upload_id'] && $field_id === $cf_data['postdata_id'] ) { $field_data['post-custom'][ $custom_field_index ]['value'] = $cf_data['uploads']; } } } } } $post_id = $form_field_obj->save_post( $field_array, $field_data ); if ( $post_id ) { $field_data = array( 'postdata' => $post_id, 'value' => $field_data, ); } else { return array( 'type' => 'error', 'field_id' => $field_id, 'value' => esc_html__( 'There was an error saving the post data. Please try again', 'forminator' ), ); } } else { $field_data = array( 'postdata' => null, 'value' => $post_value, ); } $postdata_result[] = array( 'type' => 'success', 'field_id' => $field_id, 'field_data' => $field_data, ); } return $postdata_result; } /** * Retrieve the backup code if lost phone. * * @return void */ public function fallback_email() { $defender_data = forminator_defender_compatibility(); $two_fa_component = new $defender_data['two_fa_component'](); $post_data = $this->get_post_data(); $token = isset( $post_data['token'] ) ? $post_data['token'] : ''; $ret = $two_fa_component->send_otp_to_email( $token ); if ( false === $ret ) { wp_send_json_error( array( 'message' => esc_html__( 'Please try again.', 'forminator' ), ) ); } if ( is_wp_error( $ret ) ) { wp_send_json_error( array( 'message' => $ret->get_error_message(), ) ); } wp_send_json_success( array( 'message' => esc_html__( 'Your code has been sent to your email.', 'forminator' ), ) ); } /** * Get the first email in submitted data * * @param array $submitted_data Submitted data. * * @since 1.17.0 */ private static function get_first_email( $submitted_data ) { foreach ( $submitted_data as $key => $val ) { if ( false !== strpos( $key, 'email-' ) && ! empty( $val ) ) { return $val; } } return null; } /** * Create draft ID * * @param int $form_id Form Id. * * @since 1.17.0 */ public function create_draft_id( $form_id ) { // Must guarantee alphanumeric. $draft_id = wp_rand( 0, 9 ); $draft_id .= substr( str_shuffle( 'abcdefghijklmnopqrstvwxyz' ), 0, 1 ); $draft_id .= substr( str_replace( '-', '', wp_generate_uuid4() ), 0, 10 ); return apply_filters( 'forminator_create_draft_id', $draft_id, $form_id ); } /** * Set the Draft ID */ public function set_entry_draft_id() { // 1st draft save. if ( self::$is_draft && is_null( self::$previous_draft_id ) ) { return $this->create_draft_id( self::$module_id ); // Succeeding draft saves. } elseif ( self::$is_draft && ! is_null( self::$previous_draft_id ) ) { return self::$previous_draft_id; } } /** * Get draft notification from form notifications * * @param array $notifications Notification. * @param array $data Data. * * @since 1.17.0 */ public function get_draft_notification( $notifications, $data ) { foreach ( $notifications as $key => $notif ) { if ( false !== array_search( 'save_draft', $notif, true ) ) { $notifications[ $key ]['recipients'] = str_replace( '{save_and_continue_email}', $data['email-1'], $notif['recipients'] ); $email_msg = $notif['email-editor']; $email_msg = str_replace( '{form_link}', $data['draft_link'], $email_msg ); $email_msg = str_replace( '{retention_period}', $data['retention_period'], $email_msg ); $notifications[ $key ]['email-editor'] = $email_msg; return $notifications[ $key ]; } } return false; } /** * Draft link email submission * * @since 1.17.0 */ public function submit_email_draft_link() { $draft_id = Forminator_Core::sanitize_text_field( 'draft_id' ); $nonce = 'forminator_nonce_email_draft_link_' . $draft_id; if ( ! check_ajax_referer( $nonce, $nonce ) ) { wp_send_json_error( esc_html__( 'Invalid request, you are not allowed to do that action.', 'forminator' ) ); } $submitted_data = Forminator_Core::sanitize_array( $_POST ); $form_id = $submitted_data['form_id']; $email = $submitted_data['email-1']; if ( empty( $email ) ) { wp_send_json_error( array( 'field' => 'email-1', 'message' => apply_filters( 'forminator_draft_email_required', esc_html__( 'Email is required.', 'forminator' ), $form_id ), ) ); } elseif ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) { wp_send_json_error( array( 'field' => 'email-1', 'message' => apply_filters( 'forminator_draft_email_invalid', esc_html__( 'Please enter a valid email.', 'forminator' ), $form_id ), ) ); } // Send email. $custom_form = Forminator_Form_Model::model()->load( $form_id ); if ( ! is_object( $custom_form ) ) { wp_send_json_error( array( 'message' => apply_filters( 'forminator_draft_invalid_form_id', esc_html__( 'Invalid form ID.', 'forminator' ), $form_id ), ) ); } $draft_notifications = $this->get_draft_notification( $custom_form->notifications, $submitted_data ); unset( $custom_form->notifications ); $custom_form->notifications[] = $draft_notifications; $forminator_mail_sender = new Forminator_CForm_Front_Mail(); $draft_entry = new Forminator_Form_Entry_Model( $draft_id ); $mail_sent = $forminator_mail_sender->process_mail( $custom_form, $draft_entry, $submitted_data ); $response['draft_mail_sent'] = $mail_sent; if ( $mail_sent ) { $response['draft_mail_message'] = sprintf( '<p>%s</p><a href="#" class="draft-resend-mail">%s</a>', esc_html__( 'We\'ve sent the resume form link to your email address. Please check your spam folder if you can\'t find the link in your inbox.', 'forminator' ), esc_html__( 'Change email', 'forminator' ) ); } else { $response['draft_mail_message'] = sprintf( '<p>%s</p><a href="#" class="draft-resend-mail">%s</a>', esc_html__( 'We couldn\'t send the form resume link to your email at this time. Click on the link below to resend it or manually copy and save the link in a safe place.', 'forminator' ), esc_html__( 'Resend link', 'forminator' ) ); } wp_send_json_success( $response ); } }
💾 Save
❌ Cancel
Sid Gifari File Manager v1.0 | Terminal Auto-Sync Enabled | Current Path: /home/nradmin/public_html/wp-content/plugins/forminator/library/modules/custom-forms/front