PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
← All changes | templates/partials/booking-form-fields.php +151 -29 3.0.7 → 3.0.16 View file →
@@ -30,9 +30,11 @@
30 30 // Check if Dynamic Form Field module is enabled (Pro feature)
31 31 $is_dynamic_form_enabled = apply_filters('yatra_dynamic_form_field_enabled', false);
32 32
33 33 // Get form configuration - returns default config if module disabled, custom config if enabled
34 -$form_config = yatra_get_booking_form_config();
34 +// Scoped to the trip being booked, so a field or section limited to certain
35 +// trips (Pro) is neither rendered nor required here.
36 +$form_config = yatra_get_booking_form_config(!empty($trip_id) ? (int) $trip_id : null);
35 37
36 38
37 39 // Country list — pulls from the canonical FormatHelper source so every
38 40 // dropdown (admin, public booking, Pro modules) shows the same full
@@ -65,9 +67,9 @@
65 67 } elseif (($field['width'] ?? '') === 'third') {
66 68 $tb_width = 'yatra-field-third';
67 69 }
68 70 ?>
69 - <div class="yatra-form-group yatra-form-text-block <?php echo esc_attr($tb_width); ?>">
71 + <div class="yatra-form-group yatra-form-text-block <?php echo esc_attr($tb_width); ?>" data-applies-to="<?php echo esc_attr($field['applies_to'] ?? 'all'); ?>">
70 72 <?php echo wpautop(wp_kses_post(yatra_translate_form_string($field['content'] ?? ''))); ?>
71 73 </div>
72 74 <?php
73 75 return;
@@ -104,9 +106,9 @@
104 106 }
105 107 }
106 108 $field_type = $field['type'] ?? 'text';
107 109 ?>
108 - <div class="yatra-form-group <?php echo esc_attr($width_class); ?> <?php echo $field_type === 'checkbox' ? 'yatra-form-group--checkbox' : ''; ?>">
110 + <div class="yatra-form-group <?php echo esc_attr($width_class); ?> <?php echo $field_type === 'checkbox' ? 'yatra-form-group--checkbox' : ''; ?>" data-applies-to="<?php echo esc_attr($field['applies_to'] ?? 'all'); ?>">
109 111 <?php if ($field_type !== 'checkbox') : ?>
110 112 <label for="<?php echo $field_id; ?>">
111 113 <?php echo esc_html(yatra_translate_form_string($field['label'])); ?> <?php echo $required_star; ?>
112 114 </label>
@@ -144,10 +146,17 @@
144 146 <?php
145 147 break;
146 148
147 149 case 'country':
150 + // Flag base is handed to the field (same contract as the phone
151 + // widget) so country-select.js can build flag URLs without
152 + // knowing the plugin URL. The select still renders and submits
153 + // normally — the widget is a progressive enhancement over it.
154 + $country_flag_base = \defined('YATRA_PLUGIN_URL') ? YATRA_PLUGIN_URL . 'assets/img/flags/' : '';
148 155 ?>
149 - <select id="<?php echo $field_id; ?>" name="<?php echo $field_name; ?>" <?php echo $required_attr; ?>>
156 + <select id="<?php echo $field_id; ?>" name="<?php echo $field_name; ?>" <?php echo $required_attr; ?>
157 + data-yatra-country-select
158 + data-flag-base="<?php echo esc_url($country_flag_base); ?>">
150 159 <option value=""><?php echo esc_html(yatra_translate_form_string($field['placeholder'] ?? '') ?: __('Select Country', 'yatra')); ?></option>
151 160 <?php foreach ($countries as $code => $name) : ?>
152 161 <option value="<?php echo esc_attr($code); ?>" <?php echo selected($prefill_value, (string) $code, false); ?>>
153 162 <?php echo esc_html($name); ?>
@@ -170,14 +179,33 @@
170 179 break;
171 180
172 181 case 'date':
173 182 $min_attr = '';
183 + // Date-of-birth-style fields are bounded to today and flagged so
184 + // booking.js can upgrade them to a picker with fast year jumping
185 + // (a native date popup steps one month at a time). The class is
186 + // the JS hook; if JS/flatpickr is unavailable the input stays a
187 + // working native <input type="date">.
188 + $is_dob = (stripos($field_id, 'birth') !== false || stripos($field_id, 'dob') !== false
189 + || stripos($field_name, 'birth') !== false || stripos($field_name, 'dob') !== false);
190 + $dob_attr = $is_dob ? ' data-yatra-dob="1" max="' . esc_attr(date('Y-m-d')) . '"' : '';
191 + // Native date inputs ignore the placeholder, but once booking.js
192 + // upgrades the field to a flatpickr text input the placeholder is
193 + // what keeps it visually consistent with the other text fields
194 + // (otherwise it renders blank). Use the field's own placeholder
195 + // when set, else a format hint matching flatpickr's Y-m-d output.
196 + $date_placeholder = !empty($field['placeholder'])
197 + ? yatra_translate_form_string($field['placeholder'])
198 + : 'YYYY-MM-DD';
174 199 ?>
175 - <input
176 - type="date"
177 - id="<?php echo $field_id; ?>"
200 + <input
201 + type="date"
202 + class="yatra-js-date"
203 + id="<?php echo $field_id; ?>"
178 204 name="<?php echo $field_name; ?>"
205 + placeholder="<?php echo esc_attr($date_placeholder); ?>"
179 206 <?php echo $min_attr; ?>
207 + <?php echo $dob_attr; ?>
180 208 <?php echo $required_attr; ?>
181 209 value="<?php echo esc_attr($prefill_value); ?>"
182 210 >
183 211 <?php
@@ -183,18 +211,81 @@
183 211 <?php
184 212 break;
185 213
186 214 default: // text, email, tel, number
187 - ?>
188 - <input
189 - type="<?php echo esc_attr($field['type']); ?>"
190 - id="<?php echo $field_id; ?>"
191 - name="<?php echo $field_name; ?>"
192 - placeholder="<?php echo esc_attr(yatra_translate_form_string($field['placeholder'] ?? '')); ?>"
193 - <?php echo $required_attr; ?>
194 - value="<?php echo esc_attr($prefill_value); ?>"
195 - >
196 - <?php
215 + // Phone (tel) fields get the international country-code widget
216 + // UNLESS it has been explicitly disabled in the (Pro) form
217 + // builder. A missing key means ON, so every existing form and
218 + // customized field keeps the widget without needing a re-save.
219 + $is_phone_widget = (($field['type'] ?? '') === 'tel')
220 + && (!array_key_exists('show_country_code', $field) || !empty($field['show_country_code']));
221 +
222 + if ($is_phone_widget) {
223 + // Split the stored value for display: an international value
224 + // ("+9779806015400") is parsed into country + national part;
225 + // a legacy bare number is left in the number box under the
226 + // default country (never rewritten on display).
227 + $pv = (string) $prefill_value;
228 + $detected = \Yatra\Helpers\FormatHelper::detectPhoneCountry($pv);
229 + if ($detected !== null) {
230 + $p_iso = $detected['iso'];
231 + $p_dial = $detected['dial'];
232 + $p_national = $detected['national'];
233 + } else {
234 + $p_iso = \Yatra\Helpers\FormatHelper::getDefaultPhoneCountry();
235 + $p_dial = \Yatra\Helpers\FormatHelper::getDialingCode($p_iso);
236 + $p_national = $pv;
237 + }
238 +
239 + // Companion hidden field holding the chosen ISO. Array-style
240 + // names (travelers[0][phone]) become travelers[0][phone_country];
241 + // the server combines dial code + national number on submit.
242 + if (preg_match('/^(.*)\[([^\]]+)\]$/', $field_name, $mm)) {
243 + $companion_name = $mm[1] . '[' . $mm[2] . '_country]';
244 + } else {
245 + $companion_name = $field_name . '_country';
246 + }
247 +
248 + $flag_base = \defined('YATRA_PLUGIN_URL') ? YATRA_PLUGIN_URL . 'assets/img/flags/' : '';
249 + ?>
250 + <div class="yatra-phone-field" data-yatra-phone
251 + data-default-iso="<?php echo esc_attr($p_iso); ?>"
252 + data-flag-base="<?php echo esc_url($flag_base); ?>">
253 + <button type="button" class="yatra-phone-country" aria-haspopup="listbox" aria-expanded="false"
254 + aria-label="<?php esc_attr_e('Select country dialing code', 'yatra'); ?>">
255 + <img class="yatra-phone-flag" src="<?php echo esc_url($flag_base . strtolower($p_iso) . '.svg'); ?>"
256 + alt="" width="22" height="16" loading="lazy">
257 + <span class="yatra-phone-dial">+<?php echo esc_html($p_dial); ?></span>
258 + <span class="yatra-phone-caret" aria-hidden="true"></span>
259 + </button>
260 + <input
261 + type="tel"
262 + class="yatra-phone-number"
263 + id="<?php echo $field_id; ?>"
264 + name="<?php echo $field_name; ?>"
265 + value="<?php echo esc_attr($p_national); ?>"
266 + placeholder="<?php echo esc_attr(yatra_translate_form_string($field['placeholder'] ?? '')); ?>"
267 + inputmode="tel"
268 + autocomplete="tel-national"
269 + <?php echo $required_attr; ?>
270 + >
271 + <input type="hidden" class="yatra-phone-iso"
272 + name="<?php echo esc_attr($companion_name); ?>"
273 + value="<?php echo esc_attr($p_iso); ?>">
274 + </div>
275 + <?php
276 + } else {
277 + ?>
278 + <input
279 + type="<?php echo esc_attr($field['type']); ?>"
280 + id="<?php echo $field_id; ?>"
281 + name="<?php echo $field_name; ?>"
282 + placeholder="<?php echo esc_attr(yatra_translate_form_string($field['placeholder'] ?? '')); ?>"
283 + <?php echo $required_attr; ?>
284 + value="<?php echo esc_attr($prefill_value); ?>"
285 + >
286 + <?php
287 + }
197 288 break;
198 289 }
199 290 ?>
200 291 </div>
@@ -515,8 +606,22 @@
515 606 } else {
516 607 /* translators: %d: traveler sequence number. */
517 608 $traveler_label = ($i === 1) ? __('Traveler 1 (Lead Traveler)', 'yatra') : sprintf(__('Traveler %d', 'yatra'), $i);
518 609 }
610 +
611 + // Fields targeted at the lead traveler (applies_to === 'lead') render
612 + // only for Traveler 1; everything else ('all' / unset) renders for
613 + // every traveler. Empty subsections are dropped so additional
614 + // travelers don't get an orphan heading.
615 + $traveler_grouped_fields = [];
616 + foreach ($grouped_traveler_fields as $sk => $sf) {
617 + $applicable = array_values(array_filter($sf, function ($f) use ($i) {
618 + return ($f['applies_to'] ?? 'all') !== 'lead' || $i === 1;
619 + }));
620 + if (!empty($applicable)) {
621 + $traveler_grouped_fields[$sk] = $applicable;
622 + }
623 + }
519 624 ?>
520 625 <div class="yatra-traveler-form" data-traveler-index="<?php echo esc_attr($i); ?>" <?php if (!empty($traveler_category_map[$i])): ?>data-category-id="<?php echo esc_attr($traveler_category_map[$i]['category_id']); ?>" data-category-label="<?php echo esc_attr($traveler_category_map[$i]['category_label']); ?>"<?php endif; ?>>
521 626 <div class="yatra-traveler-header">
522 627 <h3 class="yatra-traveler-title"><?php echo esc_html($traveler_label); ?></h3>
@@ -524,9 +629,9 @@
524 629 <span class="yatra-traveler-note"><?php esc_html_e('Additional traveler', 'yatra'); ?></span>
525 630 <?php endif; ?>
526 631 </div>
527 632
528 - <?php foreach ($grouped_traveler_fields as $section_key => $section_fields) : ?>
633 + <?php foreach ($traveler_grouped_fields as $section_key => $section_fields) : ?>
529 634 <?php if ($section_key !== 'main') : ?>
530 635 <div class="yatra-traveler-subsection">
531 636 <h4 class="yatra-subsection-title">
532 637 <?php
@@ -585,8 +690,11 @@
585 690 'deposit_required' => $deposit_required,
586 691 'deposit_percentage' => $deposit_percentage,
587 692 'partial_payment' => $partial_payment,
588 693 'partial_payment_percentage' => $partial_payment_percentage,
694 + // Tour start (when a date is already chosen) → Pro hides deposit/partial for
695 + // tour-anchored payments when the tour is inside the balance-due window.
696 + 'travel_date' => isset($booking->travel_date) ? (string) $booking->travel_date : '',
589 697 ]);
590 698
591 699 $has_flexible_options = $flexible_payments_enabled && !empty($payment_method_options);
592 700 ?>
@@ -681,20 +789,28 @@
681 789 </div>
682 790 <?php endif; ?>
683 791
684 792 <!-- Account Creation Section (only for guests) -->
685 -<?php
793 +<?php
686 794 $allow_guest_checkout = \Yatra\Services\SettingsService::isEnabled('allow_guest_checkout');
687 795 $require_login = \Yatra\Services\SettingsService::isEnabled('require_login');
796 +// Account CREATION is gated by the same setting the backend enforces
797 +// (AuthController rejects registration when this is off). When registration is
798 +// disabled we never offer account-creation UI.
799 +$registration_enabled = \Yatra\Services\SettingsService::isEnabled('customer_registration');
688 800
689 -// Show account section if user is not logged in
690 -if (!is_user_logged_in() && !$is_remaining_payment) :
801 +// Show the account section only when it has something to render: login is
802 +// required, guest checkout is off (must authenticate), or registration is on
803 +// (optional/required account creation). When registration is OFF and guests are
804 +// allowed, there is nothing to show — proceed as a pure guest.
805 +if (!is_user_logged_in() && !$is_remaining_payment
806 + && ($require_login || !$allow_guest_checkout || $registration_enabled)) :
691 807 ?>
692 808 <div class="yatra-booking-section yatra-account-section">
693 809 <h2 class="yatra-section-title"><?php esc_html_e('Account', 'yatra'); ?></h2>
694 810
695 - <?php if ($require_login) : ?>
696 - <!-- Login Required Message -->
811 + <?php if ($require_login || (!$allow_guest_checkout && !$registration_enabled)) : ?>
812 + <!-- Login Required Message (login required, OR guests off with registration disabled) -->
697 813 <div class="yatra-login-required-notice" style="background: #fef3c7; border: 1px solid #f59e0b; padding: 16px; border-radius: 8px; margin-bottom: 16px;">
698 814 <div style="display: flex; align-items: flex-start; gap: 12px;">
699 815 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#d97706" stroke-width="2" style="flex-shrink: 0;">
700 816 <circle cx="12" cy="12" r="10"></circle>
@@ -703,9 +819,11 @@
703 819 </svg>
704 820 <div>
705 821 <p style="font-weight: 600; color: #92400e; margin: 0 0 8px 0;"><?php esc_html_e('Login Required', 'yatra'); ?></p>
706 822 <p style="color: #a16207; margin: 0 0 12px 0; font-size: 14px;">
707 - <?php esc_html_e('You must be logged in to complete this booking. Please log in or create an account.', 'yatra'); ?>
823 + <?php echo $registration_enabled
824 + ? esc_html__('You must be logged in to complete this booking. Please log in or create an account.', 'yatra')
825 + : esc_html__('You must be logged in to complete this booking. Please log in to continue.', 'yatra'); ?>
708 826 </p>
709 827 <a href="<?php echo esc_url(wp_login_url(get_permalink())); ?>" class="yatra-login-btn" style="display: inline-flex; align-items: center; gap: 8px; padding: 10px 20px; background: #3b82f6; color: #fff; text-decoration: none; border-radius: 6px; font-weight: 500; font-size: 14px;">
710 828 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
711 829 <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
@@ -713,19 +831,21 @@
713 831 <line x1="15" y1="12" x2="3" y2="12"></line>
714 832 </svg>
715 833 <?php esc_html_e('Log In', 'yatra'); ?>
716 834 </a>
835 + <?php if ($registration_enabled) : ?>
717 836 <span style="margin: 0 12px; color: #a16207;"><?php esc_html_e('or', 'yatra'); ?></span>
718 837 <a href="<?php echo esc_url(wp_registration_url()); ?>" style="color: #3b82f6; text-decoration: none; font-weight: 500;">
719 838 <?php esc_html_e('Create an Account', 'yatra'); ?>
720 839 </a>
840 + <?php endif; ?>
721 841 </div>
722 842 </div>
723 843 </div>
724 844 <input type="hidden" name="login_required" value="1">
725 845
726 - <?php elseif (!$allow_guest_checkout) : ?>
727 - <!-- Account Required - Must Create Account -->
846 + <?php elseif (!$allow_guest_checkout && $registration_enabled) : ?>
847 + <!-- Account Required - Must Create Account (registration enabled) -->
728 848 <p class="yatra-section-description" style="margin-bottom: 16px;">
729 849 <?php esc_html_e('Please create an account to complete your booking. This allows you to manage your bookings and receive important updates.', 'yatra'); ?>
730 850 </p>
731 851
@@ -754,10 +874,10 @@
754 874 <?php esc_html_e('Your email address will be used as your username.', 'yatra'); ?>
755 875 </p>
756 876 <input type="hidden" name="create_account" value="1">
757 877
758 - <?php else : ?>
759 - <!-- Guest Checkout Allowed - Optional Account Creation -->
878 + <?php elseif ($registration_enabled) : ?>
879 + <!-- Guest Checkout Allowed - Optional Account Creation (registration enabled) -->
760 880 <p class="yatra-section-description" style="margin-bottom: 16px;">
761 881 <?php esc_html_e('Create an account to easily manage your bookings and receive travel updates.', 'yatra'); ?>
762 882 </p>
763 883
@@ -772,8 +892,9 @@
772 892 <label for="account_password">
773 893 <?php esc_html_e('Password', 'yatra'); ?> <span class="required">*</span>
774 894 </label>
775 895 <input type="password" id="account_password" name="account_password" minlength="8"
896 + autocomplete="new-password"
776 897 placeholder="<?php esc_attr_e('Minimum 8 characters', 'yatra'); ?>">
777 898 </div>
778 899 <div class="yatra-form-group yatra-field-half">
779 900 <label for="account_password_confirm">
@@ -779,8 +900,9 @@
779 900 <label for="account_password_confirm">
780 901 <?php esc_html_e('Confirm Password', 'yatra'); ?> <span class="required">*</span>
781 902 </label>
782 903 <input type="password" id="account_password_confirm" name="account_password_confirm" minlength="8"
904 + autocomplete="new-password"
783 905 placeholder="<?php esc_attr_e('Re-enter password', 'yatra'); ?>">
784 906 </div>
785 907 </div>
786 908 <p class="yatra-field-hint" style="font-size: 13px; color: #6b7280; margin-top: 8px;">
@@ -793,9 +915,9 @@
793 915 </p>
794 916 </div>
795 917 <?php endif; ?>
796 918 </div>
797 -<?php elseif (!is_user_logged_in()) : ?>
919 +<?php elseif (is_user_logged_in()) : ?>
798 920 <!-- User is logged in -->
799 921 <div class="yatra-booking-section yatra-logged-in-notice">
800 922 <div style="display: flex; align-items: center; gap: 12px; padding: 12px 16px; background: #ecfdf5; border: 1px solid #10b981; border-radius: 8px;">
801 923 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#059669" stroke-width="2">