Booking Form * Dynamic form customization requires the Dynamic Form Field module (Pro). * * @package Yatra * * Expected variables: * - $trip_id * - $trip_slug (optional) * - $total_travelers * - $deposit_required * - $deposit_percentage * - $partial_payment * - $partial_payment_percentage * - $enabled_gateways * * Form Configuration Structure: * - contact_form: Lead traveler contact information (prefix: contact_) * - emergency_contact_form: Emergency contact details (prefix: emergency_) * - traveler_form: Individual traveler details (array format: travelers[1][field_id]) */ if (!defined('ABSPATH')) { exit; } // Check if Dynamic Form Field module is enabled (Pro feature) $is_dynamic_form_enabled = apply_filters('yatra_dynamic_form_field_enabled', false); // Get form configuration - returns default config if module disabled, custom config if enabled $form_config = yatra_get_booking_form_config(); // Country list — pulls from the canonical FormatHelper source so every // dropdown (admin, public booking, Pro modules) shows the same full // ISO-3166-1 list. Operators that want a "popular countries" subset // or custom ordering apply the `yatra_countries_list` filter. $countries = \Yatra\Helpers\FormatHelper::getCountries(); /** * Render a single form field based on configuration * * @param array $field Field configuration * @param string $prefix Field name prefix (e.g., 'contact_', 'emergency_') * @param array $countries Country list for country fields * @param string $custom_name Optional custom field name (for array-style names like travelers[1][field_id]) * @param string $custom_id Optional custom field ID */ if (!function_exists('yatra_render_form_field')) { function yatra_render_form_field($field, $prefix = '', $countries = [], $custom_name = null, $custom_id = null) { if (empty($field['enabled'])) { return; } $field_id = $custom_id ? esc_attr($custom_id) : esc_attr($prefix . $field['id']); $field_name = $custom_name ? esc_attr($custom_name) : esc_attr($prefix . $field['id']); $required = !empty($field['required']); $required_attr = $required ? 'required' : ''; $required_star = $required ? '*' : ''; $prefill_value = ''; if ($custom_name === null && $prefix === 'contact_') { global $booking; if (isset($booking) && is_object($booking)) { $prop = 'contact_' . ($field['id'] ?? ''); if (!empty($prop) && isset($booking->{$prop}) && $booking->{$prop} !== null && $booking->{$prop} !== '') { $prefill_value = (string) $booking->{$prop}; } } } $width_class = ''; if (!empty($field['width'])) { switch ($field['width']) { case 'half': $width_class = 'yatra-field-half'; break; case 'third': $width_class = 'yatra-field-third'; break; default: $width_class = 'yatra-field-full'; } } $field_type = $field['type'] ?? 'text'; ?>
value="" > value="" >

$section_fields) : ?>

