PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.7
Yatra – Travel Booking & Tour Operator Software v3.0.7
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 2.0.10 2.0.11 All 82 releases
yatra / app / Services / FilterService.php

FilterService.php in Yatra – Travel Booking & Tour Operator Software 3.0.7, at app/Services/FilterService.php

425 lines 20.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Yatra\Services;
6
7 use Yatra\Services\DifficultyLevelService;
8 use Yatra\Services\TripCategoryService;
9 use Yatra\Services\DestinationService;
10 use Yatra\Services\ActivityService;
11 use Yatra\Database\Tables\TripsTable;
12
13 /**
14 * Filter Service
15 * Contains business logic for rendering individual filter components
16 */
17 class FilterService extends BaseService
18 {
19 /**
20 * Render price range filter component
21 *
22 * @param array $active_filters Current active filters
23 * @param array $options Filter options (min_price, max_price, step)
24 * @return string HTML output
25 */
26 public function renderPriceRangeFilter(array $active_filters = [], array $options = []): string
27 {
28 // Get price range from TripRepository
29 $tripRepository = new \Yatra\Repositories\TripRepository();
30 $price_stats = $tripRepository->getPriceRangeStats();
31
32 $min_price = $options['min_price'] ?? ($price_stats->min_price ?? 100);
33 $max_price = $options['max_price'] ?? ($price_stats->max_price ?? 5000);
34 $step = $options['step'] ?? max(1, ($max_price - $min_price) / 100);
35
36 ob_start();
37 ?>
38 <div class="yatra-filter-section">
39 <div class="yatra-filter-title" data-toggle="price">
40 <div class="yatra-filter-title-content">
41 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
42 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1"/>
43 </svg>
44 <span>Price Range</span>
45 </div>
46 <div class="yatra-filter-actions">
47 <span class="yatra-clear-section" data-section="price">Clear</span>
48 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
49 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
50 </svg>
51 </div>
52 </div>
53 <div class="yatra-filter-content">
54 <div class="yatra-price-range">
55 <div class="yatra-price-inputs">
56 <div class="yatra-price-input-group">
57 <label class="yatra-price-input-label">Min Price</label>
58 <input type="number" name="price_min" placeholder="<?php echo $min_price; ?>" min="<?php echo $min_price; ?>" max="<?php echo $max_price; ?>" value="<?php echo !empty($active_filters['price_min']) ? esc_attr($active_filters['price_min']) : ''; ?>" id="priceMin">
59 </div>
60 <div class="yatra-price-separator"></div>
61 <div class="yatra-price-input-group">
62 <label class="yatra-price-input-label">Max Price</label>
63 <input type="number" name="price_max" placeholder="<?php echo $max_price; ?>" min="<?php echo $min_price; ?>" max="<?php echo $max_price; ?>" value="<?php echo !empty($active_filters['price_max']) ? esc_attr($active_filters['price_max']) : ''; ?>" id="priceMax">
64 </div>
65 </div>
66 <div class="yatra-price-slider">
67 <div class="yatra-price-slider-track" aria-hidden="true"></div>
68 <div class="yatra-price-slider-range" aria-hidden="true"></div>
69 <input type="range" min="<?php echo $min_price; ?>" max="<?php echo $max_price; ?>" step="<?php echo $step; ?>" value="<?php echo !empty($active_filters['price_min']) ? esc_attr($active_filters['price_min']) : $min_price; ?>" class="yatra-range-min" id="priceRangeMin" data-default="<?php echo esc_attr((string) $min_price); ?>">
70 <input type="range" min="<?php echo $min_price; ?>" max="<?php echo $max_price; ?>" step="<?php echo $step; ?>" value="<?php echo !empty($active_filters['price_max']) ? esc_attr($active_filters['price_max']) : $max_price; ?>" class="yatra-range-max" id="priceRangeMax" data-default="<?php echo esc_attr((string) $max_price); ?>">
71 </div>
72 <div class="yatra-price-display"><?php echo yatra_format_price($min_price); ?> - <?php echo yatra_format_price($max_price); ?></div>
73 </div>
74 </div>
75 </div>
76 <?php
77 return ob_get_clean();
78 }
79
80 /**
81 * Render difficulty level filter component
82 *
83 * @param array $active_filters Current active filters
84 * @param array $options Filter options
85 * @return string HTML output
86 */
87 public function renderDifficultyFilter(array $active_filters = [], array $options = []): string
88 {
89 $difficulty_service = new DifficultyLevelService();
90 $difficulty_levels = $difficulty_service->getPublished(['order_by' => 'sorting', 'order' => 'ASC']);
91
92 if (empty($difficulty_levels)) {
93 return '';
94 }
95
96 ob_start();
97 ?>
98 <div class="yatra-filter-section">
99 <div class="yatra-filter-title" data-toggle="difficulty">
100 <div class="yatra-filter-title-content">
101 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
102 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
103 </svg>
104 <span>Difficulty Level</span>
105 </div>
106 <div class="yatra-filter-actions">
107 <span class="yatra-clear-section" data-section="difficulty">Clear</span>
108 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
109 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
110 </svg>
111 </div>
112 </div>
113 <div class="yatra-filter-content">
114 <div class="yatra-checkbox-group">
115 <?php foreach ($difficulty_levels as $level) :
116 // Get trip count for this difficulty level
117 $tripRepository = new \Yatra\Repositories\TripRepository();
118 $trip_count = $tripRepository->countByDifficultyLevel($level->id);
119 ?>
120 <label class="yatra-checkbox-label">
121 <input type="checkbox" name="difficulty[]" value="<?php echo esc_attr($level->id); ?>" <?php echo in_array($level->id, $active_filters['difficulty'] ?? []) ? 'checked' : ''; ?>>
122 <span><?php echo esc_html($level->name); ?></span>
123 <span class="yatra-filter-count">(<?php echo (int)$trip_count; ?>)</span>
124 </label>
125 <?php endforeach; ?>
126 </div>
127 </div>
128 </div>
129 <?php
130 return ob_get_clean();
131 }
132
133 /**
134 * Render rating filter component
135 *
136 * @param array $active_filters Current active filters
137 * @param array $options Filter options
138 * @return string HTML output
139 */
140 public function renderRatingFilter(array $active_filters = [], array $options = []): string
141 {
142 ob_start();
143 ?>
144 <div class="yatra-filter-section">
145 <div class="yatra-filter-title" data-toggle="rating">
146 <div class="yatra-filter-title-content">
147 <svg class="yatra-filter-icon" width="18" height="18" fill="#fbbf24" viewBox="0 0 24 24">
148 <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
149 </svg>
150 <span>Rating</span>
151 </div>
152 <div class="yatra-filter-actions">
153 <span class="yatra-clear-section" data-section="rating">Clear</span>
154 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
155 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
156 </svg>
157 </div>
158 </div>
159 <div class="yatra-filter-content">
160 <div class="yatra-rating-filter">
161 <?php
162 global $wpdb;
163 $rating_options = [
164 ['stars' => 5, 'label' => 'And Up'],
165 ['stars' => 4, 'label' => 'And Up'],
166 ['stars' => 3, 'label' => 'And Up'],
167 ['stars' => 2, 'label' => 'And Up'],
168 ['stars' => 1, 'label' => 'And Up']
169 ];
170
171 // Check if reviews table exists and get trip counts
172 $tripRepository = new \Yatra\Repositories\TripRepository();
173 $reviews_table_exists = $tripRepository->reviewsTableExists();
174
175 foreach ($rating_options as $option) :
176 // Get trip count for this rating and above
177 $trip_count = 0;
178 if ($reviews_table_exists) {
179 $trip_count = $tripRepository->countByMinRating($option['stars']);
180 }
181 ?>
182 <label class="yatra-rating-option">
183 <input type="checkbox" name="rating[]" value="<?php echo esc_attr($option['stars']); ?>" <?php echo in_array($option['stars'], $active_filters['rating'] ?? []) ? 'checked' : ''; ?>>
184 <div class="yatra-stars-display">
185 <?php for ($i = 1; $i <= 5; $i++) : ?>
186 <svg class="yatra-star <?php echo $i <= $option['stars'] ? 'filled' : 'empty'; ?>" width="16" height="16" viewBox="0 0 24 24">
187 <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" fill="<?php echo $i <= $option['stars'] ? '#fbbf24' : '#e5e7eb'; ?>"/>
188 </svg>
189 <?php endfor; ?>
190 <span class="yatra-rating-label"><?php echo esc_html($option['label']); ?></span>
191 </div>
192 </label>
193 <?php endforeach; ?>
194 </div>
195 </div>
196 </div>
197 <?php
198 return ob_get_clean();
199 }
200
201 /**
202 * Render categories filter component
203 *
204 * @param array $active_filters Current active filters
205 * @param array $options Filter options
206 * @return string HTML output
207 */
208 public function renderCategoriesFilter(array $active_filters = [], array $options = []): string
209 {
210 $category_service = new TripCategoryService();
211 $categories = $category_service->getPublished(['order_by' => 'name', 'order' => 'ASC']);
212
213 if (empty($categories)) {
214 return '';
215 }
216
217 ob_start();
218 ?>
219 <div class="yatra-filter-section">
220 <div class="yatra-filter-title" data-toggle="categories">
221 <div class="yatra-filter-title-content">
222 <svg class="yatra-filter-icon" width="18" height="18" fill="currentColor" viewBox="0 0 20 20">
223 <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" />
224 </svg>
225 <span>Categories</span>
226 </div>
227 <div class="yatra-filter-actions">
228 <span class="yatra-clear-section" data-section="categories">Clear</span>
229 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
230 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
231 </svg>
232 </div>
233 </div>
234 <div class="yatra-filter-content">
235 <div class="yatra-checkbox-group">
236 <?php foreach ($categories as $category) :
237 // Get trip count for this category
238 $tripRepository = new \Yatra\Repositories\TripRepository();
239 $trip_count = $tripRepository->countByCategory($category->id);
240
241 if ($trip_count > 0) :
242 ?>
243 <label class="yatra-checkbox-label">
244 <input type="checkbox" name="categories[]" value="<?php echo esc_attr($category->id); ?>" <?php echo in_array($category->id, $active_filters['categories'] ?? []) ? 'checked' : ''; ?>>
245 <span><?php echo esc_html($category->name); ?></span>
246 <span class="yatra-filter-count">(<?php echo (int)$trip_count; ?>)</span>
247 </label>
248 <?php endif; endforeach; ?>
249 </div>
250 </div>
251 </div>
252 <?php
253 return ob_get_clean();
254 }
255
256 /**
257 * Render destinations filter component
258 *
259 * @param array $active_filters Current active filters
260 * @param array $options Filter options
261 * @return string HTML output
262 */
263 public function renderDestinationsFilter(array $active_filters = [], array $options = []): string
264 {
265 $destination_service = new DestinationService();
266 $destinations = $destination_service->getPublished(['order_by' => 'name', 'order' => 'ASC', 'limit' => 15]);
267
268 if (empty($destinations)) {
269 return '';
270 }
271
272 ob_start();
273 ?>
274 <div class="yatra-filter-section">
275 <div class="yatra-filter-title" data-toggle="destinations">
276 <div class="yatra-filter-title-content">
277 <svg class="yatra-filter-icon" width="18" height="18" fill="currentColor" viewBox="0 0 20 20">
278 <path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd" />
279 </svg>
280 <span>Destinations</span>
281 </div>
282 <div class="yatra-filter-actions">
283 <span class="yatra-clear-section" data-section="destinations">Clear</span>
284 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
285 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
286 </svg>
287 </div>
288 </div>
289 <div class="yatra-filter-content">
290 <div class="yatra-checkbox-group">
291 <?php foreach ($destinations as $destination) :
292 // Get trip count for this destination
293 $tripRepository = new \Yatra\Repositories\TripRepository();
294 $trip_count = $tripRepository->countByDestination($destination->id);
295
296 if ($trip_count > 0) :
297 ?>
298 <label class="yatra-checkbox-label">
299 <input type="checkbox" name="destinations[]" value="<?php echo esc_attr($destination->id); ?>" <?php echo in_array($destination->id, $active_filters['destinations'] ?? []) ? 'checked' : ''; ?>>
300 <span><?php echo esc_html($destination->name); ?></span>
301 <span class="yatra-filter-count">(<?php echo (int)$trip_count; ?>)</span>
302 </label>
303 <?php endif; endforeach; ?>
304 </div>
305 </div>
306 </div>
307 <?php
308 return ob_get_clean();
309 }
310
311 /**
312 * Render activities filter component
313 *
314 * @param array $active_filters Current active filters
315 * @param array $options Filter options
316 * @return string HTML output
317 */
318 public function renderActivitiesFilter(array $active_filters = [], array $options = []): string
319 {
320 $activity_service = new ActivityService();
321 $activities = $activity_service->getPublished(['order_by' => 'name', 'order' => 'ASC', 'limit' => 15]);
322
323 if (empty($activities)) {
324 return '';
325 }
326
327 ob_start();
328 ?>
329 <div class="yatra-filter-section">
330 <div class="yatra-filter-title" data-toggle="activities">
331 <div class="yatra-filter-title-content">
332 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
333 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
334 </svg>
335 <span>Activities</span>
336 </div>
337 <div class="yatra-filter-actions">
338 <span class="yatra-clear-section" data-section="activities">Clear</span>
339 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
340 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
341 </svg>
342 </div>
343 </div>
344 <div class="yatra-filter-content">
345 <div class="yatra-checkbox-group">
346 <?php foreach ($activities as $activity) :
347 // Get trip count for this activity
348 $tripRepository = new \Yatra\Repositories\TripRepository();
349 $trip_count = $tripRepository->countByActivity($activity->id);
350
351 if ($trip_count > 0) :
352 ?>
353 <label class="yatra-checkbox-label">
354 <input type="checkbox" name="activities[]" value="<?php echo esc_attr($activity->id); ?>" <?php echo in_array($activity->id, $active_filters['activities'] ?? []) ? 'checked' : ''; ?>>
355 <span><?php echo esc_html($activity->name); ?></span>
356 <span class="yatra-filter-count">(<?php echo (int)$trip_count; ?>)</span>
357 </label>
358 <?php endif; endforeach; ?>
359 </div>
360 </div>
361 </div>
362 <?php
363 return ob_get_clean();
364 }
365
366 /**
367 * Render complete filter sidebar
368 *
369 * @param array $active_filters Current active filters
370 * @param array $options Filter options and configuration
371 * @return string HTML output
372 */
373 public function renderFilterSidebar(array $active_filters = [], array $options = []): string
374 {
375 $enabled_filters = $options['enabled_filters'] ?? [
376 'price_range', 'difficulty', 'rating', 'categories', 'destinations', 'activities'
377 ];
378
379 ob_start();
380 ?>
381 <aside class="yatra-filter-sidebar">
382 <div class="yatra-filter-header">
383 <h2>Filters</h2>
384 <span class="yatra-clear-filters">Clear all</span>
385 </div>
386
387 <?php
388 foreach ($enabled_filters as $filter_type) {
389 switch ($filter_type) {
390 case 'price_range':
391 echo $this->renderPriceRangeFilter($active_filters, $options);
392 break;
393 case 'difficulty':
394 echo $this->renderDifficultyFilter($active_filters, $options);
395 break;
396 case 'rating':
397 echo $this->renderRatingFilter($active_filters, $options);
398 break;
399 case 'categories':
400 echo $this->renderCategoriesFilter($active_filters, $options);
401 break;
402 case 'destinations':
403 echo $this->renderDestinationsFilter($active_filters, $options);
404 break;
405 case 'activities':
406 echo $this->renderActivitiesFilter($active_filters, $options);
407 break;
408 }
409 }
410 ?>
411 </aside>
412 <?php
413 return ob_get_clean();
414 }
415
416 /**
417 * Get repository (required by BaseService)
418 */
419 protected function getRepository()
420 {
421 // FilterService doesn't need a repository
422 return null;
423 }
424 }
425