PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.6
Yatra – Travel Booking & Tour Operator Software v3.0.6
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 2.0.10 All 83 releases
yatra / app / Services / EmailTemplateDefaults.php

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

1,356 lines 65.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 'email_tpl_trip_consent_subject' => '📝 [{{site_name}}] Action required · {{form_name}}',
38 'email_tpl_trip_consent_body' => self::htmlTripConsentRequest(),
39 'email_tpl_customer_verification_subject' => '✉️ [{{site_name}}] Verify your email address',
40 'email_tpl_customer_verification_body' => self::htmlCustomerEmailVerification(),
41 'email_tpl_booking_completed_subject' => '🌟 [{{site_name}}] Thanks for traveling · {{booking_reference}}',
42 'email_tpl_booking_completed_body' => self::htmlTripCompleted(),
43 'email_tpl_booking_expired_customer_subject' => '⏱️ [{{site_name}}] Booking expired · {{booking_reference}}',
44 'email_tpl_booking_expired_customer_body' => self::htmlBookingExpiredCustomer(),
45 'email_tpl_admin_booking_expired_subject' => '⏱️ [{{site_name}}] Booking expired · {{booking_reference}} (#{{booking_id}})',
46 'email_tpl_admin_booking_expired_body' => self::htmlAdminBookingExpired(),
47 'email_tpl_scheduled_payment_reminder_subject' => '💳 [{{site_name}}] Upcoming payment · {{booking_reference}}',
48 'email_tpl_scheduled_payment_reminder_body' => self::htmlScheduledPaymentReminder(),
49 'email_tpl_scheduled_payment_succeeded_subject' => '�
50 [{{site_name}}] Scheduled payment received · {{booking_reference}}',
51 'email_tpl_scheduled_payment_succeeded_body' => self::htmlScheduledPaymentSucceeded(),
52 'email_tpl_scheduled_payment_failed_subject' => '⚠️ [{{site_name}}] Payment issue · {{booking_reference}}',
53 'email_tpl_scheduled_payment_failed_body' => self::htmlScheduledPaymentFailed(),
54 'email_tpl_admin_scheduled_payment_failed_subject' => '⚠️ [{{site_name}}] Scheduled payment failed · {{booking_reference}}',
55 'email_tpl_admin_scheduled_payment_failed_body' => self::htmlAdminScheduledPaymentFailed(),
56 'email_tpl_enquiry_admin_subject' => '💬 [{{site_name}}] New enquiry · {{customer_name}}',
57 'email_tpl_enquiry_admin_body' => self::htmlEnquiryAdmin(),
58 'email_tpl_enquiry_received_subject' => '✉️ [{{site_name}}] We received your message',
59 'email_tpl_enquiry_received_body' => self::htmlEnquiryCustomer(),
60 'email_tpl_enquiry_response_subject' => '💬 [{{site_name}}] Re: your enquiry',
61 'email_tpl_enquiry_response_body' => self::htmlEnquiryResponse(),
62 'email_tpl_review_request_subject' => ' [{{site_name}}] How was {{trip_name}}?',
63 'email_tpl_review_request_body' => self::htmlReviewRequest(),
64 'email_tpl_abandoned_booking_recovery_first_subject' => '🛒 [{{site_name}}] Complete your booking',
65 'email_tpl_abandoned_booking_recovery_first_body' => self::htmlAbandonedBookingRecoveryFirst(),
66 'email_tpl_abandoned_booking_recovery_second_subject' => ' [{{site_name}}] Still interested? Your booking is waiting',
67 'email_tpl_abandoned_booking_recovery_second_body' => self::htmlAbandonedBookingRecoverySecond(),
68 'email_tpl_abandoned_booking_recovery_final_subject' => '⚠️ [{{site_name}}] Final reminder: complete your booking',
69 'email_tpl_abandoned_booking_recovery_final_body' => self::htmlAbandonedBookingRecoveryFinal(),
70 ];
71 }
72
73 /**
74 * Full subject + body for Pro system templates (DB). Null = no bundled default for that key.
75 *
76 * @return array{subject: string, body: string}|null
77 */
78 public static function proSystemTemplate(string $templateKey): ?array
79 {
80 $map = [
81 'new_booking' => [
82 'subject' => '✈️ Booking confirmation · {{booking_reference}}',
83 'body' => self::htmlBookingCustomer(),
84 ],
85 'booking_payment' => [
86 'subject' => '�
87 Payment received · {{booking_reference}}',
88 'body' => self::htmlPaymentCustomer(),
89 ],
90 'booking_confirmation' => [
91 'subject' => '✈️ Your booking · {{booking_reference}}',
92 'body' => self::htmlBookingCustomer(),
93 ],
94 'booking_confirmed' => [
95 'subject' => '🎉 You\'re confirmed · {{booking_reference}}',
96 'body' => self::htmlBookingConfirmed(),
97 ],
98 'admin_new_booking' => [
99 'subject' => '🔔 New booking · {{booking_reference}} (#{{booking_id}})',
100 'body' => self::htmlAdminNewBooking(),
101 ],
102 'booking_cancelled' => [
103 'subject' => '📋 Booking cancelled · {{booking_reference}}',
104 'body' => self::htmlCancellationCustomer(),
105 ],
106 'booking_completed' => [
107 'subject' => '🌟 Thanks for traveling with us · {{booking_reference}}',
108 'body' => self::htmlTripCompleted(),
109 ],
110 'payment_received' => [
111 'subject' => '�
112 Payment received · {{booking_reference}}',
113 'body' => self::htmlPaymentCustomer(),
114 ],
115 'payment_reminder' => [
116 'subject' => '💳 Payment reminder · {{booking_reference}}',
117 'body' => self::htmlPaymentReminder(),
118 ],
119 'enquiry_received' => [
120 'subject' => '✉️ We received your message',
121 'body' => self::htmlEnquiryCustomer(),
122 ],
123 'enquiry_admin' => [
124 'subject' => '💬 New enquiry · {{customer_name}}',
125 'body' => self::htmlEnquiryAdmin(),
126 ],
127 'enquiry_response' => [
128 'subject' => '💬 Re: your enquiry',
129 'body' => self::htmlEnquiryResponse(),
130 ],
131 'trip_reminder' => [
132 'subject' => '🗓 Reminder · {{trip_name}}',
133 'body' => self::htmlReminderCustomer(),
134 ],
135 'review_request' => [
136 'subject' => ' How was {{trip_name}}?',
137 'body' => self::htmlReviewRequest(),
138 ],
139 'trip_consent_request' => [
140 'subject' => '📝 [{{site_name}}] Action required · {{form_name}}',
141 'body' => self::htmlTripConsentRequest(),
142 ],
143 'customer_email_verification' => [
144 'subject' => '✉️ [{{site_name}}] Verify your email address',
145 'body' => self::htmlCustomerEmailVerification(),
146 ],
147 'booking_expired_customer' => [
148 'subject' => '⏱️ [{{site_name}}] Booking expired · {{booking_reference}}',
149 'body' => self::htmlBookingExpiredCustomer(),
150 ],
151 'admin_booking_expired' => [
152 'subject' => '⏱️ [{{site_name}}] Booking expired · {{booking_reference}} (#{{booking_id}})',
153 'body' => self::htmlAdminBookingExpired(),
154 ],
155 'scheduled_payment_reminder' => [
156 'subject' => '💳 [{{site_name}}] Upcoming payment · {{booking_reference}}',
157 'body' => self::htmlScheduledPaymentReminder(),
158 ],
159 'scheduled_payment_succeeded' => [
160 'subject' => '�
161 [{{site_name}}] Scheduled payment received · {{booking_reference}}',
162 'body' => self::htmlScheduledPaymentSucceeded(),
163 ],
164 'scheduled_payment_failed' => [
165 'subject' => '⚠️ [{{site_name}}] Payment issue · {{booking_reference}}',
166 'body' => self::htmlScheduledPaymentFailed(),
167 ],
168 'admin_scheduled_payment_failed' => [
169 'subject' => '⚠️ [{{site_name}}] Scheduled payment failed · {{booking_reference}}',
170 'body' => self::htmlAdminScheduledPaymentFailed(),
171 ],
172 'abandoned_booking_recovery_first' => [
173 'subject' => '🛒 [{{site_name}}] Complete your booking',
174 'body' => self::htmlAbandonedBookingRecoveryFirst(),
175 ],
176 'abandoned_booking_recovery_second' => [
177 'subject' => ' [{{site_name}}] Still interested? Your booking is waiting',
178 'body' => self::htmlAbandonedBookingRecoverySecond(),
179 ],
180 'abandoned_booking_recovery_final' => [
181 'subject' => '⚠️ [{{site_name}}] Final reminder: complete your booking',
182 'body' => self::htmlAbandonedBookingRecoveryFinal(),
183 ],
184 ];
185
186 return $map[$templateKey] ?? null;
187 }
188
189 /**
190 * Fallback HTML when settings templates are empty (escaped runtime variables).
191 *
192 * @param array<string, string> $v
193 */
194 public static function fallbackTransactionalBooking(array $v): string
195 {
196 $name = esc_html($v['customer_first_name'] ?: $v['customer_name'] ?: __('there', 'yatra'));
197 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
198
199 if (!empty($v['details_html_only'])) {
200 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
201 . sprintf(
202 /* translators: %s: customer name */
203 esc_html__('Hello %s,', 'yatra'),
204 $name
205 )
206 . '</p>'
207 . '<p style="margin:0 0 20px;color:#475569;">'
208 . esc_html($v['intro_paragraph'] ?? __('Thank you for your booking. Here are your details:', 'yatra'))
209 . '</p>'
210 . wp_kses_post((string) ($v['details_html'] ?? ''))
211 . (!empty($v['footer_note']) ? '<p style="margin:24px 0 0;color:#475569;">' . wp_kses_post((string) $v['footer_note']) . '</p>' : '');
212
213 return EmailTemplateLayout::customer(
214 '✈️',
215 __('Booking update', 'yatra'),
216 $inner,
217 $site,
218 __('Your booking details are inside.', 'yatra')
219 );
220 }
221
222 $rows = array_values(array_filter([
223 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
224 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
225 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
226 ['label' => __('Travelers', 'yatra'), 'value' => esc_html($v['travelers_count'] ?? '')],
227 ['label' => __('Total', 'yatra'), 'value' => esc_html($v['total_amount_formatted'] ?? '')],
228 ['label' => __('Amount due now', 'yatra'), 'value' => esc_html($v['amount_due_formatted'] ?? '')],
229 ], static function (array $row): bool {
230 return $row['value'] !== '';
231 }));
232
233 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
234 . sprintf(
235 /* translators: %s: customer name */
236 esc_html__('Hello %s,', 'yatra'),
237 $name
238 )
239 . '</p>'
240 . '<p style="margin:0 0 8px;color:#475569;">'
241 . esc_html($v['intro_paragraph'] ?? __('Thank you for your booking. Here are your details:', 'yatra'))
242 . '</p>'
243 . EmailTemplateLayout::detailCard($rows)
244 . (!empty($v['details_html']) ? '<div style="margin:16px 0 0;">' . wp_kses_post((string) $v['details_html']) . '</div>' : '')
245 . (!empty($v['footer_note']) ? '<p style="margin:24px 0 0;color:#475569;">' . wp_kses_post((string) $v['footer_note']) . '</p>' : '');
246
247 return EmailTemplateLayout::customer(
248 '✈️',
249 __('Booking update', 'yatra'),
250 $inner,
251 $site,
252 __('Your booking details are inside.', 'yatra')
253 );
254 }
255
256 /**
257 * @param array<string, string> $v
258 */
259 public static function fallbackTransactionalPayment(array $v): string
260 {
261 $name = esc_html($v['customer_first_name'] ?: $v['customer_name'] ?: __('Customer', 'yatra'));
262 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
263 $rows = array_values(array_filter([
264 ['label' => __('Booking reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
265 ['label' => __('Amount paid', 'yatra'), 'value' => esc_html($v['payment_amount_formatted'] ?? '')],
266 ['label' => __('Method', 'yatra'), 'value' => esc_html($v['payment_method'] ?? '')],
267 ['label' => __('Transaction ID', 'yatra'), 'value' => esc_html($v['transaction_id'] ?? '')],
268 ], static function (array $row): bool {
269 return $row['value'] !== '';
270 }));
271
272 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
273 . sprintf(
274 /* translators: %s: customer name */
275 esc_html__('Dear %s,', 'yatra'),
276 $name
277 )
278 . '</p>'
279 . '<p style="margin:0 0 8px;color:#475569;">'
280 . esc_html__('We’ve received your payment thank you! Here’s a quick summary.', 'yatra')
281 . '</p>'
282 . EmailTemplateLayout::detailCard($rows);
283
284 return EmailTemplateLayout::customer(
285 '�
286 ',
287 __('Payment received', 'yatra'),
288 $inner,
289 $site,
290 __('Payment confirmation', 'yatra')
291 );
292 }
293
294 /**
295 * @param array<string, string> $v
296 */
297 public static function fallbackTransactionalCancellation(array $v): string
298 {
299 $name = esc_html($v['customer_first_name'] ?: $v['customer_name'] ?: __('Customer', 'yatra'));
300 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
301 $rows = array_values(array_filter([
302 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
303 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
304 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
305 ], static function (array $row): bool {
306 return $row['value'] !== '';
307 }));
308
309 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
310 . sprintf(
311 /* translators: %s: customer name */
312 esc_html__('Hello %s,', 'yatra'),
313 $name
314 )
315 . '</p>'
316 . '<p style="margin:0 0 20px;color:#475569;">'
317 . esc_html__('Your booking has been cancelled as requested. If you have questions, just reply to this email.', 'yatra')
318 . '</p>'
319 . EmailTemplateLayout::detailCard($rows);
320
321 return EmailTemplateLayout::customer(
322 '📋',
323 __('Booking cancelled', 'yatra'),
324 $inner,
325 $site,
326 __('Booking cancellation notice', 'yatra')
327 );
328 }
329
330 /**
331 * @param array<string, string> $v
332 */
333 public static function fallbackTransactionalReminder(array $v): string
334 {
335 $name = esc_html($v['customer_name'] ?: __('Traveler', 'yatra'));
336 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
337 $days = esc_html((string) ($v['reminder_days'] ?? $v['days_until_trip'] ?? ''));
338
339 $rows = array_values(array_filter([
340 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
341 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
342 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
343 ['label' => __('Travelers', 'yatra'), 'value' => esc_html($v['travelers_count'] ?? '')],
344 ], static function (array $row): bool {
345 return $row['value'] !== '';
346 }));
347
348 $balanceRow = (!empty($v['amount_due_formatted']) && isset($v['amount_due_formatted']) && $v['amount_due_formatted'] !== yatra_format_price(0))
349 ? [['label' => __('Balance due', 'yatra'), 'value' => esc_html((string) $v['amount_due_formatted'])]]
350 : [];
351 if ($balanceRow !== []) {
352 $rows = array_merge($rows, $balanceRow);
353 }
354
355 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
356 . sprintf(
357 /* translators: %s: customer name */
358 esc_html__('Dear %s,', 'yatra'),
359 $name
360 )
361 . '</p>'
362 . '<p style="margin:0 0 20px;color:#475569;">'
363 . ($days !== ''
364 ? sprintf(
365 /* translators: %s: number of days */
366 esc_html__('Your adventure starts in %s days — we can’t wait to see you!', 'yatra'),
367 $days
368 )
369 : esc_html__('Your trip is coming up soon — we look forward to seeing you!', 'yatra'))
370 . '</p>'
371 . EmailTemplateLayout::detailCard($rows)
372 . (!empty($v['reminder_extra_html']) ? '<div style="margin:20px 0 0;">' . wp_kses_post($v['reminder_extra_html']) . '</div>' : '');
373
374 return EmailTemplateLayout::customer(
375 '🗓️',
376 __('Trip reminder', 'yatra'),
377 $inner,
378 $site,
379 __('Upcoming trip reminder', 'yatra')
380 );
381 }
382
383 /**
384 * @param array<string, string> $v
385 */
386 public static function fallbackTransactionalTripConsent(array $v): string
387 {
388 $recipient = esc_html($v['recipient_name'] ?: __('Traveler', 'yatra'));
389 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
390 $formNameRaw = (string) ($v['form_name'] ?? '');
391 $formNameEsc = esc_html($formNameRaw);
392 $link = esc_url((string) ($v['consent_link'] ?? home_url('/')));
393 $rows = array_values(array_filter([
394 ['label' => __('Form', 'yatra'), 'value' => $formNameEsc],
395 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
396 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
397 ['label' => __('Booking reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
398 ], static function (array $row): bool {
399 return $row['value'] !== '';
400 }));
401
402 $notice = !empty($v['expiry_notice_html'])
403 ? '<div style="margin:16px 0 0;padding:12px 16px;background:#fff7ed;border:1px solid #fed7aa;border-radius:10px;font-size:14px;color:#9a3412;">'
404 . wp_kses_post((string) $v['expiry_notice_html'])
405 . '</div>'
406 : '';
407
408 $testBlock = !empty($v['consent_test_notice_html'])
409 ? '<div style="margin:0 0 20px;padding:12px 16px;background:#f0fdfa;border:1px solid #99f6e4;border-radius:10px;font-size:14px;color:#115e59;">'
410 . wp_kses_post((string) $v['consent_test_notice_html'])
411 . '</div>'
412 : '';
413
414 $inner = $testBlock
415 . '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
416 . sprintf(
417 /* translators: %s: customer name */
418 esc_html__('Hello %s,', 'yatra'),
419 $recipient
420 )
421 . '</p>'
422 . '<p style="margin:0 0 20px;color:#475569;">'
423 . sprintf(
424 /* translators: %s: consent form title */
425 esc_html__('Please complete and sign “%s” before your trip.', 'yatra'),
426 $formNameRaw !== '' ? $formNameEsc : esc_html__('your consent form', 'yatra')
427 )
428 . '</p>'
429 . EmailTemplateLayout::detailCard($rows)
430 . $notice
431 . EmailTemplateLayout::button($link, __('Sign consent form', 'yatra'))
432 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
433 . esc_html__('If the button does not work, copy this link into your browser:', 'yatra')
434 . '</p>'
435 . '<p style="margin:8px 0 0;font-size:13px;word-break:break-all;"><a href="' . $link . '" style="color:#0d9488;">' . $link . '</a></p>';
436
437 return EmailTemplateLayout::customer(
438 '📝',
439 __('Consent required', 'yatra'),
440 $inner,
441 $site,
442 __('Sign your trip consent form', 'yatra')
443 );
444 }
445
446 /**
447 * @param array<string, string> $v
448 */
449 public static function fallbackTransactionalCustomerEmailVerification(array $v): string
450 {
451 $firstRaw = (string) ($v['customer_first_name'] ?? '');
452 if ($firstRaw === '') {
453 $firstRaw = (string) ($v['customer_name'] ?? '');
454 }
455 $first = esc_html($firstRaw !== '' ? $firstRaw : __('there', 'yatra'));
456 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
457 $link = esc_url((string) ($v['verification_link'] ?? home_url('/')));
458 $intro = isset($v['intro_paragraph']) ? esc_html((string) $v['intro_paragraph']) : '';
459 $footer = isset($v['footer_note']) ? esc_html((string) $v['footer_note']) : '';
460 $expiryInner = !empty($v['expiry_notice_html'])
461 ? wp_kses_post((string) $v['expiry_notice_html'])
462 : esc_html(
463 sprintf(
464 /* translators: %d: hours until link expiry */
465 __('This verification link expires in %d hours for your security.', 'yatra'),
466 24
467 )
468 );
469 $expiry = '<div style="margin:20px 0 0;padding:12px 16px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;font-size:14px;color:#475569;">'
470 . $expiryInner
471 . '</div>';
472
473 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
474 . sprintf(
475 /* translators: %s: customer name */
476 esc_html__('Hello %s,', 'yatra'),
477 $first
478 )
479 . '</p>'
480 . ($intro !== '' ? '<p style="margin:0 0 20px;color:#475569;">' . $intro . '</p>' : '')
481 . EmailTemplateLayout::button($link, __('Verify email address', 'yatra'))
482 . $expiry
483 . ($footer !== '' ? '<p style="margin:24px 0 0;font-size:14px;color:#64748b;">' . $footer . '</p>' : '')
484 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
485 . esc_html__('If the button does not work, copy this link into your browser:', 'yatra')
486 . '</p>'
487 . '<p style="margin:8px 0 0;font-size:13px;word-break:break-all;"><a href="' . $link . '" style="color:#0d9488;">' . $link . '</a></p>';
488
489 return EmailTemplateLayout::customer(
490 '✉️',
491 __('Verify your email', 'yatra'),
492 $inner,
493 $site,
494 __('Account verification', 'yatra')
495 );
496 }
497
498 /**
499 * Fallback HTML for admin new-booking notice (empty saved template).
500 *
501 * @param array<string, string> $v
502 */
503 /**
504 * Fallback HTML for admin payment-received notice.
505 *
506 * @param array<string, string> $v
507 */
508 public static function fallbackAdminPaymentReceived(array $v): string
509 {
510 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
511 $rows = array_values(array_filter([
512 ['label' => __('Booking ID', 'yatra'), 'value' => esc_html($v['booking_id'] ?? '')],
513 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
514 ['label' => __('Customer', 'yatra'), 'value' => esc_html($v['customer_name'] ?? '')],
515 ['label' => __('Amount', 'yatra'), 'value' => esc_html($v['payment_amount_formatted'] ?? '')],
516 ['label' => __('Method', 'yatra'), 'value' => esc_html($v['payment_method'] ?? '')],
517 ['label' => __('Transaction ID', 'yatra'), 'value' => esc_html($v['transaction_id'] ?? '')],
518 ], static function (array $row): bool {
519 return trim((string) ($row['value'] ?? '')) !== '';
520 }));
521
522 $adminUrl = esc_url($v['admin_url'] ?? admin_url('admin.php?page=yatra'));
523
524 $inner = '<p style="margin:0 0 20px;color:#475569;">'
525 . esc_html__('A payment was recorded for the booking below.', 'yatra')
526 . '</p>'
527 . EmailTemplateLayout::detailCard($rows)
528 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
529 . '<td style="border-radius:10px;background:#2563eb;">'
530 . '<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;">'
531 . esc_html__('Open in Yatra admin', 'yatra')
532 . '</a></td></tr></table>';
533
534 return EmailTemplateLayout::admin(
535 '�
536 ',
537 __('Payment received', 'yatra'),
538 $inner,
539 $site . ' · ' . esc_html__('Admin notification', 'yatra')
540 );
541 }
542
543 /**
544 * Fallback HTML for admin booking-cancelled notice.
545 *
546 * @param array<string, string> $v
547 */
548 public static function fallbackAdminBookingCancelled(array $v): string
549 {
550 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
551 $rows = array_values(array_filter([
552 ['label' => __('Booking ID', 'yatra'), 'value' => esc_html($v['booking_id'] ?? '')],
553 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
554 ['label' => __('Customer', 'yatra'), 'value' => esc_html($v['customer_name'] ?? '')],
555 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
556 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
557 ], static function (array $row): bool {
558 return trim((string) ($row['value'] ?? '')) !== '';
559 }));
560
561 $adminUrl = esc_url($v['admin_url'] ?? admin_url('admin.php?page=yatra'));
562
563 $inner = '<p style="margin:0 0 20px;color:#475569;">'
564 . esc_html__('A booking was cancelled. Summary below.', 'yatra')
565 . '</p>'
566 . EmailTemplateLayout::detailCard($rows)
567 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
568 . '<td style="border-radius:10px;background:#2563eb;">'
569 . '<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;">'
570 . esc_html__('Open in Yatra admin', 'yatra')
571 . '</a></td></tr></table>';
572
573 return EmailTemplateLayout::admin(
574 '📋',
575 __('Booking cancelled', 'yatra'),
576 $inner,
577 $site . ' · ' . esc_html__('Admin notification', 'yatra')
578 );
579 }
580
581 public static function fallbackAdminNewBooking(array $v): string
582 {
583 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
584 $rows = array_values(array_filter([
585 ['label' => __('Reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
586 ['label' => __('Booking ID', 'yatra'), 'value' => esc_html($v['booking_id'] ?? '')],
587 ['label' => __('Customer', 'yatra'), 'value' => esc_html($v['customer_name'] ?? '')],
588 ['label' => __('Email', 'yatra'), 'value' => esc_html($v['customer_email'] ?? '')],
589 ['label' => __('Phone', 'yatra'), 'value' => esc_html($v['customer_phone'] ?? '')],
590 ['label' => __('Trip', 'yatra'), 'value' => esc_html($v['trip_name'] ?? '')],
591 ['label' => __('Travel date', 'yatra'), 'value' => esc_html($v['travel_date'] ?? '')],
592 ['label' => __('Travelers', 'yatra'), 'value' => esc_html($v['travelers_count'] ?? '')],
593 ['label' => __('Total', 'yatra'), 'value' => trim(esc_html($v['total_amount_formatted'] ?? '') . ' ' . esc_html($v['currency'] ?? ''))],
594 ['label' => __('Booking status', 'yatra'), 'value' => esc_html($v['booking_status'] ?? '')],
595 ['label' => __('Payment status', 'yatra'), 'value' => esc_html($v['payment_status'] ?? '')],
596 ], static function (array $row): bool {
597 return trim((string) ($row['value'] ?? '')) !== '';
598 }));
599
600 $adminUrl = esc_url($v['admin_url'] ?? admin_url('admin.php?page=yatra'));
601 $siteUrl = esc_url($v['site_url'] ?? home_url('/'));
602
603 $inner = '<p style="margin:0 0 20px;color:#475569;">'
604 . esc_html__('A new booking just landed. Review the snapshot below and open the admin to take action.', 'yatra')
605 . '</p>'
606 . EmailTemplateLayout::detailCard($rows)
607 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
608 . '<td style="border-radius:10px;background:#2563eb;">'
609 . '<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;">'
610 . esc_html__('Open in Yatra admin', 'yatra')
611 . '</a></td></tr></table>'
612 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
613 . esc_html__('Site:', 'yatra') . ' <a href="' . $siteUrl . '" style="color:#2563eb;">' . esc_html($siteUrl) . '</a>'
614 . '</p>';
615
616 return EmailTemplateLayout::admin(
617 '🔔',
618 __('New booking', 'yatra'),
619 $inner,
620 $site . ' · ' . esc_html__('Admin notification', 'yatra')
621 );
622 }
623
624 private static function htmlBookingCustomer(): string
625 {
626 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
627 . '<p style="margin:0 0 20px;color:#475569;">{{intro_paragraph}}</p>'
628 . EmailTemplateLayout::detailCard([
629 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
630 ['label' => 'Trip', 'value' => '{{trip_name}}'],
631 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
632 ['label' => 'Travelers', 'value' => '{{travelers_count}}'],
633 ['label' => 'Total', 'value' => '{{total_amount_formatted}}'],
634 ['label' => 'Amount due now', 'value' => '{{amount_due_formatted}}'],
635 ])
636 . '{{details_html}}'
637 . '<p style="margin:24px 0 0;color:#475569;">{{footer_note}}</p>'
638 . '<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>';
639
640 return EmailTemplateLayout::customer(
641 '✈️',
642 'Booking update',
643 $inner,
644 '{{site_name}}',
645 'Booking update'
646 );
647 }
648
649 private static function htmlBookingConfirmed(): string
650 {
651 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
652 . '<p style="margin:0 0 20px;color:#475569;">'
653 . esc_html__('Great news your booking is confirmed. Save this email for your records.', 'yatra')
654 . '</p>'
655 . EmailTemplateLayout::detailCard([
656 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
657 ['label' => 'Trip', 'value' => '{{trip_name}}'],
658 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
659 ['label' => 'Travelers', 'value' => '{{travelers_count}}'],
660 ['label' => 'Total', 'value' => '{{total_amount_formatted}}'],
661 ])
662 . '<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>';
663
664 return EmailTemplateLayout::customer(
665 '🎉',
666 __("You're all set", 'yatra'),
667 $inner,
668 '{{site_name}}',
669 'Booking confirmed'
670 );
671 }
672
673 private static function htmlAdminPaymentReceived(): string
674 {
675 $inner = '<p style="margin:0 0 20px;color:#475569;">'
676 . esc_html__('A payment was recorded for the booking below.', 'yatra')
677 . '</p>'
678 . EmailTemplateLayout::detailCard([
679 ['label' => 'Booking ID', 'value' => '{{booking_id}}'],
680 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
681 ['label' => 'Customer', 'value' => '{{customer_name}}'],
682 ['label' => 'Amount', 'value' => '{{payment_amount_formatted}}'],
683 ['label' => 'Method', 'value' => '{{payment_method}}'],
684 ['label' => 'Transaction ID', 'value' => '{{transaction_id}}'],
685 ])
686 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
687 . '<td style="border-radius:10px;background:#2563eb;">'
688 . '<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;">'
689 . esc_html__('Open in Yatra admin', 'yatra')
690 . '</a></td></tr></table>';
691
692 return EmailTemplateLayout::admin(
693 '�
694 ',
695 'Payment received',
696 $inner,
697 '{{site_name}} · ' . esc_html__('Admin notification', 'yatra')
698 );
699 }
700
701 private static function htmlAdminBookingCancelled(): string
702 {
703 $inner = '<p style="margin:0 0 20px;color:#475569;">'
704 . esc_html__('A booking was cancelled. Summary below.', 'yatra')
705 . '</p>'
706 . EmailTemplateLayout::detailCard([
707 ['label' => 'Booking ID', 'value' => '{{booking_id}}'],
708 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
709 ['label' => 'Customer', 'value' => '{{customer_name}}'],
710 ['label' => 'Trip', 'value' => '{{trip_name}}'],
711 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
712 ])
713 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
714 . '<td style="border-radius:10px;background:#2563eb;">'
715 . '<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;">'
716 . esc_html__('Open in Yatra admin', 'yatra')
717 . '</a></td></tr></table>';
718
719 return EmailTemplateLayout::admin(
720 '📋',
721 'Booking cancelled',
722 $inner,
723 '{{site_name}} · ' . esc_html__('Admin notification', 'yatra')
724 );
725 }
726
727 private static function htmlAdminNewBooking(): string
728 {
729 $inner = '<p style="margin:0 0 20px;color:#475569;">'
730 . esc_html__('A new booking just landed. Review the snapshot below and open the admin to take action.', 'yatra')
731 . '</p>'
732 . EmailTemplateLayout::detailCard([
733 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
734 ['label' => 'Booking ID', 'value' => '{{booking_id}}'],
735 ['label' => 'Customer', 'value' => '{{customer_name}}'],
736 ['label' => 'Email', 'value' => '{{customer_email}}'],
737 ['label' => 'Phone', 'value' => '{{customer_phone}}'],
738 ['label' => 'Trip', 'value' => '{{trip_name}}'],
739 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
740 ['label' => 'Travelers', 'value' => '{{travelers_count}}'],
741 ['label' => 'Total', 'value' => '{{total_amount_formatted}} {{currency}}'],
742 ['label' => 'Booking status', 'value' => '{{booking_status}}'],
743 ['label' => 'Payment status', 'value' => '{{payment_status}}'],
744 ])
745 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
746 . '<td style="border-radius:10px;background:#2563eb;">'
747 . '<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;">'
748 . esc_html__('Open in Yatra admin', 'yatra')
749 . '</a></td></tr></table>'
750 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
751 . esc_html__('Site:', 'yatra') . ' <a href="{{site_url}}" style="color:#2563eb;">{{site_url}}</a>'
752 . '</p>';
753
754 return EmailTemplateLayout::admin(
755 '🔔',
756 'New booking',
757 $inner,
758 '{{site_name}} · ' . esc_html__('Admin notification', 'yatra')
759 );
760 }
761
762 private static function htmlPaymentCustomer(): string
763 {
764 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Dear {{customer_name}},</p>'
765 . '<p style="margin:0 0 20px;color:#475569;">'
766 . esc_html__('We’ve successfully received your payment. Thank you you’re one step closer to takeoff!', 'yatra')
767 . '</p>'
768 . EmailTemplateLayout::detailCard([
769 ['label' => 'Booking reference', 'value' => '{{booking_reference}}'],
770 ['label' => 'Amount paid', 'value' => '{{payment_amount_formatted}}'],
771 ['label' => 'Method', 'value' => '{{payment_method}}'],
772 ['label' => 'Transaction ID', 'value' => '{{transaction_id}}'],
773 ]);
774
775 return EmailTemplateLayout::customer(
776 '�
777 ',
778 'Payment received',
779 $inner,
780 '{{site_name}}',
781 'Payment received'
782 );
783 }
784
785 private static function htmlCancellationCustomer(): string
786 {
787 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
788 . '<p style="margin:0 0 20px;color:#475569;">'
789 . esc_html__('This email confirms that your booking has been cancelled. If this wasn’t expected, please contact us.', 'yatra')
790 . '</p>'
791 . EmailTemplateLayout::detailCard([
792 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
793 ['label' => 'Trip', 'value' => '{{trip_name}}'],
794 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
795 ])
796 . '<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>';
797
798 return EmailTemplateLayout::customer(
799 '📋',
800 'Booking cancelled',
801 $inner,
802 '{{site_name}}',
803 'Booking cancelled'
804 );
805 }
806
807 private static function htmlTripCompleted(): string
808 {
809 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
810 . '<p style="margin:0 0 20px;color:#475569;">'
811 . esc_html__('We hope you loved', 'yatra') . ' <strong style="color:#0f172a;">{{trip_name}}</strong>. '
812 . esc_html__('Thank you for choosing us — we’d be delighted to host you again.', 'yatra')
813 . '</p>'
814 . EmailTemplateLayout::detailCard([
815 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
816 ['label' => 'Trip', 'value' => '{{trip_name}}'],
817 ]);
818
819 return EmailTemplateLayout::customer(
820 '🌟',
821 'Trip complete',
822 $inner,
823 '{{site_name}}',
824 'Thank you for traveling with us'
825 );
826 }
827
828 private static function htmlReminderCustomer(): string
829 {
830 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Dear {{customer_name}},</p>'
831 . '<p style="margin:0 0 20px;color:#475569;">'
832 . esc_html__('Friendly heads-up: your departure is in', 'yatra')
833 . ' <strong style="color:#0f172a;">{{reminder_days}}</strong> '
834 . esc_html__('days. Here’s what you need at a glance.', 'yatra')
835 . '</p>'
836 . EmailTemplateLayout::detailCard([
837 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
838 ['label' => 'Trip', 'value' => '{{trip_name}}'],
839 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
840 ['label' => 'Travelers', 'value' => '{{travelers_count}}'],
841 ['label' => 'Balance due', 'value' => '{{amount_due_formatted}}'],
842 ])
843 . '{{reminder_extra_html}}';
844
845 return EmailTemplateLayout::customer(
846 '🗓️',
847 'Trip reminder',
848 $inner,
849 '{{site_name}}',
850 'Trip reminder'
851 );
852 }
853
854 private static function htmlTripConsentRequest(): string
855 {
856 $cta = '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0;"><tr>'
857 . '<td style="border-radius:10px;background:#0d9488;">'
858 . '<a href="{{consent_link}}" style="display:inline-block;padding:14px 28px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
859 . esc_html__('Sign consent form', 'yatra')
860 . '</a></td></tr></table>';
861
862 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{recipient_name}},</p>'
863 . '<p style="margin:0 0 20px;color:#475569;">'
864 . esc_html__('Please review and sign the consent form for your upcoming trip.', 'yatra')
865 . '</p>'
866 . '{{consent_test_notice_html}}'
867 . EmailTemplateLayout::detailCard([
868 ['label' => 'Form', 'value' => '{{form_name}}'],
869 ['label' => 'Trip', 'value' => '{{trip_name}}'],
870 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
871 ['label' => 'Booking reference', 'value' => '{{booking_reference}}'],
872 ])
873 . '{{expiry_notice_html}}'
874 . $cta
875 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
876 . esc_html__('If the button does not work, copy this link into your browser:', 'yatra')
877 . '</p>'
878 . '<p style="margin:8px 0 0;font-size:13px;word-break:break-all;"><a href="{{consent_link}}" style="color:#0d9488;">{{consent_link}}</a></p>';
879
880 return EmailTemplateLayout::customer(
881 '📝',
882 'Consent required',
883 $inner,
884 '{{site_name}}',
885 'Trip consent'
886 );
887 }
888
889 private static function htmlCustomerEmailVerification(): string
890 {
891 $cta = '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0;"><tr>'
892 . '<td style="border-radius:10px;background:#0d9488;">'
893 . '<a href="{{verification_link}}" style="display:inline-block;padding:14px 28px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
894 . esc_html__('Verify email address', 'yatra')
895 . '</a></td></tr></table>';
896
897 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_first_name}},</p>'
898 . '<p style="margin:0 0 20px;color:#475569;">{{intro_paragraph}}</p>'
899 . $cta
900 . '<div style="margin:20px 0 0;padding:12px 16px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;font-size:14px;color:#475569;">'
901 . '{{expiry_notice_html}}'
902 . '</div>'
903 . '<p style="margin:24px 0 0;font-size:14px;color:#64748b;">{{footer_note}}</p>'
904 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
905 . esc_html__('If the button does not work, copy this link into your browser:', 'yatra')
906 . '</p>'
907 . '<p style="margin:8px 0 0;font-size:13px;word-break:break-all;"><a href="{{verification_link}}" style="color:#0d9488;">{{verification_link}}</a></p>';
908
909 return EmailTemplateLayout::customer(
910 '✉️',
911 __('Verify your email', 'yatra'),
912 $inner,
913 '{{site_name}}',
914 __('Account verification', 'yatra')
915 );
916 }
917
918 private static function htmlPaymentReminder(): string
919 {
920 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
921 . '<p style="margin:0 0 20px;color:#475569;">'
922 . esc_html__('This is a gentle nudge about your booking', 'yatra')
923 . ' <strong>{{booking_reference}}</strong> '
924 . esc_html__('for', 'yatra')
925 . ' <strong>{{trip_name}}</strong>. '
926 . esc_html__('If a balance remains, please settle it before your travel date ({{travel_date}}).', 'yatra')
927 . '</p>'
928 . EmailTemplateLayout::detailCard([
929 ['label' => 'Amount due', 'value' => '{{amount_due_formatted}}'],
930 ['label' => 'Trip', 'value' => '{{trip_name}}'],
931 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
932 ]);
933
934 return EmailTemplateLayout::customer(
935 '💳',
936 'Payment reminder',
937 $inner,
938 '{{site_name}}',
939 'Payment reminder'
940 );
941 }
942
943 private static function htmlEnquiryCustomer(): string
944 {
945 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
946 . '<p style="margin:0 0 20px;color:#475569;">'
947 . esc_html__('Thanks for reaching out about', 'yatra')
948 . ' <strong style="color:#0f172a;">{{trip_name}}</strong>. '
949 . esc_html__('We’ve received your message and our team will reply shortly.', 'yatra')
950 . '</p>'
951 . '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#f0fdfa;border:1px solid #99f6e4;border-radius:12px;margin:8px 0 0;">'
952 . '<tr><td style="padding:16px 20px;font-size:14px;color:#115e59;">✉️ '
953 . esc_html__('Typical reply time: within one business day.', 'yatra')
954 . '</td></tr></table>';
955
956 return EmailTemplateLayout::customer(
957 '✉️',
958 'Message received',
959 $inner,
960 '{{site_name}}',
961 'Enquiry received'
962 );
963 }
964
965 private static function htmlEnquiryAdmin(): string
966 {
967 $inner = '<p style="margin:0 0 20px;color:#475569;">'
968 . esc_html__('Someone submitted an enquiry from your site. Follow up from the details below.', 'yatra')
969 . '</p>'
970 . EmailTemplateLayout::detailCard([
971 ['label' => 'Name', 'value' => '{{customer_name}}'],
972 ['label' => 'Email', 'value' => '{{customer_email}}'],
973 ['label' => 'Phone', 'value' => '{{customer_phone}}'],
974 ['label' => 'Trip', 'value' => '{{trip_name}}'],
975 ])
976 . '<p style="margin:20px 0 8px;font-size:12px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;">'
977 . esc_html__('Message', 'yatra')
978 . '</p>'
979 . '<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:18px 20px;color:#334155;line-height:1.65;">{{message}}</div>';
980
981 return EmailTemplateLayout::admin(
982 '💬',
983 'New enquiry',
984 $inner,
985 '{{site_name}} · ' . esc_html__('Admin', 'yatra')
986 );
987 }
988
989 private static function htmlEnquiryResponse(): string
990 {
991 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
992 . '<p style="margin:0 0 20px;color:#475569;">'
993 . esc_html__('Here’s our reply to your enquiry:', 'yatra')
994 . '</p>'
995 . '<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>'
996 . '<p style="margin:24px 0 0;font-size:14px;color:#64748b;">'
997 . esc_html__('Questions? Just reply to this email.', 'yatra')
998 . '</p>';
999
1000 return EmailTemplateLayout::customer(
1001 '💬',
1002 'Our reply',
1003 $inner,
1004 '{{site_name}}',
1005 'Enquiry response'
1006 );
1007 }
1008
1009 private static function htmlReviewRequest(): string
1010 {
1011 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
1012 . '<p style="margin:0 0 20px;color:#475569;">'
1013 . esc_html__('We hope', 'yatra')
1014 . ' <strong>{{trip_name}}</strong> '
1015 . esc_html__('was unforgettable. Would you share a quick review? It helps other travelers and our team.', 'yatra')
1016 . '</p>'
1017 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:8px 0 24px;"><tr>'
1018 . '<td style="border-radius:10px;background:#f59e0b;">'
1019 . '<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;">'
1020 . '' . esc_html__('Leave a review', 'yatra')
1021 . '</a></td></tr></table>'
1022 . '<p style="margin:0;font-size:13px;color:#94a3b8;">'
1023 . esc_html__('Takes about a minute — thank you!', 'yatra')
1024 . '</p>';
1025
1026 return EmailTemplateLayout::customer(
1027 '',
1028 'How was your trip?',
1029 $inner,
1030 '{{site_name}}',
1031 'Review request'
1032 );
1033 }
1034
1035 private static function htmlBookingExpiredCustomer(): string
1036 {
1037 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
1038 . '<p style="margin:0 0 20px;color:#475569;">'
1039 . esc_html__('Your booking was cancelled automatically because payment was not received in time.', 'yatra')
1040 . '</p>'
1041 . EmailTemplateLayout::detailCard([
1042 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
1043 ['label' => 'Trip', 'value' => '{{trip_name}}'],
1044 ['label' => 'Travel date', 'value' => '{{travel_date}}'],
1045 ['label' => 'Policy', 'value' => '{{expiry_policy_note}}'],
1046 ])
1047 . '<p style="margin:24px 0 0;"><a href="{{trip_url}}" style="color:#0d9488;font-weight:600;text-decoration:none;">'
1048 . esc_html__('Browse trips again →', 'yatra')
1049 . '</a></p>';
1050
1051 return EmailTemplateLayout::customer(
1052 '⏱️',
1053 __('Booking expired', 'yatra'),
1054 $inner,
1055 '{{site_name}}',
1056 __('Booking expired', 'yatra')
1057 );
1058 }
1059
1060 private static function htmlAdminBookingExpired(): string
1061 {
1062 $inner = '<p style="margin:0 0 20px;color:#475569;">'
1063 . esc_html__('A booking was cancelled automatically due to non-payment (expiry policy).', 'yatra')
1064 . '</p>'
1065 . EmailTemplateLayout::detailCard([
1066 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
1067 ['label' => 'Booking ID', 'value' => '{{booking_id}}'],
1068 ['label' => 'Customer', 'value' => '{{customer_name}}'],
1069 ['label' => 'Email', 'value' => '{{customer_email}}'],
1070 ['label' => 'Trip', 'value' => '{{trip_name}}'],
1071 ])
1072 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
1073 . '<td style="border-radius:10px;background:#2563eb;">'
1074 . '<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;">'
1075 . esc_html__('Open in Yatra admin', 'yatra')
1076 . '</a></td></tr></table>';
1077
1078 return EmailTemplateLayout::admin(
1079 '⏱️',
1080 __('Booking expired', 'yatra'),
1081 $inner,
1082 '{{site_name}} · ' . esc_html__('Admin', 'yatra')
1083 );
1084 }
1085
1086 private static function htmlScheduledPaymentReminder(): string
1087 {
1088 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_first_name}},</p>'
1089 . '<p style="margin:0 0 20px;color:#475569;">'
1090 . esc_html__('This is a reminder that a scheduled payment is coming up for your booking.', 'yatra')
1091 . '</p>'
1092 . EmailTemplateLayout::detailCard([
1093 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
1094 ['label' => 'Amount', 'value' => '{{scheduled_amount_formatted}}'],
1095 ['label' => 'Scheduled date', 'value' => '{{scheduled_date_formatted}}'],
1096 ['label' => 'Type', 'value' => '{{payment_type_label}}'],
1097 ])
1098 . '<p style="margin:24px 0 0;font-size:14px;color:#64748b;">'
1099 . esc_html__('If you need to update your payment method, contact us before the charge date.', 'yatra')
1100 . '</p>';
1101
1102 return EmailTemplateLayout::customer(
1103 '💳',
1104 __('Upcoming payment', 'yatra'),
1105 $inner,
1106 '{{site_name}}',
1107 __('Scheduled payment reminder', 'yatra')
1108 );
1109 }
1110
1111 private static function htmlScheduledPaymentSucceeded(): string
1112 {
1113 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_first_name}},</p>'
1114 . '<p style="margin:0 0 20px;color:#475569;">'
1115 . esc_html__('Your scheduled payment was processed successfully.', 'yatra')
1116 . '</p>'
1117 . EmailTemplateLayout::detailCard([
1118 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
1119 ['label' => 'Amount charged', 'value' => '{{scheduled_amount_formatted}}'],
1120 ['label' => 'Type', 'value' => '{{payment_type_label}}'],
1121 ['label' => 'Balance due now', 'value' => '{{balance_after_formatted}}'],
1122 ]);
1123
1124 return EmailTemplateLayout::customer(
1125 '�
1126 ',
1127 __('Payment received', 'yatra'),
1128 $inner,
1129 '{{site_name}}',
1130 __('Scheduled payment', 'yatra')
1131 );
1132 }
1133
1134 private static function htmlScheduledPaymentFailed(): string
1135 {
1136 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_first_name}},</p>'
1137 . '<p style="margin:0 0 20px;color:#475569;">'
1138 . '{{failure_intro_html}}'
1139 . '</p>'
1140 . EmailTemplateLayout::detailCard([
1141 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
1142 ['label' => 'Amount', 'value' => '{{scheduled_amount_formatted}}'],
1143 ['label' => 'Details', 'value' => '{{failure_reason}}'],
1144 ])
1145 . '<p style="margin:24px 0 0;font-size:14px;color:#64748b;">{{failure_followup_html}}</p>';
1146
1147 return EmailTemplateLayout::customer(
1148 '⚠️',
1149 __('Payment issue', 'yatra'),
1150 $inner,
1151 '{{site_name}}',
1152 __('Scheduled payment', 'yatra')
1153 );
1154 }
1155
1156 private static function htmlAdminScheduledPaymentFailed(): string
1157 {
1158 $inner = '<p style="margin:0 0 20px;color:#475569;">'
1159 . esc_html__('A scheduled payment permanently failed after retries.', 'yatra')
1160 . '</p>'
1161 . EmailTemplateLayout::detailCard([
1162 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
1163 ['label' => 'Customer', 'value' => '{{customer_name}}'],
1164 ['label' => 'Email', 'value' => '{{customer_email}}'],
1165 ['label' => 'Amount', 'value' => '{{scheduled_amount_formatted}}'],
1166 ['label' => 'Error', 'value' => '{{failure_reason}}'],
1167 ])
1168 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0 0;"><tr>'
1169 . '<td style="border-radius:10px;background:#2563eb;">'
1170 . '<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;">'
1171 . esc_html__('Open in Yatra admin', 'yatra')
1172 . '</a></td></tr></table>';
1173
1174 return EmailTemplateLayout::admin(
1175 '⚠️',
1176 __('Scheduled payment failed', 'yatra'),
1177 $inner,
1178 '{{site_name}} · ' . esc_html__('Admin', 'yatra')
1179 );
1180 }
1181
1182 private static function htmlAbandonedBookingRecoveryBase(string $headline, string $subLabel): string
1183 {
1184 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
1185 . '<p style="margin:0 0 20px;color:#475569;">{{recovery_intro_html}}</p>'
1186 . EmailTemplateLayout::detailCard([
1187 ['label' => 'Trip', 'value' => '{{trip_name}}'],
1188 ['label' => 'Reminder', 'value' => '{{recovery_reminder_label}}'],
1189 ])
1190 . '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0;"><tr>'
1191 . '<td style="border-radius:10px;background:#0d9488;">'
1192 . '<a href="{{recovery_link}}" style="display:inline-block;padding:14px 28px;font-family:\'Segoe UI\',Roboto,Arial,sans-serif;font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;border-radius:10px;">'
1193 . esc_html__('Continue booking', 'yatra')
1194 . '</a></td></tr></table>'
1195 . '<p style="margin:20px 0 0;font-size:13px;color:#64748b;">'
1196 . esc_html__('If you did not start this booking, you can ignore this email.', 'yatra')
1197 . '</p>';
1198
1199 return EmailTemplateLayout::customer(
1200 '🛒',
1201 $headline,
1202 $inner,
1203 '{{site_name}}',
1204 $subLabel
1205 );
1206 }
1207
1208 private static function htmlAbandonedBookingRecoveryFirst(): string
1209 {
1210 return self::htmlAbandonedBookingRecoveryBase(
1211 __('Complete your booking', 'yatra'),
1212 __('Abandoned checkout · First reminder', 'yatra')
1213 );
1214 }
1215
1216 private static function htmlAbandonedBookingRecoverySecond(): string
1217 {
1218 return self::htmlAbandonedBookingRecoveryBase(
1219 __('Still interested?', 'yatra'),
1220 __('Abandoned checkout · Second reminder', 'yatra')
1221 );
1222 }
1223
1224 private static function htmlAbandonedBookingRecoveryFinal(): string
1225 {
1226 return self::htmlAbandonedBookingRecoveryBase(
1227 __('Final reminder', 'yatra'),
1228 __('Abandoned checkout · Final reminder', 'yatra')
1229 );
1230 }
1231
1232 public static function fallbackTransactionalBookingCompleted(array $v): string
1233 {
1234 return TransactionalEmailTemplateService::parseMergeTags(self::htmlTripCompleted(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1235 }
1236
1237 public static function fallbackTransactionalBookingExpiredCustomer(array $v): string
1238 {
1239 return TransactionalEmailTemplateService::parseMergeTags(self::htmlBookingExpiredCustomer(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1240 }
1241
1242 public static function fallbackAdminBookingExpired(array $v): string
1243 {
1244 return TransactionalEmailTemplateService::parseMergeTags(self::htmlAdminBookingExpired(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1245 }
1246
1247 public static function fallbackTransactionalScheduledPaymentReminder(array $v): string
1248 {
1249 return TransactionalEmailTemplateService::parseMergeTags(self::htmlScheduledPaymentReminder(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1250 }
1251
1252 public static function fallbackTransactionalScheduledPaymentSucceeded(array $v): string
1253 {
1254 return TransactionalEmailTemplateService::parseMergeTags(self::htmlScheduledPaymentSucceeded(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1255 }
1256
1257 public static function fallbackTransactionalScheduledPaymentFailed(array $v): string
1258 {
1259 return TransactionalEmailTemplateService::parseMergeTags(self::htmlScheduledPaymentFailed(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1260 }
1261
1262 public static function fallbackAdminScheduledPaymentFailed(array $v): string
1263 {
1264 return TransactionalEmailTemplateService::parseMergeTags(self::htmlAdminScheduledPaymentFailed(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1265 }
1266
1267 public static function fallbackTransactionalEnquiryAdmin(array $v): string
1268 {
1269 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryAdmin(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1270 }
1271
1272 public static function fallbackTransactionalEnquiryReceived(array $v): string
1273 {
1274 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryCustomer(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1275 }
1276
1277 public static function fallbackTransactionalEnquiryResponse(array $v): string
1278 {
1279 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryResponse(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1280 }
1281
1282 public static function fallbackTransactionalReviewRequest(array $v): string
1283 {
1284 return TransactionalEmailTemplateService::parseMergeTags(self::htmlReviewRequest(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1285 }
1286
1287 public static function fallbackTransactionalAbandonedBookingRecoveryFirst(array $v): string
1288 {
1289 return TransactionalEmailTemplateService::parseMergeTags(self::htmlAbandonedBookingRecoveryFirst(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1290 }
1291
1292 public static function fallbackTransactionalAbandonedBookingRecoverySecond(array $v): string
1293 {
1294 return TransactionalEmailTemplateService::parseMergeTags(self::htmlAbandonedBookingRecoverySecond(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1295 }
1296
1297 public static function fallbackTransactionalAbandonedBookingRecoveryFinal(array $v): string
1298 {
1299 return TransactionalEmailTemplateService::parseMergeTags(self::htmlAbandonedBookingRecoveryFinal(), TransactionalEmailTemplateService::mergeTemplateVariables($v));
1300 }
1301
1302 /**
1303 * Merge-tag variables for enquiry templates (core wp_mail path when Pro does not own the channel).
1304 *
1305 * @param object $enquiry Row from EnquiryRepository::findWithTrip()
1306 */
1307 private static function enquiryVariablesForTemplates(object $enquiry, string $responsePlain): array
1308 {
1309 return TransactionalEmailTemplateService::variablesFromEnquiry($enquiry, $responsePlain);
1310 }
1311
1312 /**
1313 * Full HTML body matching Pro/system enquiry_received (for free core sends).
1314 */
1315 public static function renderCoreEnquiryCustomerConfirmationHtml(object $enquiry): string
1316 {
1317 $vars = self::enquiryVariablesForTemplates($enquiry, '');
1318
1319 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryCustomer(), $vars);
1320 }
1321
1322 /**
1323 * Full HTML body matching Pro/system enquiry_admin.
1324 */
1325 public static function renderCoreEnquiryAdminNotificationHtml(object $enquiry): string
1326 {
1327 $vars = self::enquiryVariablesForTemplates($enquiry, '');
1328
1329 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryAdmin(), $vars);
1330 }
1331
1332 /**
1333 * Full HTML body matching Pro/system enquiry_response.
1334 */
1335 public static function renderCoreEnquiryResponseHtml(object $enquiry, string $response): string
1336 {
1337 $vars = self::enquiryVariablesForTemplates($enquiry, $response);
1338
1339 return TransactionalEmailTemplateService::parseMergeTags(self::htmlEnquiryResponse(), $vars);
1340 }
1341
1342 /**
1343 * Review reminder (cron): same shell as Pro review_request template.
1344 */
1345 public static function renderCoreReviewReminderHtml(string $customerName, string $tripName, string $reviewUrl): string
1346 {
1347 $vars = [
1348 'customer_name' => $customerName,
1349 'trip_name' => $tripName,
1350 'review_url' => esc_url($reviewUrl),
1351 ];
1352
1353 return TransactionalEmailTemplateService::parseMergeTags(self::htmlReviewRequest(), $vars);
1354 }
1355 }
1356