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 +216 -66 3.0.2.7 → 3.0.16 View file →
@@ -30,29 +30,18 @@
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 -// Country list for country type fields
38 -$countries = [
39 - 'AF' => 'Afghanistan', 'AL' => 'Albania', 'DZ' => 'Algeria', 'AR' => 'Argentina',
40 - 'AU' => 'Australia', 'AT' => 'Austria', 'BD' => 'Bangladesh', 'BE' => 'Belgium',
41 - 'BR' => 'Brazil', 'BT' => 'Bhutan', 'CA' => 'Canada', 'CN' => 'China',
42 - 'CO' => 'Colombia', 'CZ' => 'Czech Republic', 'DK' => 'Denmark', 'EG' => 'Egypt',
43 - 'FI' => 'Finland', 'FR' => 'France', 'DE' => 'Germany', 'GR' => 'Greece',
44 - 'HK' => 'Hong Kong', 'HU' => 'Hungary', 'IS' => 'Iceland', 'IN' => 'India',
45 - 'ID' => 'Indonesia', 'IE' => 'Ireland', 'IL' => 'Israel', 'IT' => 'Italy',
46 - 'JP' => 'Japan', 'KE' => 'Kenya', 'KR' => 'South Korea', 'MY' => 'Malaysia',
47 - 'MV' => 'Maldives', 'MX' => 'Mexico', 'NL' => 'Netherlands', 'NZ' => 'New Zealand',
48 - 'NP' => 'Nepal', 'NO' => 'Norway', 'PK' => 'Pakistan', 'PE' => 'Peru',
49 - 'PH' => 'Philippines', 'PL' => 'Poland', 'PT' => 'Portugal', 'RO' => 'Romania',
50 - 'RU' => 'Russia', 'SA' => 'Saudi Arabia', 'SG' => 'Singapore', 'ZA' => 'South Africa',
51 - 'ES' => 'Spain', 'LK' => 'Sri Lanka', 'SE' => 'Sweden', 'CH' => 'Switzerland',
52 - 'TW' => 'Taiwan', 'TH' => 'Thailand', 'TR' => 'Turkey', 'AE' => 'United Arab Emirates',
53 - 'GB' => 'United Kingdom', 'US' => 'United States', 'VN' => 'Vietnam'
54 -];
39 +// Country list — pulls from the canonical FormatHelper source so every
40 +// dropdown (admin, public booking, Pro modules) shows the same full
41 +// ISO-3166-1 list. Operators that want a "popular countries" subset
42 +// or custom ordering apply the `yatra_countries_list` filter.
43 +$countries = \Yatra\Helpers\FormatHelper::getCountries();
55 44
56 45 /**
57 46 * Render a single form field based on configuration
58 47 *
@@ -66,9 +55,27 @@
66 55 function yatra_render_form_field($field, $prefix = '', $countries = [], $custom_name = null, $custom_id = null) {
67 56 if (empty($field['enabled'])) {
68 57 return;
69 58 }
70 -
59 +
60 + // Display-only text block: render admin-authored content (safe HTML) at this
61 + // position between fields. It is NOT an input — no label, name, value or
62 + // required handling — so it submits nothing and is never validated.
63 + if (($field['type'] ?? '') === 'text_block') {
64 + $tb_width = 'yatra-field-full';
65 + if (($field['width'] ?? '') === 'half') {
66 + $tb_width = 'yatra-field-half';
67 + } elseif (($field['width'] ?? '') === 'third') {
68 + $tb_width = 'yatra-field-third';
69 + }
70 + ?>
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'); ?>">
72 + <?php echo wpautop(wp_kses_post(yatra_translate_form_string($field['content'] ?? ''))); ?>
73 + </div>
74 + <?php
75 + return;
76 + }
77 +
71 78 $field_id = $custom_id ? esc_attr($custom_id) : esc_attr($prefix . $field['id']);
72 79 $field_name = $custom_name ? esc_attr($custom_name) : esc_attr($prefix . $field['id']);
73 80 $required = !empty($field['required']);
74 81 $required_attr = $required ? 'required' : '';
@@ -99,12 +106,12 @@
99 106 }
100 107 }
101 108 $field_type = $field['type'] ?? 'text';
102 109 ?>
103 - <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'); ?>">
104 111 <?php if ($field_type !== 'checkbox') : ?>
105 112 <label for="<?php echo $field_id; ?>">
106 - <?php echo esc_html($field['label']); ?> <?php echo $required_star; ?>
113 + <?php echo esc_html(yatra_translate_form_string($field['label'])); ?> <?php echo $required_star; ?>
107 114 </label>
108 115 <?php endif; ?>
109 116 <?php
110 117 switch ($field['type']) {
@@ -119,9 +126,9 @@
119 126 value="1"
120 127 <?php checked($is_checked, true, false); ?>
121 128 <?php echo $required_attr; ?>
122 129 />
123 - <span><?php echo esc_html($field['label']); ?><?php echo $required_star; ?></span>
130 + <span><?php echo esc_html(yatra_translate_form_string($field['label'])); ?><?php echo $required_star; ?></span>
124 131 </label>
125 132 <?php
126 133 break;
127 134 case 'select':
@@ -126,13 +133,13 @@
126 133 break;
127 134 case 'select':
128 135 ?>
129 136 <select id="<?php echo $field_id; ?>" name="<?php echo $field_name; ?>" <?php echo $required_attr; ?>>
130 - <option value=""><?php echo esc_html($field['placeholder'] ?? 'Select...'); ?></option>
137 + <option value=""><?php echo esc_html(yatra_translate_form_string($field['placeholder'] ?? '') ?: __('Select...', 'yatra')); ?></option>
131 138 <?php if (!empty($field['options'])) : ?>
132 139 <?php foreach ($field['options'] as $option) : ?>
133 140 <option value="<?php echo esc_attr($option['value']); ?>" <?php echo selected($prefill_value, (string) ($option['value'] ?? ''), false); ?>>
134 - <?php echo esc_html($option['label']); ?>
141 + <?php echo esc_html(yatra_translate_form_string($option['label'] ?? '')); ?>
135 142 </option>
136 143 <?php endforeach; ?>
137 144 <?php endif; ?>
138 145 </select>
@@ -139,11 +146,18 @@
139 146 <?php
140 147 break;
141 148
142 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/' : '';
143 155 ?>
144 - <select id="<?php echo $field_id; ?>" name="<?php echo $field_name; ?>" <?php echo $required_attr; ?>>
145 - <option value=""><?php echo esc_html($field['placeholder'] ?? 'Select Country'); ?></option>
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); ?>">
159 + <option value=""><?php echo esc_html(yatra_translate_form_string($field['placeholder'] ?? '') ?: __('Select Country', 'yatra')); ?></option>
146 160 <?php foreach ($countries as $code => $name) : ?>
147 161 <option value="<?php echo esc_attr($code); ?>" <?php echo selected($prefill_value, (string) $code, false); ?>>
148 162 <?php echo esc_html($name); ?>
149 163 </option>
@@ -156,9 +170,9 @@
156 170 ?>
157 171 <textarea
158 172 id="<?php echo $field_id; ?>"
159 173 name="<?php echo $field_name; ?>"
160 - placeholder="<?php echo esc_attr($field['placeholder'] ?? ''); ?>"
174 + placeholder="<?php echo esc_attr(yatra_translate_form_string($field['placeholder'] ?? '')); ?>"
161 175 <?php echo $required_attr; ?>
162 176 rows="3"
163 177 ><?php echo esc_textarea($prefill_value); ?></textarea>
164 178 <?php
@@ -165,14 +179,33 @@
165 179 break;
166 180
167 181 case 'date':
168 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';
169 199 ?>
170 - <input
171 - type="date"
172 - id="<?php echo $field_id; ?>"
200 + <input
201 + type="date"
202 + class="yatra-js-date"
203 + id="<?php echo $field_id; ?>"
173 204 name="<?php echo $field_name; ?>"
205 + placeholder="<?php echo esc_attr($date_placeholder); ?>"
174 206 <?php echo $min_attr; ?>
207 + <?php echo $dob_attr; ?>
175 208 <?php echo $required_attr; ?>
176 209 value="<?php echo esc_attr($prefill_value); ?>"
177 210 >
178 211 <?php
@@ -178,18 +211,81 @@
178 211 <?php
179 212 break;
180 213
181 214 default: // text, email, tel, number
182 - ?>
183 - <input
184 - type="<?php echo esc_attr($field['type']); ?>"
185 - id="<?php echo $field_id; ?>"
186 - name="<?php echo $field_name; ?>"
187 - placeholder="<?php echo esc_attr($field['placeholder'] ?? ''); ?>"
188 - <?php echo $required_attr; ?>
189 - value="<?php echo esc_attr($prefill_value); ?>"
190 - >
191 - <?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 + }
192 288 break;
193 289 }
194 290 ?>
195 291 </div>
@@ -227,11 +323,11 @@
227 323 }
228 324 }
229 325 ?>
230 326 <div class="yatra-booking-section">
231 - <h2 class="yatra-section-title"><?php echo esc_html($section_config['title'] ?? ''); ?></h2>
327 + <h2 class="yatra-section-title"><?php echo esc_html(yatra_translate_form_string($section_config['title'] ?? '')); ?></h2>
232 328 <?php if (!empty($section_config['description'])) : ?>
233 - <p class="yatra-section-description"><?php echo esc_html($section_config['description']); ?></p>
329 + <p class="yatra-section-description"><?php echo esc_html(yatra_translate_form_string($section_config['description'])); ?></p>
234 330 <?php endif; ?>
235 331
236 332 <?php foreach ($grouped_fields as $section_key => $section_fields) : ?>
237 333 <?php if ($section_key !== 'main') : ?>
@@ -409,17 +505,24 @@
409 505 $category_id = $pt->category_id ?? $index;
410 506 $category_label = $pt->category_label ?? __('Traveler', 'yatra');
411 507 $category_price = isset($pt->effective_price) ? (float) $pt->effective_price : ($pt->sale_price ?? $pt->discounted_price ?? $pt->original_price ?? 0);
412 508 $count = isset($traveler_counts[$category_id]) ? (int) $traveler_counts[$category_id] : ($index === 0 ? 1 : 0);
413 - $subtotal = $category_price * $count;
509 + // Single source of truth for the line amount (per-person × count, flat
510 + // per-group, or per-block group pricing). Defaults to the prior flat/
511 + // multiply behaviour when group_overflow is absent.
512 + $pt_pricing_mode = $pt->pricing_mode ?? 'per_person';
513 + $subtotal = \Yatra\Services\TripPricingService::categoryLineSubtotal($pt, $count, $category_price);
414 514
415 515 $age_info = '';
416 516 if (isset($pt->age_min) || isset($pt->age_max)) {
417 517 if (isset($pt->age_min) && isset($pt->age_max)) {
418 - $age_info = sprintf(__('(Age %d-%d)', 'yatra'), $pt->age_min, $pt->age_max);
518 + /* translators: 1: minimum age, 2: maximum age. */
519 + $age_info = sprintf(__('(Age %1$d-%2$d)', 'yatra'), $pt->age_min, $pt->age_max);
419 520 } elseif (isset($pt->age_min)) {
521 + /* translators: %d: minimum age. */
420 522 $age_info = sprintf(__('(Age %d+)', 'yatra'), $pt->age_min);
421 523 } else {
524 + /* translators: %d: maximum age. */
422 525 $age_info = sprintf(__('(Up to age %d)', 'yatra'), $pt->age_max);
423 526 }
424 527 }
425 528
@@ -428,8 +531,9 @@
428 531 'category_label' => $category_label,
429 532 'category_price' => $category_price,
430 533 'count' => $count,
431 534 'subtotal' => $subtotal,
535 + 'pricing_mode' => $pt_pricing_mode,
432 536 'age_info' => $age_info,
433 537 ];
434 538
435 539 $calculated_total += $subtotal;
@@ -455,13 +559,19 @@
455 559 $initial_due_amount = $initial_total_amount;
456 560
457 561 ?>
458 562
459 -<?php if (!empty($traveler_config) && !$is_remaining_payment) : ?>
563 +<?php
564 +// Honour the Traveler section's enable flag (Pro Dynamic Form module), mirroring
565 +// the Contact/Emergency sections. The default config has no `enabled` key, so an
566 +// un-customised/Free site treats the section as enabled and renders as before.
567 +$traveler_section_enabled = !isset($traveler_config['enabled']) || (bool) $traveler_config['enabled'];
568 +?>
569 +<?php if (!empty($traveler_config) && $traveler_section_enabled && !$is_remaining_payment) : ?>
460 570 <div class="yatra-booking-section">
461 - <h2 class="yatra-section-title"><?php echo esc_html($traveler_config['title'] ?? __('Traveler Information', 'yatra')); ?></h2>
571 + <h2 class="yatra-section-title"><?php echo esc_html(yatra_translate_form_string($traveler_config['title'] ?? '') ?: __('Traveler Information', 'yatra')); ?></h2>
462 572 <?php if (!empty($traveler_config['description'])) : ?>
463 - <p class="yatra-section-description"><?php echo esc_html($traveler_config['description']); ?></p>
573 + <p class="yatra-section-description"><?php echo esc_html(yatra_translate_form_string($traveler_config['description'])); ?></p>
464 574 <?php endif; ?>
465 575
466 576 <div id="yatra-travelers-container">
467 577 <?php
@@ -487,15 +597,31 @@
487 597 if (!empty($traveler_category_map[$i])) {
488 598 $category_info = $traveler_category_map[$i];
489 599 $category_label = $category_info['category_label'];
490 600 $category_index = $category_info['category_index'];
491 - $traveler_label = sprintf(__('%s %d', 'yatra'), $category_label, $category_index);
601 + /* translators: 1: traveler category label (e.g. Adult, Child), 2: sequential index within that category. */
602 + $traveler_label = sprintf(__('%1$s %2$d', 'yatra'), $category_label, $category_index);
492 603 if ($i === 1) {
493 604 $traveler_label .= ' (' . __('Lead Traveler', 'yatra') . ')';
494 605 }
495 606 } else {
607 + /* translators: %d: traveler sequence number. */
496 608 $traveler_label = ($i === 1) ? __('Traveler 1 (Lead Traveler)', 'yatra') : sprintf(__('Traveler %d', 'yatra'), $i);
497 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 + }
498 624 ?>
499 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; ?>>
500 626 <div class="yatra-traveler-header">
501 627 <h3 class="yatra-traveler-title"><?php echo esc_html($traveler_label); ?></h3>
@@ -503,9 +629,9 @@
503 629 <span class="yatra-traveler-note"><?php esc_html_e('Additional traveler', 'yatra'); ?></span>
504 630 <?php endif; ?>
505 631 </div>
506 632
507 - <?php foreach ($grouped_traveler_fields as $section_key => $section_fields) : ?>
633 + <?php foreach ($traveler_grouped_fields as $section_key => $section_fields) : ?>
508 634 <?php if ($section_key !== 'main') : ?>
509 635 <div class="yatra-traveler-subsection">
510 636 <h4 class="yatra-subsection-title">
511 637 <?php
@@ -549,16 +675,26 @@
549 675 */
550 676 $flexible_payments_enabled = apply_filters('yatra_flexible_payments_enabled', false);
551 677
552 678 /**
553 - * Filter to get payment method options
554 - * Pro module can add deposit/partial payment options via this filter
679 + * Filter to get payment method options.
680 + *
681 + * Pro module (FlexiblePayments) can add deposit/partial payment options here.
682 + * We pass `trip_id` so the Pro module can look up per-trip overrides
683 + * (trip.deposit_amount / trip.deposit_percentage) and expose the deposit
684 + * option even when the site-wide "deposit_required" flag is off — i.e. a
685 + * single trip can opt in to a custom deposit without enabling deposits for
686 + * the whole catalogue.
555 687 */
556 688 $payment_method_options = apply_filters('yatra_payment_method_options', [], [
557 - 'deposit_required' => $deposit_required,
558 - 'deposit_percentage' => $deposit_percentage,
559 - 'partial_payment' => $partial_payment,
689 + 'trip_id' => isset($trip_id) ? (int) $trip_id : 0,
690 + 'deposit_required' => $deposit_required,
691 + 'deposit_percentage' => $deposit_percentage,
692 + 'partial_payment' => $partial_payment,
560 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 : '',
561 697 ]);
562 698
563 699 $has_flexible_options = $flexible_payments_enabled && !empty($payment_method_options);
564 700 ?>
@@ -653,20 +789,28 @@
653 789 </div>
654 790 <?php endif; ?>
655 791
656 792 <!-- Account Creation Section (only for guests) -->
657 -<?php
793 +<?php
658 794 $allow_guest_checkout = \Yatra\Services\SettingsService::isEnabled('allow_guest_checkout');
659 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');
660 800
661 -// Show account section if user is not logged in
662 -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)) :
663 807 ?>
664 808 <div class="yatra-booking-section yatra-account-section">
665 809 <h2 class="yatra-section-title"><?php esc_html_e('Account', 'yatra'); ?></h2>
666 810
667 - <?php if ($require_login) : ?>
668 - <!-- 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) -->
669 813 <div class="yatra-login-required-notice" style="background: #fef3c7; border: 1px solid #f59e0b; padding: 16px; border-radius: 8px; margin-bottom: 16px;">
670 814 <div style="display: flex; align-items: flex-start; gap: 12px;">
671 815 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#d97706" stroke-width="2" style="flex-shrink: 0;">
672 816 <circle cx="12" cy="12" r="10"></circle>
@@ -675,9 +819,11 @@
675 819 </svg>
676 820 <div>
677 821 <p style="font-weight: 600; color: #92400e; margin: 0 0 8px 0;"><?php esc_html_e('Login Required', 'yatra'); ?></p>
678 822 <p style="color: #a16207; margin: 0 0 12px 0; font-size: 14px;">
679 - <?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'); ?>
680 826 </p>
681 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;">
682 828 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
683 829 <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
@@ -685,19 +831,21 @@
685 831 <line x1="15" y1="12" x2="3" y2="12"></line>
686 832 </svg>
687 833 <?php esc_html_e('Log In', 'yatra'); ?>
688 834 </a>
835 + <?php if ($registration_enabled) : ?>
689 836 <span style="margin: 0 12px; color: #a16207;"><?php esc_html_e('or', 'yatra'); ?></span>
690 837 <a href="<?php echo esc_url(wp_registration_url()); ?>" style="color: #3b82f6; text-decoration: none; font-weight: 500;">
691 838 <?php esc_html_e('Create an Account', 'yatra'); ?>
692 839 </a>
840 + <?php endif; ?>
693 841 </div>
694 842 </div>
695 843 </div>
696 844 <input type="hidden" name="login_required" value="1">
697 845
698 - <?php elseif (!$allow_guest_checkout) : ?>
699 - <!-- Account Required - Must Create Account -->
846 + <?php elseif (!$allow_guest_checkout && $registration_enabled) : ?>
847 + <!-- Account Required - Must Create Account (registration enabled) -->
700 848 <p class="yatra-section-description" style="margin-bottom: 16px;">
701 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'); ?>
702 850 </p>
703 851
@@ -726,10 +874,10 @@
726 874 <?php esc_html_e('Your email address will be used as your username.', 'yatra'); ?>
727 875 </p>
728 876 <input type="hidden" name="create_account" value="1">
729 877
730 - <?php else : ?>
731 - <!-- Guest Checkout Allowed - Optional Account Creation -->
878 + <?php elseif ($registration_enabled) : ?>
879 + <!-- Guest Checkout Allowed - Optional Account Creation (registration enabled) -->
732 880 <p class="yatra-section-description" style="margin-bottom: 16px;">
733 881 <?php esc_html_e('Create an account to easily manage your bookings and receive travel updates.', 'yatra'); ?>
734 882 </p>
735 883
@@ -744,8 +892,9 @@
744 892 <label for="account_password">
745 893 <?php esc_html_e('Password', 'yatra'); ?> <span class="required">*</span>
746 894 </label>
747 895 <input type="password" id="account_password" name="account_password" minlength="8"
896 + autocomplete="new-password"
748 897 placeholder="<?php esc_attr_e('Minimum 8 characters', 'yatra'); ?>">
749 898 </div>
750 899 <div class="yatra-form-group yatra-field-half">
751 900 <label for="account_password_confirm">
@@ -751,8 +900,9 @@
751 900 <label for="account_password_confirm">
752 901 <?php esc_html_e('Confirm Password', 'yatra'); ?> <span class="required">*</span>
753 902 </label>
754 903 <input type="password" id="account_password_confirm" name="account_password_confirm" minlength="8"
904 + autocomplete="new-password"
755 905 placeholder="<?php esc_attr_e('Re-enter password', 'yatra'); ?>">
756 906 </div>
757 907 </div>
758 908 <p class="yatra-field-hint" style="font-size: 13px; color: #6b7280; margin-top: 8px;">
@@ -765,9 +915,9 @@
765 915 </p>
766 916 </div>
767 917 <?php endif; ?>
768 918 </div>
769 -<?php elseif (!is_user_logged_in()) : ?>
919 +<?php elseif (is_user_logged_in()) : ?>
770 920 <!-- User is logged in -->
771 921 <div class="yatra-booking-section yatra-logged-in-notice">
772 922 <div style="display: flex; align-items: center; gap: 12px; padding: 12px 16px; background: #ecfdf5; border: 1px solid #10b981; border-radius: 8px;">
773 923 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#059669" stroke-width="2">