amount_paid)) : ?> total_amount)) : ?> */ $yatra_normalize_booking_arrayish = static function ($value): array { if ($value === null || $value === false || $value === '') { return []; } if (is_array($value)) { return $value; } if ($value instanceof \stdClass) { return (array) $value; } if (is_string($value)) { $trim = trim($value); if ($trim === '') { return []; } $decoded = json_decode($value, true); if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) { return $decoded; } if (function_exists('maybe_unserialize')) { $un = maybe_unserialize($value); if (is_array($un)) { return $un; } } } return []; }; $price_types = $yatra_normalize_booking_arrayish($price_types); $traveler_counts = $yatra_normalize_booking_arrayish($traveler_counts); // Build traveler-to-category mapping for traveler-based pricing $traveler_category_map = []; if ($pricing_type === 'traveler_based' && !empty($price_types) && !empty($traveler_counts)) { $traveler_index = 1; foreach ($price_types as $index => $pt) { $pt = (object) $pt; $category_id = $pt->category_id ?? $index; $category_label = $pt->category_label ?? __('Traveler', 'yatra'); $count = isset($traveler_counts[$category_id]) ? (int) $traveler_counts[$category_id] : 0; for ($c = 1; $c <= $count; $c++) { $traveler_category_map[$traveler_index] = [ 'category_id' => $category_id, 'category_label' => $category_label, 'category_index' => $c, ]; $traveler_index++; } } } $price_candidates = [ isset($trip->price) ? (float) $trip->price : 0, isset($booking->session_price) ? (float) $booking->session_price : 0, isset($trip->sale_price) ? (float) $trip->sale_price : 0, isset($trip->original_price) ? (float) $trip->original_price : 0, ]; $effective_trip_price = 0; foreach ($price_candidates as $candidate) { if ($candidate > 0) { $effective_trip_price = $candidate; break; } } $traveler_price_rows = []; $calculated_total = 0; if ($pricing_type === 'traveler_based' && !empty($price_types)) { foreach ($price_types as $index => $pt) { $pt = (object) $pt; $category_id = $pt->category_id ?? $index; $category_label = $pt->category_label ?? __('Traveler', 'yatra'); $category_price = isset($pt->effective_price) ? (float) $pt->effective_price : ($pt->sale_price ?? $pt->discounted_price ?? $pt->original_price ?? 0); $count = isset($traveler_counts[$category_id]) ? (int) $traveler_counts[$category_id] : ($index === 0 ? 1 : 0); $subtotal = $category_price * $count; $age_info = ''; if (isset($pt->age_min) || isset($pt->age_max)) { if (isset($pt->age_min) && isset($pt->age_max)) { /* translators: 1: minimum age, 2: maximum age. */ $age_info = sprintf(__('(Age %1$d-%2$d)', 'yatra'), $pt->age_min, $pt->age_max); } elseif (isset($pt->age_min)) { /* translators: %d: minimum age. */ $age_info = sprintf(__('(Age %d+)', 'yatra'), $pt->age_min); } else { /* translators: %d: maximum age. */ $age_info = sprintf(__('(Up to age %d)', 'yatra'), $pt->age_max); } } $traveler_price_rows[] = [ 'category_id' => $category_id, 'category_label' => $category_label, 'category_price' => $category_price, 'count' => $count, 'subtotal' => $subtotal, 'age_info' => $age_info, ]; $calculated_total += $subtotal; if ($effective_trip_price <= 0 && $category_price > 0) { $effective_trip_price = $category_price; } } } if ($effective_trip_price <= 0) { $effective_trip_price = 0; } $initial_total_amount = $calculated_total > 0 ? $calculated_total : ($effective_trip_price * max(1, (int) $total_travelers)); if ($initial_total_amount <= 0 && $effective_trip_price > 0) { $initial_total_amount = $effective_trip_price * max(1, (int) $total_travelers); } $initial_due_amount = $initial_total_amount; ?>

data-category-id="" data-category-label="">

1) : ?>
$section_fields) : ?>

isset($trip_id) ? (int) $trip_id : 0, 'deposit_required' => $deposit_required, 'deposit_percentage' => $deposit_percentage, 'partial_payment' => $partial_payment, 'partial_payment_percentage' => $partial_payment_percentage, ]); $has_flexible_options = $flexible_payments_enabled && !empty($payment_method_options); ?>

$option) : ?>
getForCheckout() as $gateway) { if (!empty($gateway['id'])) { $display_gateways[$gateway['id']] = $gateway; } } } ?>

$gateway) : $icon = !empty($gateway['icon']) ? $gateway['icon'] : plugins_url('assets/images/payment-placeholder.png', dirname(__DIR__)); ?>

' . esc_html($current_user->display_name) . '' ); ?>
0 ? get_permalink($termsPageId) : ''; $privacyUrl = $privacyPageId > 0 ? get_permalink($privacyPageId) : ''; if ($privacyUrl === '' && function_exists('get_privacy_policy_url')) { $privacyUrl = (string) get_privacy_policy_url(); } ?>