<?php
/**
* Form builder class
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! class_exists( 'Jet_Engine_Booking_Forms_Handler' ) ) {
/**
* Define Jet_Engine_Booking_Forms_Handler class
*/
class Jet_Engine_Booking_Forms_Handler {
public $hook_key = 'jet_engine_action';
public $hook_val = 'book';
public $form = null;
public $form_fields = array();
public $refer = null;
public $manager = null;
public $notifcations = null;
public $form_data = array();
public $response_data = array();
public $is_ajax = false;
public $repeaters = array();
/**
* Constructor for the class
*/
function __construct( $manager ) {
if ( wp_doing_ajax() ) {
add_action( 'wp_ajax_jet_engine_form_booking_submit', array( $this, 'process_ajax_form' ) );
add_action( 'wp_ajax_nopriv_jet_engine_form_booking_submit', array( $this, 'process_ajax_form' ) );
} else {
if ( ! isset( $_REQUEST[ $this->hook_key ] ) || $this->hook_val !== $_REQUEST[ $this->hook_key ] ) {
return;
}
add_action( 'wp_loaded', array( $this, 'process_form' ), 0 );
}
$this->manager = $manager;
}
/**
* Is ajax form processing or not
*
* @return boolean [description]
*/
public function is_ajax() {
return $this->is_ajax;
}
/**
* Setup form data
*
* @return [type] [description]
*/
public function setup_form() {
$form_key = '_jet_engine_booking_form_id';
$refer_key = '_jet_engine_refer';
if ( ! $this->is_ajax ) {
$this->form = ! empty( $_REQUEST[ $form_key ] ) ? $_REQUEST[ $form_key ] : false;
$this->refer = ! empty( $_REQUEST[ $refer_key ] ) ? $_REQUEST[ $refer_key ] : false;
} else {
$values = ! empty( $_REQUEST['values'] ) ? $_REQUEST['values'] : array();
foreach ( $values as $data ) {
if ( $data['name'] === $form_key ) {
$this->form = $data['value'];
}
if ( $data['name'] === $refer_key ) {
$this->refer = $data['value'];
}
}
}
}
/**
* Check if current form has configured gateway
*
* @return boolean [description]
*/
public function has_gateway() {
return apply_filters( 'jet-engine/forms/handler/has-gateways', false, $this->form );
}
/**
* Process form with Ajax
*
* @return [type] [description]
*/
public function process_ajax_form() {
$this->is_ajax = true;
$this->process_form();
}
/**
* Process current form
*
* @return [type] [description]
*/
public function process_form() {
$this->setup_form();
$data = $this->get_form_data();
require_once jet_engine()->modules->modules_path( 'forms/notifications.php' );
$this->notifcations = new Jet_Engine_Booking_Forms_Notifications(
$this->form,
$data,
$this->manager,
$this
);
do_action( 'jet-engine/forms/handler/before-send', $this );
$success = $this->notifcations->send();
do_action( 'jet-engine/forms/handler/after-send', $this, $success );
if ( true === $success ) {
$this->redirect( array(
'status' => 'success',
) );
} else {
$this->redirect( array(
'status' => 'failed',
) );
}
}
/**
* Add new properties into response data
*
* @param array $data [description]
*/
public function add_response_data( $data = array() ) {
$this->response_data = array_merge( $this->response_data, $data );
}
/**
* Redirect back to refer
* @param array $args [description]
* @return [type] [description]
*/
public function redirect( $args = array() ) {
$args = wp_parse_args( $args, array(
'status' => 'success',
) );
$error_statuses = array( 'validation_failed', 'invalid_email' );
if ( $this->notifcations ) {
$specific_status = $this->notifcations->get_specific_status();
} else {
$specific_status = false;
}
if ( ! empty( $specific_status ) ) {
$args['status'] = $specific_status;
}
$query_args = array(
'status' => $args['status'],
);
$query_args = array_merge( $query_args, $this->response_data );
// Clear form-related arguments
$this->refer = remove_query_arg( array( 'values', 'status', 'fields' ), $this->refer );
if ( 'validation_failed' === $args['status'] ) {
if ( $this->is_ajax ) {
$query_args['fields'] = $args['errors'];
} else {
$query_args['fields'] = implode( ',', $args['errors'] );
}
}
$send_values = apply_filters( 'jet-engine/forms/booking/handler/send-values-on-error', true );
if ( ! $this->is_ajax && $send_values && in_array( $args['status'], $error_statuses ) ) {
$query_args['values'] = $this->form_data;
}
$query_args = apply_filters( 'jet-engine/forms/handler/query-args', $query_args, $args, $this );
if ( $this->is_ajax ) {
$messages = jet_engine()->forms->get_messages_builder( $this->form );
ob_start();
$messages->set_form_status( $args['status'] );
$messages->render_messages();
$query_args['message'] = ob_get_clean();
if ( 'validation_failed' === $args['status'] ) {
ob_start();
$messages->render_empty_field_message();
$query_args['field_message'] = ob_get_clean();
}
wp_send_json( $query_args );
} else {
$redirect = add_query_arg( $query_args, $this->refer );
wp_redirect( $redirect );
die();
}
}
/**
* Get form values from request
*
* @return [type] [description]
*/
public function get_values_from_request() {
if ( $this->is_ajax ) {
$prepared = array();
$raw = ! empty( $_REQUEST['values'] ) ? $_REQUEST['values'] : array();
if ( empty( $raw ) ) {
return $prepared;
}
foreach ( $raw as $data ) {
$name = $data['name'];
$value = $data['value'];
if ( preg_match( '/\[\d\]\[/', $name ) ) {
$name_parts = explode( '[', $name );
$name = $name_parts[0];
$index = absint( rtrim( $name_parts[1], ']' ) );
$key = rtrim( $name_parts[2], ']' );
if ( empty( $prepared[ $name ] ) ) {
$prepared[ $name ] = array();
}
if ( empty( $prepared[ $name ][ $index ] ) ) {
$prepared[ $name ][ $index ] = array();
}
if ( isset( $name_parts[3] ) ) {
if ( empty( $prepared[ $name ][ $index ][ $key ] ) ) {
$prepared[ $name ][ $index ][ $key ] = array();
}
$prepared[ $name ][ $index ][ $key ][] = $value;
} else {
$prepared[ $name ][ $index ][ $key ] = $value;
}
} elseif ( false !== strpos( $name, '[]') ) {
$name = str_replace( '[]', '', $name );
if ( empty( $prepared[ $name ] ) ) {
$prepared[ $name ] = array();
}
$prepared[ $name ][] = $value;
} else {
$prepared[ $name ] = $value;
}
}
return $prepared;
} else {
return $_REQUEST;
}
}
/**
* Get submitted form data
*
* @return [type] [description]
*/
public function get_form_data() {
$fields = $this->manager->editor->get_form_data( $this->form );
$data = array();
$errors = array();
$invalid_email = false;
$request = $this->get_values_from_request();
$skip_fields = array( 'submit', 'page_break', 'heading', 'group_break', 'repeater_end' );
$in_repeater = false;
$current_repeater = null;
usort( $fields, function( $a, $b ) {
if ( $a['y'] == $b['y'] ) {
return 0;
}
return ( $a['y'] < $b['y'] ) ? -1 : 1;
} );
foreach ( $fields as $field ) {
if ( in_array( $field['settings']['name'], $skip_fields ) ) {
continue;
}
if ( in_array( $field['settings']['type'], array( 'heading', 'group_break', 'repeater_end' ) ) ) {
if ( 'repeater_end' === $field['settings']['type'] ) {
$in_repeater = false;
$current_repeater = null;
}
continue;
}
if ( ! $this->is_field_visible( $field['settings'] ) ) {
continue;
}
$settings = $field['settings'];
$required = ! empty( $settings['required'] ) ? $settings['required'] : '';
$name = $settings['name'];
$value = isset( $request[ $name ] ) ? $request[ $name ] : '';
$this->form_fields[ $name ] = $settings;
$is_repeater = false;
if ( in_array( $settings['type'], array( 'date', 'datetime-local' ) ) && ! empty( $settings['is_timestamp'] ) ) {
$value = strtotime( $value );
}
if ( 'repeater_start' === $settings['type'] ) {
$is_repeater = true;
$in_repeater = true;
$current_repeater = $name;
$this->repeaters[ $settings['name'] ] = $settings;
} elseif ( 'repeater_end' === $settings['type'] ) {
$in_repeater = false;
$current_repeater = null;
}
if ( ! $is_repeater && $in_repeater ) {
if ( 'media' === $settings['type'] && ! empty( $data[ $current_repeater ] ) ) {
foreach ( $data[ $current_repeater ] as $index => $row ) {
if ( ! empty( $row[ $name ] ) ) {
if ( 'is-hidden' !== $value ) {
$value = json_decode( wp_unslash( $row[ $name ] ), true );
if ( ! empty( $settings['insert_attachment'] ) && ! empty( $settings['value_format'] ) && 'id' === $settings['value_format'] ) {
if ( ! is_array( $value ) ) {
$value = ! empty( $value ) ? absint( $value ) : null;
} else {
$value = implode( ',', $value );
}
}
}
$row[ $name ] = $value;
$data[ $current_repeater ][ $index ] = $row;
}
}
}
continue;
}
$is_media_by_id_url = false;
if ( 'media' === $settings['type'] ) {
if ( 'is-hidden' !== $value ) {
$value = json_decode( wp_unslash( $value ), true );
if ( ! empty( $settings['insert_attachment'] ) && ! empty( $settings['value_format'] ) && 'id' === $settings['value_format'] ) {
if ( ! is_array( $value ) ) {
$value = ! empty( $value ) ? absint( $value ) : null;
} else {
$value = implode( ',', $value );
}
}
if ( ! empty( $settings['insert_attachment'] ) && ! empty( $settings['value_format'] ) && 'both' === $settings['value_format'] ) {
$is_media_by_id_url = true;
}
}
}
if ( 'wysiwyg' === $settings['type'] ) {
$required = false;
$value = jet_engine_sanitize_wysiwyg( $value );
}
$data[ $name ] = $value;
if ( 'text' === $settings['type'] && isset( $settings['field_type'] ) && 'email' === $settings['field_type'] &&
! empty( $value ) && 'is-hidden' !== $value && ! is_email( $value )
) {
$invalid_email = true;
}
if ( is_array( $value ) && ! $is_repeater && ! $is_media_by_id_url ) {
$value = implode( ', ', $value );
}
if ( $required && Jet_Engine_Tools::is_empty( $value ) ) {
$errors[] = $name;
}
}
// Remove `is-hidden` fields value
$data = array_map( function ( $item ) {
return 'is-hidden' !== $item ? $item : '';
}, $data );
$this->form_data = apply_filters( 'jet-engine/forms/handler/form-data', $data, $this->form, $fields );
if ( ! $this->manager->captcha->verify( $this->form, $this->is_ajax ) ) {
$this->redirect( array(
'status' => 'captcha_failed',
'errors' => $errors,
) );
}
if ( ! empty( $errors ) ) {
$this->redirect( array(
'status' => 'validation_failed',
'errors' => $errors,
) );
}
if ( $invalid_email ) {
$this->redirect( array(
'status' => 'invalid_email',
) );
}
return $data;
}
/**
* Returns true if field is visible
*
* @param array $field [description]
* @return boolean [description]
*/
public function is_field_visible( $field = array() ) {
// For backward compatibility and hidden fields
if ( empty( $field['visibility'] ) ) {
return true;
}
// If is visible for all - show field
if ( 'all' === $field['visibility'] ) {
return true;
}
// If is visible for logged in users and user is logged in - show field
if ( 'logged_id' === $field['visibility'] && is_user_logged_in() ) {
return true;
}
// If is visible for not logged in users and user is not logged in - show field
if ( 'not_logged_in' === $field['visibility'] && ! is_user_logged_in() ) {
return true;
}
return false;
}
}
}