PluginProbe
Yatra – Travel Booking & Tour Operator Software / trunk
Yatra – Travel Booking & Tour Operator Software vtrunk
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 / Shortcodes / SearchShortcode.php

SearchShortcode.php in Yatra – Travel Booking & Tour Operator Software trunk, at app/Shortcodes/SearchShortcode.php

194 lines 7.8 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\Shortcodes;
6
7 /**
8 * Search Shortcode
9 *
10 * Displays advanced tour search functionality
11 */
12 class SearchShortcode extends BaseShortcode
13 {
14 private static bool $tripSearchAssetsQueued = false;
15
16 public function __construct()
17 {
18 parent::__construct('yatra_search', [
19 'show_filters' => 'yes',
20 'show_categories' => 'yes',
21 'show_destinations' => 'yes',
22 'show_activities' => 'yes',
23 'show_price_range' => 'yes',
24 'show_duration' => 'yes',
25 'show_difficulty' => 'yes',
26 'placeholder' => 'Search for tours...',
27 'button_text' => 'Search Tours',
28 // Per-field visibility overrides. Empty string = inherit the global
29 // Settings → Search & Listing toggle (so [yatra_search] is unchanged).
30 // Pass yes/no (or true/false, on/off, 1/0) to force a field on/off for
31 // this one placement, e.g. [yatra_search budget="no" keyword="yes"].
32 'keyword' => '',
33 'destination' => '',
34 'activities' => '',
35 'duration' => '',
36 'budget' => '',
37 'date' => '',
38 ]);
39
40 // [yatra_search] may appear in posts, widgets, builders, FSE templates, or do_shortcode()
41 // with no reliable way to detect that before output. Enqueue on every public frontend
42 // request so styles always print in wp_head (avoids FOUC). Rules are scoped to
43 // .yatra-trip-search-shortcode in trip-search-shortcode.css.
44 add_action('wp_enqueue_scripts', [self::class, 'enqueueTripSearchAssets'], 10);
45 }
46
47 /**
48 * Enqueue trip search bar CSS/JS for head output. Idempotent per request.
49 */
50 public static function enqueueTripSearchAssets(): void
51 {
52 if (is_admin() || is_feed()) {
53 return;
54 }
55 if (self::$tripSearchAssetsQueued) {
56 return;
57 }
58 self::$tripSearchAssetsQueued = true;
59
60 $tripSearchCssPath = YATRA_PLUGIN_PATH . 'assets/css/shortcodes/trip-search-shortcode.css';
61 $tripSearchCssVer = is_readable($tripSearchCssPath)
62 ? (string) filemtime($tripSearchCssPath)
63 : YATRA_VERSION;
64 wp_enqueue_style(
65 'yatra-trip-search-shortcode',
66 YATRA_PLUGIN_URL . 'assets/css/shortcodes/trip-search-shortcode.css',
67 [],
68 $tripSearchCssVer
69 );
70
71 // When the date field is enabled, load the same flatpickr library the
72 // checkout/booking page uses, so the search date field gets the styled
73 // calendar instead of the browser's native one. Gated on the global
74 // toggle so the extra CSS/JS only ships where the field is actually
75 // used; the search JS self-guards on `typeof flatpickr`, so a per-
76 // placement [yatra_search date="yes"] override still falls back safely
77 // to the native input when flatpickr is not present. Shared 'yatra-
78 // flatpickr' handle → WordPress de-dupes if another component enqueues
79 // it too.
80 $searchJsDeps = ['jquery'];
81 if (\Yatra\Services\SettingsService::isEnabled('search_show_date')) {
82 wp_enqueue_style(
83 'yatra-flatpickr',
84 'https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css',
85 [],
86 YATRA_VERSION
87 );
88 wp_enqueue_script(
89 'yatra-flatpickr',
90 'https://cdn.jsdelivr.net/npm/flatpickr',
91 [],
92 YATRA_VERSION,
93 true
94 );
95 $searchJsDeps[] = 'yatra-flatpickr';
96 }
97
98 $tripSearchJsPath = YATRA_PLUGIN_PATH . 'assets/js/trip-search-shortcode.js';
99 $tripSearchJsVer = is_readable($tripSearchJsPath)
100 ? (string) filemtime($tripSearchJsPath)
101 : YATRA_VERSION;
102 wp_enqueue_script(
103 'yatra-trip-search-shortcode',
104 YATRA_PLUGIN_URL . 'assets/js/trip-search-shortcode.js',
105 $searchJsDeps,
106 $tripSearchJsVer,
107 true
108 );
109
110 $listing_url = \function_exists('yatra_get_trip_listing_url')
111 ? \yatra_get_trip_listing_url()
112 : \trailingslashit(\home_url('/trip/'));
113
114 wp_localize_script(
115 'yatra-trip-search-shortcode',
116 'yatraTripSearchConfig',
117 [
118 'listingUrl' => $listing_url,
119 ]
120 );
121 }
122
123 /**
124 * Render the search shortcode content
125 */
126 protected function renderContent(array $atts): string
127 {
128 $atts = shortcode_atts($this->default_attributes, $atts, $this->tag);
129
130 // Same source as trip listing sidebar filters: published classifications.
131 // TripRepository::*ForSearch() only returned rows linked via trip_classifications,
132 // so empty relations hid all dropdown options.
133 $destinationRepository = new \Yatra\Repositories\DestinationRepository();
134 $activityRepository = new \Yatra\Repositories\ActivityRepository();
135 $destinations = $destinationRepository->getPublished();
136 $activities = $activityRepository->getPublished();
137 $tripListingService = new \Yatra\Services\TripListingService();
138 $tripRepository = new \Yatra\Repositories\TripRepository();
139
140 $listing_url = \function_exists('yatra_get_trip_listing_url')
141 ? \yatra_get_trip_listing_url()
142 : \trailingslashit(\home_url('/trip/'));
143
144 return $this->loadTemplate('shortcodes/trip-search.php', [
145 'atts' => $atts,
146 'destinations' => $destinations,
147 'activities' => $activities,
148 'listing_url' => $listing_url,
149 'duration_bounds' => $tripRepository->getDurationDaysBounds(),
150 'budget_presets' => $tripListingService->getSearchBudgetPresets(),
151 'field_visibility' => $this->resolveFieldVisibility($atts),
152 ]);
153 }
154
155 /**
156 * Resolve which search fields are visible for THIS shortcode instance.
157 *
158 * Each field follows the rule: an explicit shortcode attribute wins; when the
159 * attribute is omitted (empty), inherit the global Settings → Search & Listing
160 * toggle. This keeps a bare [yatra_search] identical to before while allowing
161 * per-placement overrides like [yatra_search budget="no"].
162 *
163 * @param array<string,mixed> $atts Resolved shortcode attributes.
164 * @return array<string,bool> Keyed by field: keyword/destination/activities/duration/budget.
165 */
166 private function resolveFieldVisibility(array $atts): array
167 {
168 $resolve = static function ($attr_value, string $setting_key): bool {
169 $value = strtolower(trim((string) $attr_value));
170 if ($value === '') {
171 // No override → inherit the global toggle (defaults to true).
172 return \Yatra\Services\SettingsService::isEnabled($setting_key);
173 }
174 if (\in_array($value, ['1', 'yes', 'true', 'on', 'show'], true)) {
175 return true;
176 }
177 if (\in_array($value, ['0', 'no', 'false', 'off', 'hide'], true)) {
178 return false;
179 }
180 // Unrecognised value → fall back to the global toggle, never guess.
181 return \Yatra\Services\SettingsService::isEnabled($setting_key);
182 };
183
184 return [
185 'keyword' => $resolve($atts['keyword'] ?? '', 'search_show_keyword'),
186 'destination' => $resolve($atts['destination'] ?? '', 'search_show_destination'),
187 'activities' => $resolve($atts['activities'] ?? '', 'search_show_activities'),
188 'duration' => $resolve($atts['duration'] ?? '', 'search_show_duration'),
189 'budget' => $resolve($atts['budget'] ?? '', 'search_show_budget'),
190 'date' => $resolve($atts['date'] ?? '', 'search_show_date'),
191 ];
192 }
193 }
194