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
← All changes | app/Core/Modules/ModuleManager.php +195 -19 3.0.2.6trunk View file →
@@ -10,9 +10,9 @@
10 10 */
11 11 class ModuleManager
12 12 {
13 13 private const OPTION_KEY = 'yatra_modules';
14 - private const DEFAULT_VIDEO_URL = 'https://www.youtube.com/embed/2g811Eo7K8U';
14 + private const DEFAULT_VIDEO_URL = 'https://youtu.be/cHmC-x7y0TQ';
15 15
16 16 /**
17 17 * Ensure option exists with defaults
18 18 */
@@ -43,9 +43,9 @@
43 43 'slug' => 'google_calendar',
44 44 'name' => __('Google Calendar Integration', 'yatra'),
45 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 46 'category' => __('Integrations', 'yatra'),
47 - 'docs_url' => 'https://docs.yatra.com/modules/google-calendar',
47 + 'docs_url' => 'https://docs.wpyatra.com/modules/google-calendar',
48 48 'is_premium' => true,
49 49 'purchase_url' => 'https://wpyatra.com/pricing?module=google-calendar',
50 50 'is_core' => false,
51 51 'enabled' => false,
@@ -58,9 +58,9 @@
58 58 'slug' => 'additional_services',
59 59 'name' => __('Additional Services', 'yatra'),
60 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 61 'category' => __('Sales', 'yatra'),
62 - 'docs_url' => 'https://docs.yatra.com/modules/additional-services',
62 + 'docs_url' => 'https://docs.wpyatra.com/modules/additional-services',
63 63 'is_premium' => true,
64 64 'purchase_url' => 'https://wpyatra.com/pricing?module=additional-services',
65 65 'is_core' => false,
66 66 'enabled' => false,
@@ -73,9 +73,9 @@
73 73 'slug' => 'trip_consent',
74 74 'name' => __('Trip Consent', 'yatra'),
75 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 76 'category' => __('Operations', 'yatra'),
77 - 'docs_url' => 'https://docs.yatra.com/modules/trip-consent',
77 + 'docs_url' => 'https://docs.wpyatra.com/modules/trip-consent',
78 78 'is_premium' => true,
79 79 'purchase_url' => 'https://wpyatra.com/pricing?module=trip-consent',
80 80 'is_core' => false,
81 81 'enabled' => false,
@@ -88,9 +88,9 @@
88 88 'slug' => 'email_automation',
89 89 'name' => __('Email Automation', 'yatra'),
90 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 91 'category' => __('Marketing', 'yatra'),
92 - 'docs_url' => 'https://docs.yatra.com/modules/email-automation',
92 + 'docs_url' => 'https://docs.wpyatra.com/modules/email-automation',
93 93 'is_premium' => true,
94 94 'purchase_url' => 'https://wpyatra.com/pricing?module=email-automation',
95 95 'is_core' => false,
96 96 'enabled' => false,
@@ -103,9 +103,9 @@
103 103 'slug' => 'dynamic_form_field',
104 104 'name' => __('Dynamic Form Field', 'yatra'),
105 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 106 'category' => __('Bookings', 'yatra'),
107 - 'docs_url' => 'https://docs.yatra.com/modules/dynamic-form-field',
107 + 'docs_url' => 'https://docs.wpyatra.com/modules/dynamic-form-field',
108 108 'is_premium' => true,
109 109 'purchase_url' => 'https://wpyatra.com/pricing?module=dynamic-form-field',
110 110 'is_core' => false,
111 111 'enabled' => false,
@@ -118,9 +118,9 @@
118 118 'slug' => 'advanced_discount',
119 119 'name' => __('Advanced Discount', 'yatra'),
120 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 121 'category' => __('Marketing', 'yatra'),
122 - 'docs_url' => 'https://docs.yatra.com/modules/advanced-discount',
122 + 'docs_url' => 'https://docs.wpyatra.com/modules/advanced-discount',
123 123 'is_premium' => true,
124 124 'purchase_url' => 'https://wpyatra.com/pricing?module=advanced-discount',
125 125 'is_core' => false,
126 126 'enabled' => false,
@@ -132,9 +132,9 @@
132 132 'slug' => 'mailchimp',
133 133 'name' => __('Mailchimp Integration', 'yatra'),
134 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 135 'category' => __('Marketing', 'yatra'),
136 - 'docs_url' => 'https://docs.yatra.com/modules/mailchimp',
136 + 'docs_url' => 'https://docs.wpyatra.com/modules/mailchimp',
137 137 'is_premium' => true,
138 138 'purchase_url' => 'https://wpyatra.com/pricing?module=mailchimp',
139 139 'is_core' => false,
140 140 'enabled' => false,
@@ -147,9 +147,9 @@
147 147 'slug' => 'facebook_pixel',
148 148 'name' => __('Facebook Pixel', 'yatra'),
149 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 150 'category' => __('Marketing', 'yatra'),
151 - 'docs_url' => 'https://docs.yatra.com/modules/facebook-pixel',
151 + 'docs_url' => 'https://docs.wpyatra.com/modules/facebook-pixel',
152 152 'is_premium' => true,
153 153 'purchase_url' => 'https://wpyatra.com/pricing?module=facebook-pixel',
154 154 'is_core' => false,
155 155 'enabled' => false,
@@ -162,9 +162,9 @@
162 162 'slug' => 'google_analytics',
163 163 'name' => __('Google Analytics 4 Enhanced', 'yatra'),
164 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 165 'category' => __('Marketing', 'yatra'),
166 - 'docs_url' => 'https://docs.yatra.com/modules/google-analytics',
166 + 'docs_url' => 'https://docs.wpyatra.com/modules/google-analytics',
167 167 'is_premium' => true,
168 168 'purchase_url' => 'https://wpyatra.com/pricing?module=google-analytics',
169 169 'is_core' => false,
170 170 'enabled' => false,
@@ -177,9 +177,9 @@
177 177 'slug' => 'flexible_payments',
178 178 'name' => __('Flexible Payments', 'yatra'),
179 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 180 'category' => __('Payments', 'yatra'),
181 - 'docs_url' => 'https://docs.yatra.com/modules/flexible-payments',
181 + 'docs_url' => 'https://docs.wpyatra.com/modules/flexible-payments',
182 182 'is_premium' => true,
183 183 'purchase_url' => 'https://wpyatra.com/pricing?module=flexible-payments',
184 184 'is_core' => false,
185 185 'enabled' => false,
@@ -188,13 +188,28 @@
188 188 'requires_pro' => true,
189 189 'settings_page' => 'yatra-settings',
190 190 ],
191 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.wpyatra.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 + [
192 207 'slug' => 'dynamic_pricing',
193 208 'name' => __('Dynamic Pricing', 'yatra'),
194 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'),
195 210 'category' => __('Sales', 'yatra'),
196 - 'docs_url' => 'https://docs.yatra.com/modules/dynamic-pricing',
211 + 'docs_url' => 'https://docs.wpyatra.com/modules/dynamic-pricing',
197 212 'is_premium' => true,
198 213 'purchase_url' => 'https://wpyatra.com/pricing?module=dynamic-pricing',
199 214 'is_core' => false,
200 215 'enabled' => false,
@@ -203,13 +218,28 @@
203 218 'requires_pro' => true,
204 219 'settings_page' => 'dynamic-pricing',
205 220 ],
206 221 [
222 + 'slug' => 'custom_landing_pages',
223 + 'name' => __('Custom Landing Pages', 'yatra'),
224 + 'description' => __('Point destinations, activities, and trip types to any WordPress page. Use your page builder and Yatra shortcodes on that page; catalog links and redirects use the page URL when the module is enabled.', 'yatra'),
225 + 'category' => __('Marketing', 'yatra'),
226 + 'docs_url' => 'https://docs.wpyatra.com/modules/custom-landing-pages',
227 + 'is_premium' => true,
228 + 'purchase_url' => 'https://wpyatra.com/pricing?module=custom-landing-pages',
229 + 'is_core' => false,
230 + 'enabled' => false,
231 + 'tags' => ['seo', 'landing', 'page-builder', 'destinations', 'taxonomy'],
232 + 'video_url' => self::DEFAULT_VIDEO_URL,
233 + 'requires_pro' => true,
234 + 'settings_page' => 'yatra-settings',
235 + ],
236 + [
207 237 'slug' => 'abandoned_booking_recovery',
208 238 'name' => __('Abandoned Booking Recovery', 'yatra'),
209 239 'description' => __('Recover lost sales by automatically tracking abandoned bookings and sending targeted email sequences. Win back customers who left before completing their purchase.', 'yatra'),
210 240 'category' => __('Marketing', 'yatra'),
211 - 'docs_url' => 'https://docs.yatra.com/modules/abandoned-booking-recovery',
241 + 'docs_url' => 'https://docs.wpyatra.com/modules/abandoned-booking-recovery',
212 242 'is_premium' => true,
213 243 'purchase_url' => 'https://wpyatra.com/pricing?module=abandoned-booking-recovery',
214 244 'is_core' => false,
215 245 'enabled' => false,
@@ -217,8 +247,104 @@
217 247 'video_url' => self::DEFAULT_VIDEO_URL,
218 248 'requires_pro' => true,
219 249 'settings_page' => 'abandoned-recovery',
220 250 ],
251 + [
252 + 'slug' => 'white_label',
253 + 'name' => __('White Label', 'yatra'),
254 + 'description' => __('Fully rebrand Yatra as your own product. Replace the plugin name, logo, author, support URL, and email/PDF branding shown to clients. Available exclusively on the Scale plan.', 'yatra'),
255 + 'category' => __('Branding', 'yatra'),
256 + 'docs_url' => 'https://docs.wpyatra.com/modules/white-label',
257 + 'is_premium' => true,
258 + 'purchase_url' => 'https://wpyatra.com/pricing?module=white-label',
259 + 'is_core' => false,
260 + 'enabled' => false,
261 + 'tags' => ['branding', 'agency', 'whitelabel', 'rebrand'],
262 + 'video_url' => self::DEFAULT_VIDEO_URL,
263 + 'requires_pro' => true,
264 + 'requires_agency' => true,
265 + 'settings_page' => 'white-label',
266 + ],
267 + [
268 + 'slug' => 'ai_assistant',
269 + 'name' => __('AI Assistant', 'yatra'),
270 + 'description' => __('Generate trip descriptions, itineraries, SEO meta, and email copy without leaving the editor. Inline AI affordances on every long-text field — write less, finish more. Bring your own OpenAI or Anthropic key.', 'yatra'),
271 + 'category' => __('Productivity', 'yatra'),
272 + 'docs_url' => 'https://docs.wpyatra.com/modules/ai-assistant',
273 + 'is_premium' => true,
274 + 'purchase_url' => 'https://wpyatra.com/pricing?module=ai-assistant',
275 + 'is_core' => false,
276 + 'enabled' => false,
277 + 'tags' => ['ai', 'assistant', 'content', 'seo', 'productivity'],
278 + 'video_url' => self::DEFAULT_VIDEO_URL,
279 + 'requires_pro' => true,
280 + 'requires_growth_or_agency' => true,
281 + 'settings_page' => 'ai-assistant',
282 + ],
283 + [
284 + 'slug' => 'whatsapp',
285 + 'name' => __('WhatsApp Notifications', 'yatra'),
286 + 'description' => __('Send booking confirmations, payment alerts, departure reminders, and review requests over WhatsApp — the channel customers actually read. Inbound messages route into your Yatra Enquiries inbox. Bring your own WhatsApp Business / Cloud API credentials; messages are billed by Meta, not by the plugin.', 'yatra'),
287 + 'category' => __('Communications', 'yatra'),
288 + 'docs_url' => 'https://docs.wpyatra.com/modules/whatsapp',
289 + 'is_premium' => true,
290 + 'purchase_url' => 'https://wpyatra.com/pricing?module=whatsapp',
291 + 'is_core' => false,
292 + 'enabled' => false,
293 + 'tags' => ['whatsapp', 'notifications', 'messaging', 'communications', 'reminders'],
294 + 'video_url' => self::DEFAULT_VIDEO_URL,
295 + 'requires_pro' => true,
296 + 'requires_growth_or_agency' => true,
297 + 'settings_page' => 'whatsapp',
298 + ],
299 + [
300 + 'slug' => 'channel_manager',
301 + 'name' => __('Channel Manager', 'yatra'),
302 + 'description' => __('Sync your trips + departures + inventory to Viator, GetYourGuide, Klook, and TripAdvisor Experiences. Pull bookings back into Yatra as native bookings. Real-time inventory sync prevents oversells across channels. Per-channel pricing offsets cover OTA commission. The single biggest revenue lever for tour operators on multiple platforms.', 'yatra'),
303 + 'category' => __('Distribution', 'yatra'),
304 + 'docs_url' => 'https://docs.wpyatra.com/modules/channel-manager',
305 + 'is_premium' => true,
306 + 'purchase_url' => 'https://wpyatra.com/pricing?module=channel-manager',
307 + 'is_core' => false,
308 + 'enabled' => false,
309 + 'tags' => ['ota', 'channel', 'viator', 'getyourguide', 'distribution', 'agency'],
310 + 'video_url' => self::DEFAULT_VIDEO_URL,
311 + 'requires_pro' => true,
312 + 'requires_agency' => true,
313 + 'settings_page' => 'channel-manager',
314 + ],
315 + [
316 + 'slug' => 'webhooks',
317 + 'name' => __('Webhooks', 'yatra'),
318 + 'description' => __('Push every Yatra event (booking, payment, refund, customer, enquiry, trip, departure) to your CRM, accounting tool, Zapier, Make, Slack, or any HTTPS endpoint. HMAC-SHA256 signed payloads, automatic retry with exponential backoff, full delivery log with payload inspection + replay, per-endpoint encrypted secrets. The integration backbone for agencies wiring Yatra into a custom tech stack.', 'yatra'),
319 + 'category' => __('Integrations', 'yatra'),
320 + 'docs_url' => 'https://docs.wpyatra.com/modules/webhooks',
321 + 'is_premium' => true,
322 + 'purchase_url' => 'https://wpyatra.com/pricing?module=webhooks',
323 + 'is_core' => false,
324 + 'enabled' => false,
325 + 'tags' => ['webhook', 'integration', 'zapier', 'crm', 'api', 'agency', 'automation'],
326 + 'video_url' => self::DEFAULT_VIDEO_URL,
327 + 'requires_pro' => true,
328 + 'requires_agency' => true,
329 + 'settings_page' => 'webhooks',
330 + ],
331 + [
332 + 'slug' => 'team',
333 + 'name' => __('Team & Access', 'yatra'),
334 + 'description' => __('Granular roles + capability-based access control for multi-staff agencies. Eight shipped roles (Owner, Manager, Sales Agent, Front Desk, Guide, Accountant, Marketing, Auditor) plus custom role builder. Per-user capability grants/revokes, row-level scope assignment (destination / activity / trip), magic-link invitations, append-only audit log with 180-day retention, and 2FA enforcement per role. Defense-in-depth: every REST route enforces capabilities server-side; the React UI mirrors via <Can/> for UX only.', 'yatra'),
335 + 'category' => __('Team', 'yatra'),
336 + 'docs_url' => 'https://docs.wpyatra.com/modules/team-access',
337 + 'is_premium' => true,
338 + 'purchase_url' => 'https://wpyatra.com/pricing?module=team',
339 + 'is_core' => false,
340 + 'enabled' => false,
341 + 'tags' => ['team', 'access', 'roles', 'permissions', 'rbac', 'audit-log', 'agency', 'sso', 'invitations'],
342 + 'video_url' => self::DEFAULT_VIDEO_URL,
343 + 'requires_pro' => true,
344 + 'requires_agency' => true,
345 + 'settings_page' => 'team',
346 + ],
221 347 ];
222 348
223 349 return apply_filters('yatra_default_modules', $modules);
224 350 }
@@ -256,12 +382,37 @@
256 382 $is_available = false;
257 383 }
258 384 }
259 385
386 + // Agency-tier-only modules require both Pro AND an Agency license.
387 + if ($is_available && !empty($module['requires_agency'])) {
388 + $is_available = (bool) apply_filters('yatra_is_agency_active', false);
389 + }
390 +
391 + // Growth-or-Agency tier modules (e.g. AI Assistant) — require Pro
392 + // AND a license tier at or above Growth.
393 + if ($is_available && !empty($module['requires_growth_or_agency'])) {
394 + $is_available = (bool) apply_filters('yatra_is_ai_eligible', false);
395 + }
396 +
397 + // Plan badge: 'agency' for Agency-only, 'growth' for the
398 + // Growth-or-Agency band, 'personal' for any other Pro module,
399 + // 'free' for core. Surfaced on the Modules page.
400 + if (!empty($module['requires_agency'])) {
401 + $plan = 'agency';
402 + } elseif (!empty($module['requires_growth_or_agency'])) {
403 + $plan = 'growth';
404 + } elseif (!empty($module['requires_pro'])) {
405 + $plan = 'personal';
406 + } else {
407 + $plan = 'free';
408 + }
409 +
260 410 $result[] = array_merge($module, [
261 411 'enabled' => $enabled,
262 412 'updated_at' => $stored_status[$slug]['updated_at'] ?? null,
263 413 'is_available' => $is_available,
414 + 'plan' => $plan,
264 415 ]);
265 416 }
266 417
267 418 return $result;
@@ -287,9 +438,24 @@
287 438 if (!$pro_active) {
288 439 return false;
289 440 }
290 441 }
291 -
442 +
443 + // Agency-tier-only modules also need an Agency license — a
444 + // toggle stuck "on" must not keep working after a downgrade.
445 + if (!empty($module['requires_agency'])) {
446 + if (!apply_filters('yatra_is_agency_active', false)) {
447 + return false;
448 + }
449 + }
450 +
451 + // Growth-or-Agency modules need at least a Growth license.
452 + if (!empty($module['requires_growth_or_agency'])) {
453 + if (!apply_filters('yatra_is_ai_eligible', false)) {
454 + return false;
455 + }
456 + }
457 +
292 458 return (bool) $module['enabled'];
293 459 }
294 460 }
295 461
@@ -294,9 +460,9 @@
294 460 }
295 461
296 462 return false;
297 463 }
298 -
464 +
299 465 /**
300 466 * Check if module is available (can be enabled)
301 467 */
302 468 public static function isModuleAvailable(string $slug): bool
@@ -305,9 +471,9 @@
305 471 $override = apply_filters('yatra_module_is_available_' . $slug, null);
306 472 if ($override !== null) {
307 473 return (bool) $override;
308 474 }
309 -
475 +
310 476 $modules = self::getModules();
311 477 foreach ($modules as $module) {
312 478 if ($module['slug'] === $slug) {
313 479 // If module requires Pro, check if Pro is active
@@ -316,14 +482,24 @@
316 482 $pro_active = apply_filters('yatra_is_pro_active', false);
317 483 if (!$pro_active) {
318 484 return false;
319 485 }
320 -
486 +
321 487 // Check if this module is available in Pro
322 488 $available_modules = apply_filters('yatra_pro_available_modules', []);
323 - return in_array($slug, $available_modules, true);
489 + if (!in_array($slug, $available_modules, true)) {
490 + return false;
491 + }
324 492 }
325 -
493 +
494 + if (!empty($module['requires_agency'])) {
495 + return (bool) apply_filters('yatra_is_agency_active', false);
496 + }
497 +
498 + if (!empty($module['requires_growth_or_agency'])) {
499 + return (bool) apply_filters('yatra_is_ai_eligible', false);
500 + }
501 +
326 502 return true;
327 503 }
328 504 }
329 505