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/trip-listing-card.php +73 -15 3.0.2.9 → 3.0.16 View file →
@@ -44,19 +44,43 @@
44 44 // Get all trip data using Trip model getter methods
45 45 $title = $trip->getTitle();
46 46 $duration = $trip->getDuration();
47 47 $difficulty = $trip->getDifficulty();
48 -// Calculate rating directly from reviews array (working correctly)
48 +
49 +// Prefer the SQL-aggregated average_rating / review_count that the
50 +// repository attaches to every listing row (AVG(r.rating) /
51 +// COUNT(DISTINCT r.id) over approved reviews). Falling back to a PHP
52 +// recount over `$trip->reviews` is only there for legacy callers that
53 +// hand-populate the reviews array without the aggregates.
54 +//
55 +// Earlier this block ALWAYS recounted from `$trip->reviews` — which
56 +// (a) forced the listing service into an N+1 of `findApprovedByTripId`
57 +// per displayed trip just to feed the recount, and (b) silently
58 +// rendered 0 stars on shortcode/block paths that already pass
59 +// aggregates with `reviews => []`.
60 +$sql_avg = isset($trip->average_rating) ? (float) $trip->average_rating : null;
61 +if ($sql_avg === null && isset($trip->avg_rating)) {
62 + $sql_avg = (float) $trip->avg_rating;
63 +}
64 +$sql_count = isset($trip->review_count) ? (int) $trip->review_count : null;
65 +if ($sql_count === null && isset($trip->reviews_count)) {
66 + $sql_count = (int) $trip->reviews_count;
67 +}
68 +
49 69 $reviews = $trip->reviews ?? [];
50 -$review_count = count($reviews);
51 -$average_rating = 0;
52 -
53 -if ($review_count > 0) {
54 - $total_rating = 0;
55 - foreach ($reviews as $review) {
56 - $total_rating += (float) ($review->rating ?? 0);
70 +if ($sql_avg !== null || $sql_count !== null) {
71 + $average_rating = $sql_avg !== null ? round($sql_avg, 1) : 0;
72 + $review_count = $sql_count !== null ? $sql_count : count($reviews);
73 +} else {
74 + $review_count = count($reviews);
75 + $average_rating = 0;
76 + if ($review_count > 0) {
77 + $total_rating = 0;
78 + foreach ($reviews as $review) {
79 + $total_rating += (float) ($review->rating ?? 0);
80 + }
81 + $average_rating = round($total_rating / $review_count, 1);
57 82 }
58 - $average_rating = round($total_rating / $review_count, 1);
59 83 }
60 84
61 85 $rating = [
62 86 'average_rating' => $average_rating,
@@ -69,8 +93,29 @@
69 93 }
70 94
71 95 $pricing = $trip->getPricing();
72 96 $discount = $trip->getDiscount();
97 +$yatra_dp_flags = function_exists('yatra_get_dynamic_pricing_display_flags') ? yatra_get_dynamic_pricing_display_flags() : [
98 + 'show_original_price' => true,
99 + 'show_savings_badge' => true,
100 + 'show_urgency_messages' => false,
101 +];
102 +$yatra_listing_urgency = [];
103 +if (!empty($yatra_dp_flags['show_urgency_messages'])) {
104 + $yatra_tid = (int) ($trip->id ?? 0);
105 + $yatra_listing_urgency = function_exists('yatra_trip_card_dynamic_pricing_urgency_lines')
106 + ? yatra_trip_card_dynamic_pricing_urgency_lines($yatra_tid, [
107 + 'base_sale_price' => (float) ($pricing['raw_current_price'] ?? 0),
108 + 'base_original_price' => (float) ($pricing['raw_original_price'] ?? 0),
109 + 'sale_price' => (float) ($pricing['raw_current_price'] ?? 0),
110 + 'original_price' => (float) ($pricing['raw_original_price'] ?? 0),
111 + 'departure_date' => null,
112 + 'spots_remaining' => null,
113 + 'availability_id' => null,
114 + 'surface' => 'listing',
115 + ])
116 + : [];
117 +}
73 118 $image = $trip->getImage();
74 119 $permalink = $trip->getPermalink();
75 120 $destinations = $trip->getDestinations();
76 121 $categories = $trip->getCategories();
@@ -158,9 +203,9 @@
158 203 </a>
159 204 <?php else: ?>
160 205 <img src="<?php echo esc_url($image['url']); ?>" alt="<?php echo esc_attr($image['alt']); ?>">
161 206 <?php endif; ?>
162 - <?php if ($discount['has_discount']): ?>
207 + <?php if ($discount['has_discount'] && !empty($yatra_dp_flags['show_savings_badge'])): ?>
163 208 <div class="yatra-discount-badge">
164 209 <?php
165 210 printf(
166 211 /* translators: %s: discount text (e.g. "10%") */
@@ -185,11 +230,14 @@
185 230 </svg>
186 231 </button>
187 232 <?php endif; ?>
188 233 <!-- Difficulty level overlay on bottom-right -->
189 - <?php if ($difficulty['has_difficulty'] && !empty($difficulty['icon'])): ?>
234 + <?php if ($difficulty['has_difficulty'] && (!empty($difficulty['icon_picker']) || !empty($difficulty['icon']))): ?>
190 235 <div class="yatra-difficulty-overlay">
191 - <?php echo yatra_svg_icon($difficulty['icon'], 'difficulty-icon'); ?>
236 + <?php
237 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
238 + echo yatra_stored_picker_icon_markup($difficulty['icon_picker'] ?? null, 'mountain', 'difficulty-icon');
239 + ?>
192 240 <?php echo ' ' . esc_html($difficulty['level']); ?>
193 241 </div>
194 242 <?php endif; ?>
195 243 </div>
@@ -308,9 +356,9 @@
308 356 </div>
309 357 </div>
310 358 <?php endif; ?>
311 359
312 - <?php if (!empty($difficulty['has_difficulty']) && empty($difficulty['icon'])) : ?>
360 + <?php if (!empty($difficulty['has_difficulty']) && empty($difficulty['icon']) && empty($difficulty['icon_picker'])) : ?>
313 361 <div class="yatra-trip-stat">
314 362 <div class="yatra-stat-icon difficulty">
315 363 <?php echo yatra_svg_icon('mountain', ''); ?>
316 364 </div>
@@ -372,9 +420,10 @@
372 420 $first_category = $yatra_categories_additional[0];
373 421 if (!empty($first_category->icon)) {
374 422 $icon_data = maybe_unserialize($first_category->icon);
375 423 if (is_array($icon_data) && isset($icon_data['type']) && $icon_data['type'] === 'icon' && !empty($icon_data['value'])) {
376 - echo yatra_svg_icon($icon_data['value'], 'category-icon');
424 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
425 + echo yatra_stored_picker_icon_markup($icon_data, 'tag', 'category-icon');
377 426 } else {
378 427 echo '<svg width="14" height="14" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M3 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V4zM3 10a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H4a1 1 0 01-1-1v-6zM14 9a1 1 0 00-1 1v6a1 1 0 001 1h2a1 1 0 001-1v-6a1 1 0 00-1-1h-2z" clip-rule="evenodd" /></svg>';
379 428 }
380 429 } else {
@@ -398,9 +447,9 @@
398 447 <div class="yatra-trip-card-price">
399 448 <span class="yatra-trip-price">
400 449 <?php if ($pricing['has_price']): ?>
401 450 <?php echo esc_html($pricing['price_prefix'] . $pricing['current_price']); ?>
402 - <?php if ($pricing['has_discount'] && !empty($pricing['original_price'])): ?>
451 + <?php if (!empty($yatra_dp_flags['show_original_price']) && $pricing['has_discount'] && !empty($pricing['original_price'])): ?>
403 452 <span class="yatra-original-price"><?php echo esc_html($pricing['original_price']); ?></span>
404 453 <?php endif; ?>
405 454 <?php else: ?>
406 455 <?php esc_html_e('Contact for pricing', 'yatra'); ?>
@@ -411,8 +460,17 @@
411 460 <a href="<?php echo esc_url($permalink); ?>" class="yatra-btn yatra-btn-primary yatra-archive-card-cta yatra-card-view-btn">
412 461 <?php echo function_exists('yatra_archive_listing_cta_icon_markup') ? yatra_archive_listing_cta_icon_markup($yatra_view_details_icon_slug, 'file-text') : yatra_svg_icon('file-text', 'yatra-btn-icon'); ?>
413 462 <span><?php esc_html_e('View Details', 'yatra'); ?></span>
414 463 </a>
464 + <?php endif; ?>
465 + <?php if (!empty($yatra_listing_urgency)) : ?>
466 + <div class="yatra-trip-listing-dp-urgency" style="width:100%;margin-top:8px;">
467 + <?php foreach ($yatra_listing_urgency as $yatra_urg_line) : ?>
468 + <div style="background-color:#fef3c7;color:#92400e;padding:6px 8px;border-radius:6px;font-size:12px;line-height:1.35;margin-top:4px;">
469 + <?php echo esc_html((string) $yatra_urg_line); ?>
470 + </div>
471 + <?php endforeach; ?>
472 + </div>
415 473 <?php endif; ?>
416 474 </div>
417 475 </div>
418 476 </div>