PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.17
Yatra – Travel Booking & Tour Operator Software v3.0.17
3.0.17 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 All 85 releases
← All changes | templates/partials/single-trip/content-itinerary.php +84 -17 3.0.3 → 3.0.17 View file →
@@ -81,9 +81,10 @@
81 81 </div>
82 82 <?php endif; ?>
83 83 <div class="yatra-entries-timeline">
84 84 <?php foreach ($day['entries'] as $index => $entry):
85 - $type_color = $type_colors[$entry['item_type']] ?? '#6b7280';
85 + $rawColor = isset($entry['item_type_color']) ? (string) $entry['item_type_color'] : '';
86 + $type_color = $rawColor !== '' ? $rawColor : ($type_colors[$entry['item_type']] ?? '#6b7280');
86 87 ?>
87 88 <div class="yatra-entry-item" style="--entry-color: <?php echo esc_attr($type_color); ?>">
88 89 <div class="yatra-entry-timeline-dot"></div>
89 90 <div class="yatra-entry-card">
@@ -88,22 +89,41 @@
88 89 <div class="yatra-entry-timeline-dot"></div>
89 90 <div class="yatra-entry-card">
90 91 <div class="yatra-entry-header">
91 92 <div class="yatra-entry-icon" style="background: <?php echo esc_attr($type_color); ?>15; color: <?php echo esc_attr($type_color); ?>">
92 - <?php echo $get_icon($entry['icon']); ?>
93 + <?php
94 + // Prefer icon picker data from backend (supports Font Awesome + images).
95 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
96 + echo yatra_stored_picker_icon_markup($entry['icon_picker'] ?? null, 'hiking', 'yatra-icon-sm');
97 + ?>
93 98 </div>
94 99 <div class="yatra-entry-info">
95 100 <span class="yatra-entry-type" style="color: <?php echo esc_attr($type_color); ?>"><?php echo esc_html(yatra_itinerary_item_type_label((string) $entry['item_type'])); ?></span>
96 101 <h4 class="yatra-entry-title"><?php echo esc_html($entry['title']); ?></h4>
97 102 </div>
98 - <?php if ($entry['start_time']): ?>
103 + <?php
104 + // Time block honours `time_type`:
105 + // - exact → render the start/end time range (only if values exist)
106 + // - duration → suppress the time pill entirely (the duration value renders
107 + // in the meta row below)
108 + // - flexible → render a "Flexible" label so readers know intentionally no time
109 + $entryTimeType = $entry['time_type'] ?? 'exact';
110 + $hasStart = !empty($entry['start_time']);
111 + $hasEnd = !empty($entry['end_time']);
112 + $showTimePill = ($entryTimeType === 'exact' && $hasStart) || $entryTimeType === 'flexible';
113 + ?>
114 + <?php if ($showTimePill): ?>
99 115 <div class="yatra-entry-time">
100 116 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
101 117 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
102 118 </svg>
103 119 <span>
104 - <?php echo esc_html($entry['start_time']); ?>
105 - <?php if ($entry['end_time']) { echo ' - ' . esc_html($entry['end_time']); } ?>
120 + <?php if ($entryTimeType === 'flexible'): ?>
121 + <?php esc_html_e('Flexible', 'yatra'); ?>
122 + <?php else: ?>
123 + <?php echo esc_html($entry['start_time']); ?>
124 + <?php if ($hasEnd) { echo ' - ' . esc_html($entry['end_time']); } ?>
125 + <?php endif; ?>
106 126 </span>
107 127 </div>
108 128 <?php endif; ?>
109 129 </div>
@@ -109,8 +129,20 @@
109 129 </div>
110 130
111 131 <p class="yatra-entry-description"><?php echo esc_html($entry['description']); ?></p>
112 132
133 + <?php if (!empty($entry['notes'])): ?>
134 + <div class="yatra-entry-notes" role="note" aria-label="<?php esc_attr_e('Note', 'yatra'); ?>">
135 + <div class="yatra-entry-notes__head">
136 + <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
137 + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
138 + </svg>
139 + <span class="yatra-entry-notes__label"><?php esc_html_e('Note', 'yatra'); ?></span>
140 + </div>
141 + <div class="yatra-entry-notes__body"><?php echo wp_kses_post(wpautop($entry['notes'])); ?></div>
142 + </div>
143 + <?php endif; ?>
144 +
113 145 <?php if (!empty($entry['cost']) && $entry['cost'] > 0): ?>
114 146 <div class="yatra-entry-cost">
115 147 <span class="yatra-cost-amount">
116 148 <?php echo yatra_format_price($entry['cost']); ?>
@@ -143,18 +175,49 @@
143 175 </div>
144 176 <?php endif; ?>
145 177 </div>
146 178
147 - <?php if (!empty($entry['included'])): ?>
148 - <div class="yatra-entry-included">
149 - <?php foreach ($entry['included'] as $item): ?>
150 - <span class="yatra-included-tag">
151 - <svg width="12" height="12" fill="none" stroke="currentColor" viewBox="0 0 24 24">
152 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
153 - </svg>
154 - <?php echo esc_html($item); ?>
155 - </span>
156 - <?php endforeach; ?>
179 + <?php if (!empty($entry['included']) || !empty($entry['excluded'])): ?>
180 + <div class="yatra-entry-inclusions" role="group" aria-label="<?php echo esc_attr__('Included and excluded items', 'yatra'); ?>">
181 + <div class="yatra-entry-inclusions-col is-included">
182 + <div class="yatra-entry-inclusions-heading">
183 + <span class="yatra-entry-inclusions-title"><?php echo esc_html__('Included', 'yatra'); ?></span>
184 + </div>
185 + <div class="yatra-entry-inclusions-tags">
186 + <?php if (!empty($entry['included'])): ?>
187 + <?php foreach ($entry['included'] as $item): ?>
188 + <span class="yatra-included-tag">
189 + <svg width="12" height="12" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
190 + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
191 + </svg>
192 + <?php echo esc_html($item); ?>
193 + </span>
194 + <?php endforeach; ?>
195 + <?php else: ?>
196 + <span class="yatra-entry-inclusions-empty"><?php echo esc_html__('None', 'yatra'); ?></span>
197 + <?php endif; ?>
198 + </div>
199 + </div>
200 +
201 + <div class="yatra-entry-inclusions-col is-excluded">
202 + <div class="yatra-entry-inclusions-heading">
203 + <span class="yatra-entry-inclusions-title"><?php echo esc_html__('Excluded', 'yatra'); ?></span>
204 + </div>
205 + <div class="yatra-entry-inclusions-tags">
206 + <?php if (!empty($entry['excluded'])): ?>
207 + <?php foreach ($entry['excluded'] as $item): ?>
208 + <span class="yatra-excluded-tag">
209 + <svg width="12" height="12" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
210 + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
211 + </svg>
212 + <?php echo esc_html($item); ?>
213 + </span>
214 + <?php endforeach; ?>
215 + <?php else: ?>
216 + <span class="yatra-entry-inclusions-empty"><?php echo esc_html__('None', 'yatra'); ?></span>
217 + <?php endif; ?>
218 + </div>
219 + </div>
157 220 </div>
158 221 <?php endif; ?>
159 222
160 223 <!-- Gallery Section -->
@@ -188,9 +251,13 @@
188 251 data-image-index="<?php echo esc_attr($global_index + $index); ?>">
189 252 <div class="yatra-media-card">
190 253 <img src="<?php echo esc_url($media['thumbnail_url'] ?? $media['url'] ?? ''); ?>"
191 254 data-full-size="<?php echo esc_url($media['url'] ?? ''); ?>"
192 - alt="<?php echo esc_attr($media['alt_text'] ?? $media['caption'] ?? $media['title'] ?? sprintf(__('Itinerary Gallery Image %d', 'yatra'), $global_index + $index + 1)); ?>"
255 + alt="<?php echo esc_attr($media['alt_text'] ?? $media['caption'] ?? $media['title'] ?? sprintf(
256 + /* translators: %d: gallery image sequence number. */
257 + __('Itinerary Gallery Image %d', 'yatra'),
258 + $global_index + $index + 1
259 + )); ?>"
193 260 loading="lazy">
194 261 <?php if (isset($media['type']) && $media['type'] === 'video'): ?>
195 262 <div class="yatra-media-overlay">
196 263 <svg width="32" height="32" fill="white" viewBox="0 0 24 24">
@@ -215,9 +282,9 @@
215 282
216 283 // Extract video ID and thumbnail
217 284 if (strpos($video_url, 'youtube.com') !== false || strpos($video_url, 'youtu.be') !== false) {
218 285 // YouTube thumbnail extraction
219 - preg_match('/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/', $video_url, $matches);
286 + preg_match('/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/|youtube\.com\/shorts\/|youtube\.com\/live\/)([^&\n?#\/]+)/', $video_url, $matches);
220 287 $video_id = $matches[1] ?? '';
221 288 $thumbnail_url = "https://img.youtube.com/vi/{$video_id}/maxresdefault.jpg";
222 289 } elseif (strpos($video_url, 'vimeo.com') !== false) {
223 290 // Vimeo thumbnail extraction