PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.2.6
Yatra – Travel Booking & Tour Operator Software v3.0.2.6
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
yatra / app / Services / EmailTemplateDefaults.php

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

829 lines 38.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 /**
8 * Default subject + HTML for transactional settings (free) and Pro automation seed/backfill.
9 * Uses {{merge_tags}} compatible with TransactionalEmailTemplateService and Pro EmailAutomationService.
10 */
11 final class EmailTemplateDefaults
12 {
13 /**
14 * Option keys (without yatra_ prefix) for SettingsController / InstallerService.
15 *
16 * @return array<string, string>
17 */
18 public static function settingsOptionDefaults(): array
19 {
20 return [
21 'email_tpl_booking_subject' => '✈️ [{{site_name}}] Booking update · {{booking_reference}}',
22 'email_tpl_booking_body' => self::htmlBookingCustomer(),
23 'email_tpl_payment_subject' => '�
24 [{{site_name}}] Payment received · {{booking_reference}}',
25 'email_tpl_payment_body' => self::htmlPaymentCustomer(),
26 'email_tpl_cancellation_subject' => '📋 [{{site_name}}] Booking cancelled · {{booking_reference}}',
27 'email_tpl_cancellation_body' => self::htmlCancellationCustomer(),
28 'email_tpl_reminder_subject' => '🗓️ [{{site_name}}] Your trip is coming up · {{booking_reference}}',
29 'email_tpl_reminder_body' => self::htmlReminderCustomer(),
30 'email_tpl_admin_booking_subject' => '🔔 [{{site_name}}] New booking · {{booking_reference}} (#{{booking_id}})',
31 'email_tpl_admin_booking_body' => self::htmlAdminNewBooking(),
32 'email_tpl_admin_payment_subject' => '�
33 [{{site_name}}] Payment received · {{booking_reference}} (#{{booking_id}})',
34 'email_tpl_admin_payment_body' => self::htmlAdminPaymentReceived(),
35 'email_tpl_admin_cancellation_subject' => '📋 [{{site_name}}] Booking cancelled · {{booking_reference}} (#{{booking_id}})',
36 'email_tpl_admin_cancellation_body' => self::htmlAdminBookingCancelled(),
37 ];
38 }
39
40 /**
41 * Full subject + body for Pro system templates (DB). Null = no bundled default for that key.
42 *
43 * @return array{subject: string, body: string}|null
44 */
45 public static function proSystemTemplate(string $templateKey): ?array
46 {
47 $map = [
48 'new_booking' => [
49 'subject' => '✈️ Booking confirmation · {{booking_reference}}',
50 'body' => self::htmlBookingCustomer(),
51 ],
52 'booking_payment' => [
53 'subject' => '�
54 Payment received · {{booking_reference}}',
55 'body' => self::htmlPaymentCustomer(),
56 ],
57 'booking_confirmation' => [
58 'subject' => '✈️ Your booking · {{booking_reference}}',
59 'body' => self::htmlBookingCustomer(),
60 ],
61 'booking_confirmed' => [
62 'subject' => '🎉 You\'re confirmed · {{booking_reference}}',
63 'body' => self::htmlBookingConfirmed(),
64 ],
65 'admin_new_booking' => [
66 'subject' => '🔔 New booking · {{booking_reference}} (#{{booking_id}})',
67 'body' => self::htmlAdminNewBooking(),
68 ],
69 'booking_cancelled' => [
70 'subject' => '📋 Booking cancelled · {{booking_reference}}',
71 'body' => self::htmlCancellationCustomer(),
72 ],
73 'booking_completed' => [
74 'subject' => '🌟 Thanks for traveling with us · {{booking_reference}}',
75 'body' => self::htmlTripCompleted(),
76 ],
77 'payment_received' => [
78 'subject' => '�
79 Payment received · {{booking_reference}}',
80 'body' => self::htmlPaymentCustomer(),
81 ],
82 'payment_reminder' => [
83 'subject' => '💳 Payment reminder · {{booking_reference}}',
84 'body' => self::htmlPaymentReminder(),
85 ],
86 'enquiry_received' => [
87 'subject' => '✉️ We received your message',
88 'body' => self::htmlEnquiryCustomer(),
89 ],
90 'enquiry_admin' => [
91 'subject' => '💬 New enquiry · {{customer_name}}',
92 'body' => self::htmlEnquiryAdmin(),
93 ],
94 'enquiry_response' => [
95 'subject' => '💬 Re: your enquiry',
96 'body' => self::htmlEnquiryResponse(),
97 ],
98 'trip_reminder' => [
99 'subject' => '🗓️ Reminder · {{trip_name}}',
100 'body' => self::htmlReminderCustomer(),
101 ],
102 'review_request' => [
103 'subject' => '⭐ How was {{trip_name}}?',
104 'body' => self::htmlReviewRequest(),
105 ],
106 ];
107
108 return $map[$templateKey] ?? null;
109 }
110
111 /**
112 * Fallback HTML when settings templates are empty (escaped runtime variables).
113 *
114 * @param array<string, string> $v
115 */
116 public static function fallbackTransactionalBooking(array $v): string
117 {
118 $name = esc_html($v['customer_first_name'] ?: $v['customer_name'] ?: __('there', 'yatra'));
119 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
120
121 if (!empty($v['details_html_only'])) {
122 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
123 . sprintf(
124 /* translators: %s: customer name */
125 esc_html__('Hello %s,', 'yatra'),
126 $name
127 )
128 . '</p>'
129 . '<p style="margin:0 0 20px;color:#475569;">'
130 . esc_html($v['intro_paragraph'] ?? __('Thank you for your booking. Here are your details:', 'yatra'))
131 . '</p>'
132 . wp_kses_post((string) ($v['details_html'] ?? ''))
133 . (!empty($v['footer_note']) ? '<p style="margin:24px 0 0;color:#475569;">' . wp_kses_post((string) $v['footer_note']) . '</p>' : '');
134
135 return EmailTemplateLayout::customer(
136 '✈️',
137 __('Booking update', 'yatra'),
138 $inner,
139 $site,
140 __('Your booking details are inside.', 'yatra')
141 );
142 }
143
144 $rows = array_values(array_filter([
145 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
146 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
147 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
148 ['label' => __('Travelers', 'yatra'), 'value' => esc_html($v['travelers_count'] ?? '')],
149 ['label' => __('Total', 'yatra'), 'value' => esc_html($v['total_amount_formatted'] ?? '')],
150 ['label' => __('Amount due now', 'yatra'), 'value' => esc_html($v['amount_due_formatted'] ?? '')],
151 ], static function (array $row): bool {
152 return $row['value'] !== '';
153 }));
154
155 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
156 . sprintf(
157 esc_html__('Hello %s,', 'yatra'),
158 $name
159 )
160 . '</p>'
161 . '<p style="margin:0 0 8px;color:#475569;">'
162 . esc_html($v['intro_paragraph'] ?? __('Thank you for your booking. Here are your details:', 'yatra'))
163 . '</p>'
164 . EmailTemplateLayout::detailCard($rows)
165 . (!empty($v['details_html']) ? '<div style="margin:16px 0 0;">' . wp_kses_post((string) $v['details_html']) . '</div>' : '')
166 . (!empty($v['footer_note']) ? '<p style="margin:24px 0 0;color:#475569;">' . wp_kses_post((string) $v['footer_note']) . '</p>' : '');
167
168 return EmailTemplateLayout::customer(
169 '✈️',
170 __('Booking update', 'yatra'),
171 $inner,
172 $site,
173 __('Your booking details are inside.', 'yatra')
174 );
175 }
176
177 /**
178 * @param array<string, string> $v
179 */
180 public static function fallbackTransactionalPayment(array $v): string
181 {
182 $name = esc_html($v['customer_first_name'] ?: $v['customer_name'] ?: __('Customer', 'yatra'));
183 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
184 $rows = array_values(array_filter([
185 ['label' => __('Booking reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
186 ['label' => __('Amount paid', 'yatra'), 'value' => esc_html($v['payment_amount_formatted'] ?? '')],
187 ['label' => __('Method', 'yatra'), 'value' => esc_html($v['payment_method'] ?? '')],
188 ['label' => __('Transaction ID', 'yatra'), 'value' => esc_html($v['transaction_id'] ?? '')],
189 ], static function (array $row): bool {
190 return $row['value'] !== '';
191 }));
192
193 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
194 . sprintf(esc_html__('Dear %s,', 'yatra'), $name)
195 . '</p>'
196 . '<p style="margin:0 0 8px;color:#475569;">'
197 . esc_html__('We’ve received your payment — thank you! Here’s a quick summary.', 'yatra')
198 . '</p>'
199 . EmailTemplateLayout::detailCard($rows);
200
201 return EmailTemplateLayout::customer(
202 '�
203 ',
204 __('Payment received', 'yatra'),
205 $inner,
206 $site,
207 __('Payment confirmation', 'yatra')
208 );
209 }
210
211 /**
212 * @param array<string, string> $v
213 */
214 public static function fallbackTransactionalCancellation(array $v): string
215 {
216 $name = esc_html($v['customer_first_name'] ?: $v['customer_name'] ?: __('Customer', 'yatra'));
217 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
218 $rows = array_values(array_filter([
219 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
220 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
221 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
222 ], static function (array $row): bool {
223 return $row['value'] !== '';
224 }));
225
226 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
227 . sprintf(esc_html__('Hello %s,', 'yatra'), $name)
228 . '</p>'
229 . '<p style="margin:0 0 20px;color:#475569;">'
230 . esc_html__('Your booking has been cancelled as requested. If you have questions, just reply to this email.', 'yatra')
231 . '</p>'
232 . EmailTemplateLayout::detailCard($rows);
233
234 return EmailTemplateLayout::customer(
235 '📋',
236 __('Booking cancelled', 'yatra'),
237 $inner,
238 $site,
239 __('Booking cancellation notice', 'yatra')
240 );
241 }
242
243 /**
244 * @param array<string, string> $v
245 */
246 public static function fallbackTransactionalReminder(array $v): string
247 {
248 $name = esc_html($v['customer_name'] ?: __('Traveler', 'yatra'));
249 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
250 $days = esc_html((string) ($v['reminder_days'] ?? $v['days_until_trip'] ?? ''));
251
252 $rows = array_values(array_filter([
253 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
254 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
255 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
256 ['label' => __('Travelers', 'yatra'), 'value' => esc_html($v['travelers_count'] ?? '')],
257 ], static function (array $row): bool {
258 return $row['value'] !== '';
259 }));
260
261 $balanceRow = (!empty($v['amount_due_formatted']) && isset($v['amount_due_formatted']) && $v['amount_due_formatted'] !== yatra_format_price(0))
262 ? [['label' => __('Balance due', 'yatra'), 'value' => esc_html((string) $v['amount_due_formatted'])]]
263 : [];
264 if ($balanceRow !== []) {
265 $rows = array_merge($rows, $balanceRow);
266 }
267
268 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
269 . sprintf(esc_html__('Dear %s,', 'yatra'), $name)
270 . '</p>'
271 . '<p style="margin:0 0 20px;color:#475569;">'
272 . ($days !== ''
273 ? sprintf(
274 /* translators: %s: number of days */
275 esc_html__('Your adventure starts in %s days — we can’t wait to see you!', 'yatra'),
276 $days
277 )
278 : esc_html__('Your trip is coming up soon — we look forward to seeing you!', 'yatra'))
279 . '</p>'
280 . EmailTemplateLayout::detailCard($rows)
281 . (!empty($v['reminder_extra_html']) ? '<div style="margin:20px 0 0;">' . wp_kses_post($v['reminder_extra_html']) . '</div>' : '');
282
283 return EmailTemplateLayout::customer(
284 '🗓️',
285 __('Trip reminder', 'yatra'),
286 $inner,
287 $site,
288 __('Upcoming trip reminder', 'yatra')
289 );
290 }
291
292 /**
293 * Fallback HTML for admin new-booking notice (empty saved template).
294 *
295 * @param array<string, string> $v
296 */
297 /**
298 * Fallback HTML for admin payment-received notice.
299 *
300 * @param array<string, string> $v
301 */
302 public static function fallbackAdminPaymentReceived(array $v): string
303 {
304 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
305 $rows = array_values(array_filter([
306 ['label' => __('Booking ID', 'yatra'), 'value' => esc_html($v['booking_id'] ?? '')],
307 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
308 ['label' => __('Customer', 'yatra'), 'value' => esc_html($v['customer_name'] ?? '')],
309 ['label' => __('Amount', 'yatra'), 'value' => esc_html($v['payment_amount_formatted'] ?? '')],
310 ['label' => __('Method', 'yatra'), 'value' => esc_html($v['payment_method'] ?? '')],
311 ['label' => __('Transaction ID', 'yatra'), 'value' => esc_html($v['transaction_id'] ?? '')],
312 ], static function (array $row): bool {
313 return trim((string) ($row['value'] ?? '')) !== '';
314 }));
315
316 $adminUrl = esc_url($v['admin_url'] ?? admin_url('admin.php?page=yatra'));
317
318 $inner = '<p style="margin:0 0 20px;color:#475569;">'
319 . esc_html__('A payment was recorded for the booking below.', 'yatra')
320 . '</p>'
321 . EmailTemplateLayout::detailCard($rows)
322 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
323 . '<td style="border-radius:10px;background:#2563eb;">'
324 . '<a href="' . $adminUrl . '" style="display:inline-block;padding:14px 24px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
325 . esc_html__('Open in Yatra admin', 'yatra')
326 . '</a></td></tr></table>';
327
328 return EmailTemplateLayout::admin(
329 '�
330 ',
331 __('Payment received', 'yatra'),
332 $inner,
333 $site . ' · ' . esc_html__('Admin notification', 'yatra')
334 );
335 }
336
337 /**
338 * Fallback HTML for admin booking-cancelled notice.
339 *
340 * @param array<string, string> $v
341 */
342 public static function fallbackAdminBookingCancelled(array $v): string
343 {
344 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
345 $rows = array_values(array_filter([
346 ['label' => __('Booking ID', 'yatra'), 'value' => esc_html($v['booking_id'] ?? '')],
347 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
348 ['label' => __('Customer', 'yatra'), 'value' => esc_html($v['customer_name'] ?? '')],
349 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
350 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
351 ], static function (array $row): bool {
352 return trim((string) ($row['value'] ?? '')) !== '';
353 }));
354
355 $adminUrl = esc_url($v['admin_url'] ?? admin_url('admin.php?page=yatra'));
356
357 $inner = '<p style="margin:0 0 20px;color:#475569;">'
358 . esc_html__('A booking was cancelled. Summary below.', 'yatra')
359 . '</p>'
360 . EmailTemplateLayout::detailCard($rows)
361 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
362 . '<td style="border-radius:10px;background:#2563eb;">'
363 . '<a href="' . $adminUrl . '" style="display:inline-block;padding:14px 24px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
364 . esc_html__('Open in Yatra admin', 'yatra')
365 . '</a></td></tr></table>';
366
367 return EmailTemplateLayout::admin(
368 '📋',
369 __('Booking cancelled', 'yatra'),
370 $inner,
371 $site . ' · ' . esc_html__('Admin notification', 'yatra')
372 );
373 }
374
375 public static function fallbackAdminNewBooking(array $v): string
376 {
377 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
378 $rows = array_values(array_filter([
379 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
380 ['label' => __('Booking ID', 'yatra'), 'value' => esc_html($v['booking_id'] ?? '')],
381 ['label' => __('Customer', 'yatra'), 'value' => esc_html($v['customer_name'] ?? '')],
382 ['label' => __('Email', 'yatra'), 'value' => esc_html($v['customer_email'] ?? '')],
383 ['label' => __('Phone', 'yatra'), 'value' => esc_html($v['customer_phone'] ?? '')],
384 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
385 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
386 ['label' => __('Travelers', 'yatra'), 'value' => esc_html($v['travelers_count'] ?? '')],
387 ['label' => __('Total', 'yatra'), 'value' => trim(esc_html($v['total_amount_formatted'] ?? '') . ' ' . esc_html($v['currency'] ?? ''))],
388 ['label' => __('Booking status', 'yatra'), 'value' => esc_html($v['booking_status'] ?? '')],
389 ['label' => __('Payment status', 'yatra'), 'value' => esc_html($v['payment_status'] ?? '')],
390 ], static function (array $row): bool {
391 return trim((string) ($row['value'] ?? '')) !== '';
392 }));
393
394 $adminUrl = esc_url($v['admin_url'] ?? admin_url('admin.php?page=yatra'));
395 $siteUrl = esc_url($v['site_url'] ?? home_url('/'));
396
397 $inner = '<p style="margin:0 0 20px;color:#475569;">'
398 . esc_html__('A new booking just landed. Review the snapshot below and open the admin to take action.', 'yatra')
399 . '</p>'
400 . EmailTemplateLayout::detailCard($rows)
401 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
402 . '<td style="border-radius:10px;background:#2563eb;">'
403 . '<a href="' . $adminUrl . '" style="display:inline-block;padding:14px 24px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
404 . esc_html__('Open in Yatra admin', 'yatra')
405 . '</a></td></tr></table>'
406 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
407 . esc_html__('Site:', 'yatra') . ' <a href="' . $siteUrl . '" style="color:#2563eb;">' . esc_html($siteUrl) . '</a>'
408 . '</p>';
409
410 return EmailTemplateLayout::admin(
411 '🔔',
412 __('New booking', 'yatra'),
413 $inner,
414 $site . ' · ' . esc_html__('Admin notification', 'yatra')
415 );
416 }
417
418 private static function htmlBookingCustomer(): string
419 {
420 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
421 . '<p style="margin:0 0 20px;color:#475569;">{{intro_paragraph}}</p>'
422 . EmailTemplateLayout::detailCard([
423 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
424 ['label' => 'Trip', 'value' => '{{trip_name}}'],
425 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
426 ['label' => 'Travelers', 'value' => '{{travelers_count}}'],
427 ['label' => 'Total', 'value' => '{{total_amount_formatted}}'],
428 ['label' => 'Amount due now', 'value' => '{{amount_due_formatted}}'],
429 ])
430 . '{{details_html}}'
431 . '<p style="margin:24px 0 0;color:#475569;">{{footer_note}}</p>'
432 . '<p style="margin:20px 0 0;"><a href="{{trip_url}}" style="color:#0d9488;font-weight:600;text-decoration:none;">' . esc_html__('View trip details →', 'yatra') . '</a></p>';
433
434 return EmailTemplateLayout::customer(
435 '✈️',
436 'Booking update',
437 $inner,
438 '{{site_name}}',
439 'Booking update'
440 );
441 }
442
443 private static function htmlBookingConfirmed(): string
444 {
445 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
446 . '<p style="margin:0 0 20px;color:#475569;">'
447 . esc_html__('Great news — your booking is confirmed. Save this email for your records.', 'yatra')
448 . '</p>'
449 . EmailTemplateLayout::detailCard([
450 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
451 ['label' => 'Trip', 'value' => '{{trip_name}}'],
452 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
453 ['label' => 'Travelers', 'value' => '{{travelers_count}}'],
454 ['label' => 'Total', 'value' => '{{total_amount_formatted}}'],
455 ])
456 . '<p style="margin:20px 0 0;"><a href="{{trip_url}}" style="color:#0d9488;font-weight:600;text-decoration:none;">' . esc_html__('Trip page →', 'yatra') . '</a></p>';
457
458 return EmailTemplateLayout::customer(
459 '🎉',
460 __("You're all set", 'yatra'),
461 $inner,
462 '{{site_name}}',
463 'Booking confirmed'
464 );
465 }
466
467 private static function htmlAdminPaymentReceived(): string
468 {
469 $inner = '<p style="margin:0 0 20px;color:#475569;">'
470 . esc_html__('A payment was recorded for the booking below.', 'yatra')
471 . '</p>'
472 . EmailTemplateLayout::detailCard([
473 ['label' => 'Booking ID', 'value' => '{{booking_id}}'],
474 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
475 ['label' => 'Customer', 'value' => '{{customer_name}}'],
476 ['label' => 'Amount', 'value' => '{{payment_amount_formatted}}'],
477 ['label' => 'Method', 'value' => '{{payment_method}}'],
478 ['label' => 'Transaction ID', 'value' => '{{transaction_id}}'],
479 ])
480 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
481 . '<td style="border-radius:10px;background:#2563eb;">'
482 . '<a href="{{admin_url}}" style="display:inline-block;padding:14px 24px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
483 . esc_html__('Open in Yatra admin', 'yatra')
484 . '</a></td></tr></table>';
485
486 return EmailTemplateLayout::admin(
487 '�
488 ',
489 'Payment received',
490 $inner,
491 '{{site_name}} · ' . esc_html__('Admin notification', 'yatra')
492 );
493 }
494
495 private static function htmlAdminBookingCancelled(): string
496 {
497 $inner = '<p style="margin:0 0 20px;color:#475569;">'
498 . esc_html__('A booking was cancelled. Summary below.', 'yatra')
499 . '</p>'
500 . EmailTemplateLayout::detailCard([
501 ['label' => 'Booking ID', 'value' => '{{booking_id}}'],
502 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
503 ['label' => 'Customer', 'value' => '{{customer_name}}'],
504 ['label' => 'Trip', 'value' => '{{trip_name}}'],
505 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
506 ])
507 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
508 . '<td style="border-radius:10px;background:#2563eb;">'
509 . '<a href="{{admin_url}}" style="display:inline-block;padding:14px 24px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
510 . esc_html__('Open in Yatra admin', 'yatra')
511 . '</a></td></tr></table>';
512
513 return EmailTemplateLayout::admin(
514 '📋',
515 'Booking cancelled',
516 $inner,
517 '{{site_name}} · ' . esc_html__('Admin notification', 'yatra')
518 );
519 }
520
521 private static function htmlAdminNewBooking(): string
522 {
523 $inner = '<p style="margin:0 0 20px;color:#475569;">'
524 . esc_html__('A new booking just landed. Review the snapshot below and open the admin to take action.', 'yatra')
525 . '</p>'
526 . EmailTemplateLayout::detailCard([
527 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
528 ['label' => 'Booking ID', 'value' => '{{booking_id}}'],
529 ['label' => 'Customer', 'value' => '{{customer_name}}'],
530 ['label' => 'Email', 'value' => '{{customer_email}}'],
531 ['label' => 'Phone', 'value' => '{{customer_phone}}'],
532 ['label' => 'Trip', 'value' => '{{trip_name}}'],
533 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
534 ['label' => 'Travelers', 'value' => '{{travelers_count}}'],
535 ['label' => 'Total', 'value' => '{{total_amount_formatted}} {{currency}}'],
536 ['label' => 'Booking status', 'value' => '{{booking_status}}'],
537 ['label' => 'Payment status', 'value' => '{{payment_status}}'],
538 ])
539 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
540 . '<td style="border-radius:10px;background:#2563eb;">'
541 . '<a href="{{admin_url}}" style="display:inline-block;padding:14px 24px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
542 . esc_html__('Open in Yatra admin', 'yatra')
543 . '</a></td></tr></table>'
544 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
545 . esc_html__('Site:', 'yatra') . ' <a href="{{site_url}}" style="color:#2563eb;">{{site_url}}</a>'
546 . '</p>';
547
548 return EmailTemplateLayout::admin(
549 '🔔',
550 'New booking',
551 $inner,
552 '{{site_name}} · ' . esc_html__('Admin notification', 'yatra')
553 );
554 }
555
556 private static function htmlPaymentCustomer(): string
557 {
558 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Dear {{customer_name}},</p>'
559 . '<p style="margin:0 0 20px;color:#475569;">'
560 . esc_html__('We’ve successfully received your payment. Thank you — you’re one step closer to takeoff!', 'yatra')
561 . '</p>'
562 . EmailTemplateLayout::detailCard([
563 ['label' => 'Booking reference', 'value' => '{{booking_reference}}'],
564 ['label' => 'Amount paid', 'value' => '{{payment_amount_formatted}}'],
565 ['label' => 'Method', 'value' => '{{payment_method}}'],
566 ['label' => 'Transaction ID', 'value' => '{{transaction_id}}'],
567 ]);
568
569 return EmailTemplateLayout::customer(
570 '�
571 ',
572 'Payment received',
573 $inner,
574 '{{site_name}}',
575 'Payment received'
576 );
577 }
578
579 private static function htmlCancellationCustomer(): string
580 {
581 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
582 . '<p style="margin:0 0 20px;color:#475569;">'
583 . esc_html__('This email confirms that your booking has been cancelled. If this wasn’t expected, please contact us.', 'yatra')
584 . '</p>'
585 . EmailTemplateLayout::detailCard([
586 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
587 ['label' => 'Trip', 'value' => '{{trip_name}}'],
588 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
589 ])
590 . '<p style="margin:24px 0 0;"><a href="{{trip_url}}" style="color:#0d9488;font-weight:600;text-decoration:none;">' . esc_html__('Browse more trips →', 'yatra') . '</a></p>';
591
592 return EmailTemplateLayout::customer(
593 '📋',
594 'Booking cancelled',
595 $inner,
596 '{{site_name}}',
597 'Booking cancelled'
598 );
599 }
600
601 private static function htmlTripCompleted(): string
602 {
603 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
604 . '<p style="margin:0 0 20px;color:#475569;">'
605 . esc_html__('We hope you loved', 'yatra') . ' <strong style="color:#0f172a;">{{trip_name}}</strong>. '
606 . esc_html__('Thank you for choosing us — we’d be delighted to host you again.', 'yatra')
607 . '</p>'
608 . EmailTemplateLayout::detailCard([
609 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
610 ['label' => 'Trip', 'value' => '{{trip_name}}'],
611 ]);
612
613 return EmailTemplateLayout::customer(
614 '🌟',
615 'Trip complete',
616 $inner,
617 '{{site_name}}',
618 'Thank you for traveling with us'
619 );
620 }
621
622 private static function htmlReminderCustomer(): string
623 {
624 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Dear {{customer_name}},</p>'
625 . '<p style="margin:0 0 20px;color:#475569;">'
626 . esc_html__('Friendly heads-up: your departure is in', 'yatra')
627 . ' <strong style="color:#0f172a;">{{reminder_days}}</strong> '
628 . esc_html__('days. Here’s what you need at a glance.', 'yatra')
629 . '</p>'
630 . EmailTemplateLayout::detailCard([
631 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
632 ['label' => 'Trip', 'value' => '{{trip_name}}'],
633 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
634 ['label' => 'Travelers', 'value' => '{{travelers_count}}'],
635 ['label' => 'Balance due', 'value' => '{{amount_due_formatted}}'],
636 ])
637 . '{{reminder_extra_html}}';
638
639 return EmailTemplateLayout::customer(
640 '🗓️',
641 'Trip reminder',
642 $inner,
643 '{{site_name}}',
644 'Trip reminder'
645 );
646 }
647
648 private static function htmlPaymentReminder(): string
649 {
650 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
651 . '<p style="margin:0 0 20px;color:#475569;">'
652 . esc_html__('This is a gentle nudge about your booking', 'yatra')
653 . ' <strong>{{booking_reference}}</strong> '
654 . esc_html__('for', 'yatra')
655 . ' <strong>{{trip_name}}</strong>. '
656 . esc_html__('If a balance remains, please settle it before your travel date ({{travel_date}}).', 'yatra')
657 . '</p>'
658 . EmailTemplateLayout::detailCard([
659 ['label' => 'Amount due', 'value' => '{{amount_due_formatted}}'],
660 ['label' => 'Trip', 'value' => '{{trip_name}}'],
661 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
662 ]);
663
664 return EmailTemplateLayout::customer(
665 '💳',
666 'Payment reminder',
667 $inner,
668 '{{site_name}}',
669 'Payment reminder'
670 );
671 }
672
673 private static function htmlEnquiryCustomer(): string
674 {
675 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
676 . '<p style="margin:0 0 20px;color:#475569;">'
677 . esc_html__('Thanks for reaching out about', 'yatra')
678 . ' <strong style="color:#0f172a;">{{trip_name}}</strong>. '
679 . esc_html__('We’ve received your message and our team will reply shortly.', 'yatra')
680 . '</p>'
681 . '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#f0fdfa;border:1px solid #99f6e4;border-radius:12px;margin:8px 0 0;">'
682 . '<tr><td style="padding:16px 20px;font-size:14px;color:#115e59;">✉️ '
683 . esc_html__('Typical reply time: within one business day.', 'yatra')
684 . '</td></tr></table>';
685
686 return EmailTemplateLayout::customer(
687 '✉️',
688 'Message received',
689 $inner,
690 '{{site_name}}',
691 'Enquiry received'
692 );
693 }
694
695 private static function htmlEnquiryAdmin(): string
696 {
697 $inner = '<p style="margin:0 0 20px;color:#475569;">'
698 . esc_html__('Someone submitted an enquiry from your site. Follow up from the details below.', 'yatra')
699 . '</p>'
700 . EmailTemplateLayout::detailCard([
701 ['label' => 'Name', 'value' => '{{customer_name}}'],
702 ['label' => 'Email', 'value' => '{{customer_email}}'],
703 ['label' => 'Phone', 'value' => '{{customer_phone}}'],
704 ['label' => 'Trip', 'value' => '{{trip_name}}'],
705 ])
706 . '<p style="margin:20px 0 8px;font-size:12px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;">'
707 . esc_html__('Message', 'yatra')
708 . '</p>'
709 . '<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:18px 20px;color:#334155;line-height:1.65;">{{message}}</div>';
710
711 return EmailTemplateLayout::admin(
712 '💬',
713 'New enquiry',
714 $inner,
715 '{{site_name}} · ' . esc_html__('Admin', 'yatra')
716 );
717 }
718
719 private static function htmlEnquiryResponse(): string
720 {
721 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
722 . '<p style="margin:0 0 20px;color:#475569;">'
723 . esc_html__('Here’s our reply to your enquiry:', 'yatra')
724 . '</p>'
725 . '<div style="background:#f8fafc;border-left:4px solid #0d9488;border-radius:0 12px 12px 0;padding:20px 24px;color:#334155;line-height:1.7;">{{response}}</div>'
726 . '<p style="margin:24px 0 0;font-size:14px;color:#64748b;">'
727 . esc_html__('Questions? Just reply to this email.', 'yatra')
728 . '</p>';
729
730 return EmailTemplateLayout::customer(
731 '💬',
732 'Our reply',
733 $inner,
734 '{{site_name}}',
735 'Enquiry response'
736 );
737 }
738
739 private static function htmlReviewRequest(): string
740 {
741 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
742 . '<p style="margin:0 0 20px;color:#475569;">'
743 . esc_html__('We hope', 'yatra')
744 . ' <strong>{{trip_name}}</strong> '
745 . esc_html__('was unforgettable. Would you share a quick review? It helps other travelers and our team.', 'yatra')
746 . '</p>'
747 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:8px 0 24px;"><tr>'
748 . '<td style="border-radius:10px;background:#f59e0b;">'
749 . '<a href="{{review_url}}" style="display:inline-block;padding:14px 28px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#1c1917;text-decoration:none;border-radius:10px;">'
750 . '⭐ ' . esc_html__('Leave a review', 'yatra')
751 . '</a></td></tr></table>'
752 . '<p style="margin:0;font-size:13px;color:#94a3b8;">'
753 . esc_html__('Takes about a minute — thank you!', 'yatra')
754 . '</p>';
755
756 return EmailTemplateLayout::customer(
757 '⭐',
758 'How was your trip?',
759 $inner,
760 '{{site_name}}',
761 'Review request'
762 );
763 }
764
765 /**
766 * Merge-tag variables for enquiry templates (core wp_mail path when Pro does not own the channel).
767 *
768 * @param object $enquiry Row from EnquiryRepository::findWithTrip()
769 */
770 private static function enquiryVariablesForTemplates(object $enquiry, string $responsePlain): array
771 {
772 $trip = trim((string) ($enquiry->trip_title ?? ''));
773
774 return [
775 'customer_name' => (string) ($enquiry->name ?? ''),
776 'customer_email' => (string) ($enquiry->email ?? ''),
777 'customer_phone' => (string) ($enquiry->phone ?? ''),
778 'trip_name' => $trip !== '' ? $trip : __('General enquiry', 'yatra'),
779 'message' => nl2br(esc_html((string) ($enquiry->message ?? ''))),
780 'response' => $responsePlain !== '' ? nl2br(esc_html($responsePlain)) : '',
781 'response_message' => $responsePlain !== '' ? nl2br(esc_html($responsePlain)) : '',
782 ];
783 }
784
785 /**
786 * Full HTML body matching Pro/system enquiry_received (for free core sends).
787 */
788 public static function renderCoreEnquiryCustomerConfirmationHtml(object $enquiry): string
789 {
790 $vars = self::enquiryVariablesForTemplates($enquiry, '');
791
792 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryCustomer(), $vars);
793 }
794
795 /**
796 * Full HTML body matching Pro/system enquiry_admin.
797 */
798 public static function renderCoreEnquiryAdminNotificationHtml(object $enquiry): string
799 {
800 $vars = self::enquiryVariablesForTemplates($enquiry, '');
801
802 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryAdmin(), $vars);
803 }
804
805 /**
806 * Full HTML body matching Pro/system enquiry_response.
807 */
808 public static function renderCoreEnquiryResponseHtml(object $enquiry, string $response): string
809 {
810 $vars = self::enquiryVariablesForTemplates($enquiry, $response);
811
812 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryResponse(), $vars);
813 }
814
815 /**
816 * Review reminder (cron): same shell as Pro review_request template.
817 */
818 public static function renderCoreReviewReminderHtml(string $customerName, string $tripName, string $reviewUrl): string
819 {
820 $vars = [
821 'customer_name' => $customerName,
822 'trip_name' => $tripName,
823 'review_url' => esc_url($reviewUrl),
824 ];
825
826 return TransactionalEmailTemplateService::parseMergeTags(self::htmlReviewRequest(), $vars);
827 }
828 }
829