PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
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
← All changes | app/Services/EmailTemplateDefaults.php +125 -4 3.0.10 → 3.0.16 View file →
@@ -16,13 +16,15 @@
16 16 * @return array<string, string>
17 17 */
18 18 public static function settingsOptionDefaults(): array
19 19 {
20 - return [
20 + $defaults = [
21 21 'email_tpl_booking_subject' => '✈️ [{{site_name}}] Booking update · {{booking_reference}}',
22 22 'email_tpl_booking_body' => self::htmlBookingCustomer(),
23 23 'email_tpl_payment_subject' => '✅ [{{site_name}}] Payment received · {{booking_reference}}',
24 24 'email_tpl_payment_body' => self::htmlPaymentCustomer(),
25 + 'email_tpl_partial_payment_subject' => '💳 [{{site_name}}] Part payment received · {{booking_reference}}',
26 + 'email_tpl_partial_payment_body' => self::htmlPartialPaymentCustomer(),
25 27 'email_tpl_cancellation_subject' => '📋 [{{site_name}}] Booking cancelled · {{booking_reference}}',
26 28 'email_tpl_cancellation_body' => self::htmlCancellationCustomer(),
27 29 'email_tpl_reminder_subject' => '🗓️ [{{site_name}}] Your trip is coming up · {{booking_reference}}',
28 30 'email_tpl_reminder_body' => self::htmlReminderCustomer(),
@@ -78,8 +80,26 @@
78 80 'email_tpl_abandoned_booking_recovery_second_body' => self::htmlAbandonedBookingRecoverySecond(),
79 81 'email_tpl_abandoned_booking_recovery_final_subject' => '⚠️ [{{site_name}}] Final reminder: complete your booking',
80 82 'email_tpl_abandoned_booking_recovery_final_body' => self::htmlAbandonedBookingRecoveryFinal(),
81 83 ];
84 +
85 + // Every template also gets an opt-in Bcc / Cc option, derived from its
86 + // own subject key so the two lists can never drift apart (and so a
87 + // template type added later picks them up for free). Empty by default:
88 + // no address configured means no copy is sent and nothing changes for
89 + // existing sites. Registered here because this array doubles as the
90 + // whitelist of settings the REST API will persist.
91 + foreach (array_keys($defaults) as $key) {
92 + if (substr($key, -8) !== '_subject') {
93 + continue;
94 + }
95 +
96 + $base = substr($key, 0, -8);
97 + $defaults[$base . '_bcc'] = '';
98 + $defaults[$base . '_cc'] = '';
99 + }
100 +
101 + return $defaults;
82 102 }
83 103
84 104 /**
85 105 * Full subject + body for Pro system templates (DB). Null = no bundled default for that key.
@@ -112,8 +132,12 @@
112 132 'booking_cancelled' => [
113 133 'subject' => '📋 Booking cancelled · {{booking_reference}}',
114 134 'body' => self::htmlCancellationCustomer(),
115 135 ],
136 + 'admin_booking_cancelled' => [
137 + 'subject' => '📋 Booking cancelled · {{booking_reference}} (#{{booking_id}})',
138 + 'body' => self::htmlAdminBookingCancelled(),
139 + ],
116 140 'booking_completed' => [
117 141 'subject' => '🌟 Thanks for traveling with us · {{booking_reference}}',
118 142 'body' => self::htmlTripCompleted(),
119 143 ],
@@ -120,8 +144,16 @@
120 144 'payment_received' => [
121 145 'subject' => '✅ Payment received · {{booking_reference}}',
122 146 'body' => self::htmlPaymentCustomer(),
123 147 ],
148 + 'admin_payment_received' => [
149 + 'subject' => '✅ Payment received · {{booking_reference}} (#{{booking_id}})',
150 + 'body' => self::htmlAdminPaymentReceived(),
151 + ],
152 + 'partial_payment_received' => [
153 + 'subject' => '💳 Part payment received · {{booking_reference}}',
154 + 'body' => self::htmlPartialPaymentCustomer(),
155 + ],
124 156 'payment_reminder' => [
125 157 'subject' => '💳 Payment reminder · {{booking_reference}}',
126 158 'body' => self::htmlPaymentReminder(),
127 159 ],
@@ -314,10 +346,61 @@
314 346 );
315 347 }
316 348
317 349 /**
350 + * Part-payment received — a balance is still outstanding.
351 + *
352 + * Wording differs from the full-payment email on purpose: it confirms what
353 + * was received AND states what is still owed, which is the whole reason this
354 + * template is separate.
355 + *
318 356 * @param array<string, string> $v
319 357 */
358 + public static function fallbackTransactionalPartialPayment(array $v): string
359 + {
360 + // Null-coalescing rather than `?:` so this renders cleanly even when a
361 + // caller passes a sparse variable set — this fallback runs on sites that
362 + // upgraded before the template's body option was seeded.
363 + $name = esc_html(
364 + ($v['customer_first_name'] ?? '') ?: ($v['customer_name'] ?? '') ?: __('Customer', 'yatra')
365 + );
366 + $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
367 + $rows = array_values(array_filter([
368 + ['label' => __('Booking reference', 'yatra'), 'value' => esc_html($v['booking_reference'] ?? '')],
369 + ['label' => __('Amount received', 'yatra'), 'value' => esc_html($v['payment_amount_formatted'] ?? '')],
370 + ['label' => __('Paid so far', 'yatra'), 'value' => esc_html($v['amount_paid_formatted'] ?? '')],
371 + ['label' => __('Balance remaining', 'yatra'), 'value' => esc_html($v['amount_due_formatted'] ?? '')],
372 + ['label' => __('Booking total', 'yatra'), 'value' => esc_html($v['total_amount_formatted'] ?? '')],
373 + ['label' => __('Method', 'yatra'), 'value' => esc_html($v['payment_method'] ?? '')],
374 + ['label' => __('Transaction ID', 'yatra'), 'value' => esc_html($v['transaction_id'] ?? '')],
375 + ], static function (array $row): bool {
376 + return $row['value'] !== '';
377 + }));
378 +
379 + $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">'
380 + . sprintf(
381 + /* translators: %s: customer name */
382 + esc_html__('Dear %s,', 'yatra'),
383 + $name
384 + )
385 + . '</p>'
386 + . '<p style="margin:0 0 8px;color:#475569;">'
387 + . esc_html__('Thank you — we’ve received your part payment. Your booking is not yet paid in full, so the remaining balance is shown below.', 'yatra')
388 + . '</p>'
389 + . EmailTemplateLayout::detailCard($rows);
390 +
391 + return EmailTemplateLayout::customer(
392 + '💳',
393 + __('Part payment received', 'yatra'),
394 + $inner,
395 + $site,
396 + __('Payment update', 'yatra')
397 + );
398 + }
399 +
400 + /**
401 + * @param array<string, string> $v
402 + */
320 403 public static function fallbackTransactionalCancellation(array $v): string
321 404 {
322 405 $name = esc_html($v['customer_first_name'] ?: $v['customer_name'] ?: __('Customer', 'yatra'));
323 406 $site = esc_html($v['site_name'] ?? get_bloginfo('name'));
@@ -883,8 +966,35 @@
883 966 'Payment received'
884 967 );
885 968 }
886 969
970 + /**
971 + * Editor pre-fill for the part-payment template ({{merge tags}} intact).
972 + */
973 + private static function htmlPartialPaymentCustomer(): string
974 + {
975 + $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Dear {{customer_name}},</p>'
976 + . '<p style="margin:0 0 20px;color:#475569;">'
977 + . esc_html__('Thank you — we’ve received your part payment. The remaining balance for your booking is shown below.', 'yatra')
978 + . '</p>'
979 + . EmailTemplateLayout::detailCard([
980 + ['label' => 'Booking reference', 'value' => '{{booking_reference}}'],
981 + ['label' => 'Amount received', 'value' => '{{payment_amount_formatted}}'],
982 + ['label' => 'Paid so far', 'value' => '{{amount_paid_formatted}}'],
983 + ['label' => 'Balance remaining', 'value' => '{{amount_due_formatted}}'],
984 + ['label' => 'Booking total', 'value' => '{{total_amount_formatted}}'],
985 + ['label' => 'Method', 'value' => '{{payment_method}}'],
986 + ]);
987 +
988 + return EmailTemplateLayout::customer(
989 + '💳',
990 + 'Part payment received',
991 + $inner,
992 + '{{site_name}}',
993 + 'Payment update'
994 + );
995 + }
996 +
887 997 private static function htmlCancellationCustomer(): string
888 998 {
889 999 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_name}},</p>'
890 1000 . '<p style="margin:0 0 20px;color:#475569;">'
@@ -1233,20 +1343,31 @@
1233 1343 }
1234 1344
1235 1345 private static function htmlScheduledPaymentReminder(): string
1236 1346 {
1347 + // "Pay your balance now" CTA. The href is the {{balance_payment_url}}
1348 + // merge tag (a secure, guest-accessible balance link supplied by Pro
1349 + // Scheduled Payments); it is built manually rather than via
1350 + // EmailTemplateLayout::button() because that esc_url()s the href, which
1351 + // would strip the merge-tag braces. Pro passes an already-escaped URL.
1352 + $cta = '<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:28px 0;"><tr>'
1353 + . '<td style="border-radius:10px;background:#0d9488;">'
1354 + . '<a href="{{balance_payment_url}}" 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;">'
1355 + . esc_html__('Pay your balance now', 'yatra') . '</a></td></tr></table>';
1356 +
1237 1357 $inner = '<p style="margin:0 0 16px;font-size:17px;color:#0f172a;">Hello {{customer_first_name}},</p>'
1238 1358 . '<p style="margin:0 0 20px;color:#475569;">'
1239 - . esc_html__('This is a reminder that a scheduled payment is coming up for your booking.', 'yatra')
1359 + . esc_html__('This is a reminder that the remaining balance for your booking is coming up.', 'yatra')
1240 1360 . '</p>'
1241 1361 . EmailTemplateLayout::detailCard([
1242 1362 ['label' => 'Reference', 'value' => '{{booking_reference}}'],
1243 1363 ['label' => 'Amount', 'value' => '{{scheduled_amount_formatted}}'],
1244 - ['label' => 'Scheduled date', 'value' => '{{scheduled_date_formatted}}'],
1364 + ['label' => 'Due date', 'value' => '{{scheduled_date_formatted}}'],
1245 1365 ['label' => 'Type', 'value' => '{{payment_type_label}}'],
1246 1366 ])
1367 + . $cta
1247 1368 . '<p style="margin:24px 0 0;font-size:14px;color:#64748b;">'
1248 - . esc_html__('If you need to update your payment method, contact us before the charge date.', 'yatra')
1369 + . esc_html__('If you have any questions about this payment, please contact us before the due date.', 'yatra')
1249 1370 . '</p>';
1250 1371
1251 1372 return EmailTemplateLayout::customer(
1252 1373 '💳',