PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.3
Yatra – Travel Booking & Tour Operator Software v3.0.3
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 / Core / Modules / ModuleManager.php

ModuleManager.php in Yatra – Travel Booking & Tour Operator Software 3.0.3, at app/Core/Modules/ModuleManager.php

423 lines 18.7 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\Core\Modules;
6
7 /**
8 * Module Manager
9 * Handles module definitions and persistence via wp_options
10 */
11 class ModuleManager
12 {
13 private const OPTION_KEY = 'yatra_modules';
14 private const DEFAULT_VIDEO_URL = 'https://youtu.be/cHmC-x7y0TQ';
15
16 /**
17 * Ensure option exists with defaults
18 */
19 public static function initializeDefaults(): void
20 {
21 if (get_option(self::OPTION_KEY) === false) {
22 $defaults = [];
23 $timestamp = current_time('mysql');
24
25 foreach (self::getDefaultModules() as $module) {
26 $defaults[$module['slug']] = [
27 'enabled' => !empty($module['enabled']),
28 'updated_at' => $timestamp,
29 ];
30 }
31
32 add_option(self::OPTION_KEY, $defaults);
33 }
34 }
35
36 /**
37 * Get default module definitions
38 */
39 public static function getDefaultModules(): array
40 {
41 $modules = [
42 [
43 'slug' => 'google_calendar',
44 'name' => __('Google Calendar Integration', 'yatra'),
45 'description' => __('Automatically sync bookings and departures to Google Calendar. Keep travelers informed with calendar invitations. Perfect integration for managing your travel schedule.', 'yatra'),
46 'category' => __('Integrations', 'yatra'),
47 'docs_url' => 'https://docs.yatra.com/modules/google-calendar',
48 'is_premium' => true,
49 'purchase_url' => 'https://wpyatra.com/pricing?module=google-calendar',
50 'is_core' => false,
51 'enabled' => false,
52 'tags' => ['integrations', 'calendar', 'automation'],
53 'video_url' => self::DEFAULT_VIDEO_URL,
54 'requires_pro' => true,
55 'settings_page' => 'yatra-google-calendar',
56 ],
57 [
58 'slug' => 'additional_services',
59 'name' => __('Additional Services', 'yatra'),
60 'description' => __('Offer optional add-ons like airport transfers, travel insurance, and equipment rental. Increase revenue per booking with valuable extras travelers want. Enhance complete trip experience for your customers.', 'yatra'),
61 'category' => __('Sales', 'yatra'),
62 'docs_url' => 'https://docs.yatra.com/modules/additional-services',
63 'is_premium' => true,
64 'purchase_url' => 'https://wpyatra.com/pricing?module=additional-services',
65 'is_core' => false,
66 'enabled' => false,
67 'tags' => ['upsell', 'services', 'add-ons', 'extras'],
68 'video_url' => self::DEFAULT_VIDEO_URL,
69 'requires_pro' => true,
70 'settings_page' => 'yatra-additional-services',
71 ],
72 [
73 'slug' => 'trip_consent',
74 'name' => __('Trip Consent', 'yatra'),
75 'description' => __('Collect digital consent forms and signatures from travelers before their trip. Includes liability waivers and health declarations. Ensure legal compliance and protect your business.', 'yatra'),
76 'category' => __('Operations', 'yatra'),
77 'docs_url' => 'https://docs.yatra.com/modules/trip-consent',
78 'is_premium' => true,
79 'purchase_url' => 'https://wpyatra.com/pricing?module=trip-consent',
80 'is_core' => false,
81 'enabled' => false,
82 'tags' => ['consent', 'waiver', 'signature', 'forms', 'legal'],
83 'video_url' => self::DEFAULT_VIDEO_URL,
84 'requires_pro' => true,
85 'settings_page' => 'yatra-trip-consent',
86 ],
87 [
88 'slug' => 'email_automation',
89 'name' => __('Email Automation', 'yatra'),
90 'description' => __('Adds the full automation template library (database), sequences, and send logs on the Email screen. Everyone already gets Delivery settings plus the four core customer templates (booking, payment, cancellation, reminder) without this module.', 'yatra'),
91 'category' => __('Marketing', 'yatra'),
92 'docs_url' => 'https://docs.yatra.com/modules/email-automation',
93 'is_premium' => true,
94 'purchase_url' => 'https://wpyatra.com/pricing?module=email-automation',
95 'is_core' => false,
96 'enabled' => false,
97 'tags' => ['email', 'automation', 'templates', 'marketing', 'notifications'],
98 'video_url' => self::DEFAULT_VIDEO_URL,
99 'requires_pro' => true,
100 'settings_page' => 'email-automation',
101 ],
102 [
103 'slug' => 'dynamic_form_field',
104 'name' => __('Dynamic Form Field', 'yatra'),
105 'description' => __('Customize booking form fields with drag-and-drop builder. Add custom fields for traveler information and emergency contacts. Create the perfect booking experience for your customers.', 'yatra'),
106 'category' => __('Bookings', 'yatra'),
107 'docs_url' => 'https://docs.yatra.com/modules/dynamic-form-field',
108 'is_premium' => true,
109 'purchase_url' => 'https://wpyatra.com/pricing?module=dynamic-form-field',
110 'is_core' => false,
111 'enabled' => false,
112 'tags' => ['form', 'booking', 'customization', 'fields', 'builder'],
113 'video_url' => self::DEFAULT_VIDEO_URL,
114 'requires_pro' => true,
115 'settings_page' => 'yatra-settings',
116 ],
117 [
118 'slug' => 'advanced_discount',
119 'name' => __('Advanced Discount', 'yatra'),
120 'description' => __('Create group discounts that auto-apply based on traveler count. Combine promo codes with group savings for maximum flexibility and conversion optimization.', 'yatra'),
121 'category' => __('Marketing', 'yatra'),
122 'docs_url' => 'https://docs.yatra.com/modules/advanced-discount',
123 'is_premium' => true,
124 'purchase_url' => 'https://wpyatra.com/pricing?module=advanced-discount',
125 'is_core' => false,
126 'enabled' => false,
127 'tags' => ['discount', 'group', 'promo', 'coupon', 'marketing'],
128 'video_url' => self::DEFAULT_VIDEO_URL,
129 'requires_pro' => true,
130 ],
131 [
132 'slug' => 'mailchimp',
133 'name' => __('Mailchimp Integration', 'yatra'),
134 'description' => __('Automatically sync customers to Mailchimp lists when they book. Add tags based on trips booked. Build targeted email campaigns and nurture leads effectively.', 'yatra'),
135 'category' => __('Marketing', 'yatra'),
136 'docs_url' => 'https://docs.yatra.com/modules/mailchimp',
137 'is_premium' => true,
138 'purchase_url' => 'https://wpyatra.com/pricing?module=mailchimp',
139 'is_core' => false,
140 'enabled' => false,
141 'tags' => ['email', 'marketing', 'mailchimp', 'automation', 'integration'],
142 'video_url' => self::DEFAULT_VIDEO_URL,
143 'requires_pro' => true,
144 'settings_page' => 'yatra-mailchimp',
145 ],
146 [
147 'slug' => 'facebook_pixel',
148 'name' => __('Facebook Pixel', 'yatra'),
149 'description' => __('Track booking conversions with Facebook Pixel. Retarget visitors who viewed trips. Optimize ad campaigns with accurate conversion data and build lookalike audiences.', 'yatra'),
150 'category' => __('Marketing', 'yatra'),
151 'docs_url' => 'https://docs.yatra.com/modules/facebook-pixel',
152 'is_premium' => true,
153 'purchase_url' => 'https://wpyatra.com/pricing?module=facebook-pixel',
154 'is_core' => false,
155 'enabled' => false,
156 'tags' => ['facebook', 'pixel', 'tracking', 'ads', 'retargeting', 'marketing'],
157 'video_url' => self::DEFAULT_VIDEO_URL,
158 'requires_pro' => true,
159 'settings_page' => 'yatra-facebook-pixel',
160 ],
161 [
162 'slug' => 'google_analytics',
163 'name' => __('Google Analytics 4 Enhanced', 'yatra'),
164 'description' => __('Enhanced e-commerce tracking for GA4. Track view_item, begin_checkout, and purchase events. Server-side tracking via Measurement Protocol for accurate conversion data.', 'yatra'),
165 'category' => __('Marketing', 'yatra'),
166 'docs_url' => 'https://docs.yatra.com/modules/google-analytics',
167 'is_premium' => true,
168 'purchase_url' => 'https://wpyatra.com/pricing?module=google-analytics',
169 'is_core' => false,
170 'enabled' => false,
171 'tags' => ['google', 'analytics', 'ga4', 'tracking', 'ecommerce', 'marketing'],
172 'video_url' => self::DEFAULT_VIDEO_URL,
173 'requires_pro' => true,
174 'settings_page' => 'yatra-google-analytics',
175 ],
176 [
177 'slug' => 'flexible_payments',
178 'name' => __('Flexible Payments', 'yatra'),
179 'description' => __('Enable deposit and partial payment options for bookings. Allow customers to pay a percentage upfront and the rest later. Perfect for high-value trips and improving conversion rates.', 'yatra'),
180 'category' => __('Payments', 'yatra'),
181 'docs_url' => 'https://docs.yatra.com/modules/flexible-payments',
182 'is_premium' => true,
183 'purchase_url' => 'https://wpyatra.com/pricing?module=flexible-payments',
184 'is_core' => false,
185 'enabled' => false,
186 'tags' => ['payments', 'deposit', 'partial', 'installments', 'booking'],
187 'video_url' => self::DEFAULT_VIDEO_URL,
188 'requires_pro' => true,
189 'settings_page' => 'yatra-settings',
190 ],
191 [
192 'slug' => 'scheduled_payments',
193 'name' => __('Scheduled Payments', 'yatra'),
194 'description' => __('Automatically schedule the remaining booking balance after a partial or deposit payment. Uses your payment gateway (e.g. Stripe) to invoice or charge on the dates you configure.', 'yatra'),
195 'category' => __('Payments', 'yatra'),
196 'docs_url' => 'https://docs.yatra.com/modules/scheduled-payments',
197 'is_premium' => true,
198 'purchase_url' => 'https://wpyatra.com/pricing?module=scheduled-payments',
199 'is_core' => false,
200 'enabled' => false,
201 'tags' => ['payments', 'installments', 'balance', 'stripe', 'automation'],
202 'video_url' => self::DEFAULT_VIDEO_URL,
203 'requires_pro' => true,
204 'settings_page' => 'yatra-settings',
205 ],
206 [
207 'slug' => 'dynamic_pricing',
208 'name' => __('Dynamic Pricing', 'yatra'),
209 'description' => __('Automatically adjust trip prices based on demand, seasonality, early bird discounts, and last-minute deals. Maximize revenue with intelligent pricing rules that respond to booking patterns.', 'yatra'),
210 'category' => __('Sales', 'yatra'),
211 'docs_url' => 'https://docs.yatra.com/modules/dynamic-pricing',
212 'is_premium' => true,
213 'purchase_url' => 'https://wpyatra.com/pricing?module=dynamic-pricing',
214 'is_core' => false,
215 'enabled' => false,
216 'tags' => ['pricing', 'revenue', 'automation', 'discounts', 'sales'],
217 'video_url' => self::DEFAULT_VIDEO_URL,
218 'requires_pro' => true,
219 'settings_page' => 'dynamic-pricing',
220 ],
221 [
222 'slug' => 'abandoned_booking_recovery',
223 'name' => __('Abandoned Booking Recovery', 'yatra'),
224 'description' => __('Recover lost sales by automatically tracking abandoned bookings and sending targeted email sequences. Win back customers who left before completing their purchase.', 'yatra'),
225 'category' => __('Marketing', 'yatra'),
226 'docs_url' => 'https://docs.yatra.com/modules/abandoned-booking-recovery',
227 'is_premium' => true,
228 'purchase_url' => 'https://wpyatra.com/pricing?module=abandoned-booking-recovery',
229 'is_core' => false,
230 'enabled' => false,
231 'tags' => ['recovery', 'email', 'automation', 'marketing', 'conversion'],
232 'video_url' => self::DEFAULT_VIDEO_URL,
233 'requires_pro' => true,
234 'settings_page' => 'abandoned-recovery',
235 ],
236 ];
237
238 return apply_filters('yatra_default_modules', $modules);
239 }
240
241 /**
242 * Get modules merged with stored option state
243 */
244 public static function getModules(): array
245 {
246 // Get enable/disable status ONLY from database
247 $stored_status = get_option(self::OPTION_KEY, []);
248 $stored_status = is_array($stored_status) ? $stored_status : [];
249
250 // Get module definitions ONLY from hardcoded array
251 $modules = self::getDefaultModules();
252
253 $result = [];
254 foreach ($modules as $module) {
255 $slug = $module['slug'];
256
257 // Get enable/disable status from database only
258 $enabled = isset($stored_status[$slug]['enabled'])
259 ? (bool) $stored_status[$slug]['enabled']
260 : (bool) ($module['enabled'] ?? false);
261
262 // Check if module is available (can be enabled)
263 $is_available = true;
264 if (!empty($module['requires_pro'])) {
265 $pro_active = apply_filters('yatra_is_pro_active', false);
266 if ($pro_active) {
267 // Check if this module is available in Pro
268 $available_modules = apply_filters('yatra_pro_available_modules', []);
269 $is_available = in_array($slug, $available_modules, true);
270 } else {
271 $is_available = false;
272 }
273 }
274
275 $result[] = array_merge($module, [
276 'enabled' => $enabled,
277 'updated_at' => $stored_status[$slug]['updated_at'] ?? null,
278 'is_available' => $is_available,
279 ]);
280 }
281
282 return $result;
283 }
284
285 /**
286 * Check if module is enabled
287 */
288 public static function isModuleEnabled(string $slug): bool
289 {
290 // Allow direct override for specific modules
291 $override = apply_filters('yatra_module_enabled_status', null, $slug);
292 if ($override !== null) {
293 return (bool) $override;
294 }
295
296 $modules = self::getModules();
297 foreach ($modules as $module) {
298 if ($module['slug'] === $slug) {
299 // Check if module requires Pro and if Pro is active
300 if (!empty($module['requires_pro'])) {
301 $pro_active = apply_filters('yatra_is_pro_active', false);
302 if (!$pro_active) {
303 return false;
304 }
305 }
306
307 return (bool) $module['enabled'];
308 }
309 }
310
311 return false;
312 }
313
314 /**
315 * Check if module is available (can be enabled)
316 */
317 public static function isModuleAvailable(string $slug): bool
318 {
319 // Allow direct override for specific modules
320 $override = apply_filters('yatra_module_is_available_' . $slug, null);
321 if ($override !== null) {
322 return (bool) $override;
323 }
324
325 $modules = self::getModules();
326 foreach ($modules as $module) {
327 if ($module['slug'] === $slug) {
328 // If module requires Pro, check if Pro is active
329 if (!empty($module['requires_pro'])) {
330 // Check if Pro is active
331 $pro_active = apply_filters('yatra_is_pro_active', false);
332 if (!$pro_active) {
333 return false;
334 }
335
336 // Check if this module is available in Pro
337 $available_modules = apply_filters('yatra_pro_available_modules', []);
338 return in_array($slug, $available_modules, true);
339 }
340
341 return true;
342 }
343 }
344
345 return false;
346 }
347
348 /**
349 * Update module enabled state
350 */
351 public static function setModuleStatus(string $slug, bool $enabled): array
352 {
353 $modules = get_option(self::OPTION_KEY, []);
354 $modules = is_array($modules) ? $modules : [];
355
356 $modules[$slug] = array_merge($modules[$slug] ?? [], [
357 'enabled' => $enabled,
358 'updated_at' => current_time('mysql'),
359 ]);
360
361 update_option(self::OPTION_KEY, $modules);
362
363 // Trigger module activation/deactivation hook
364 if ($enabled) {
365 do_action('yatra_module_active', $slug);
366 } else {
367 do_action('yatra_module_deactive', $slug);
368 }
369
370 return self::getModules();
371 }
372
373 /**
374 * Update multiple modules at once
375 *
376 * @param array<array{slug:string, enabled:bool}> $items
377 */
378 public static function setMultipleStatuses(array $items): array
379 {
380 if (empty($items)) {
381 return self::getModules();
382 }
383
384 $modules = get_option(self::OPTION_KEY, []);
385 $modules = is_array($modules) ? $modules : [];
386 $timestamp = current_time('mysql');
387
388 foreach ($items as $item) {
389 if (empty($item['slug'])) {
390 continue;
391 }
392
393 $slug = sanitize_key($item['slug']);
394 $enabled = (bool) ($item['enabled'] ?? false);
395
396 $modules[$slug] = array_merge($modules[$slug] ?? [], [
397 'enabled' => $enabled,
398 'updated_at' => $timestamp,
399 ]);
400 }
401
402 update_option(self::OPTION_KEY, $modules);
403
404 // Trigger module activation/deactivation hooks for bulk updates
405 foreach ($items as $item) {
406 if (empty($item['slug'])) {
407 continue;
408 }
409
410 $slug = sanitize_key($item['slug']);
411 $enabled = (bool) ($item['enabled'] ?? false);
412
413 if ($enabled) {
414 do_action('yatra_module_active', $slug);
415 } else {
416 do_action('yatra_module_deactive', $slug);
417 }
418 }
419
420 return self::getModules();
421 }
422 }
423