PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.5.25
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.5.25
2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 1.7.2 All 33 releases
fluent-booking / app / Services / EmailNotificationService.php

EmailNotificationService.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 1.5.25, at app/Services/EmailNotificationService.php

449 lines 16.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBooking\App\Services;
4
5 use FluentBooking\App\App;
6 use FluentBooking\App\Models\Booking;
7 use FluentBooking\App\Services\Libs\Emogrifier\Emogrifier;
8 use FluentBooking\Framework\Support\Arr;
9
10 class EmailNotificationService
11 {
12 /**
13 * @param \FluentBooking\App\Models\Booking $booking
14 * @param $email
15 * @param $emailTo
16 * @param $actionType
17 * @return bool|mixed
18 */
19 public static function emailOnBooked(Booking $booking, $email, $emailTo, $actionType = 'scheduled', $resending = false)
20 {
21 $emailSubject = EditorShortCodeParser::parse($email['subject'], $booking);
22 $emailBody = EditorShortCodeParser::parse($email['body'], $booking);
23
24 $globalSettings = Helper::getGlobalSettings();
25 $useHostName = Arr::get($globalSettings, 'emailing.use_host_name', 'no');
26 $useHostEmailOnReply = Arr::get($globalSettings, 'emailing.use_host_email_on_reply', 'no');
27 $attachIcsFile = Arr::get($globalSettings, 'emailing.attach_ics_on_confirmation', 'no');
28 $settingsFromName = Arr::get($globalSettings, 'emailing.from_name', '');
29 $settingsFromEmail = Arr::get($globalSettings, 'emailing.from_email', '');
30 $settingsReplyToName = Arr::get($globalSettings, 'emailing.reply_to_name', '');
31 $settingsReplyToEmail = Arr::get($globalSettings, 'emailing.reply_to_email', '');
32
33 $attachments = [];
34 if ($attachIcsFile == 'yes' && $actionType == 'scheduled' && !$resending) {
35 $attachments = self::prepareAttachments($booking);
36 }
37
38 $guestAddress = self::getGuestAddress($booking);
39
40 $authors = $booking->getHostsDetails(false);
41
42 if ($emailTo == 'guest') {
43 $authors = [$authors[0]];
44 }
45
46 $to = [];
47 $from = '';
48 $replyTo = '';
49 $result = false;
50
51 foreach ($authors as $author) {
52 $hostName = $author['name'] ?? '';
53 $hostAddress = $author['email'];
54
55 $settingsFromEmail = $settingsFromEmail ?: $author['email'];
56 $settingsReplyToEmail = $settingsReplyToEmail ?: $author['email'];
57
58 if ('guest' == $emailTo) {
59 $to[] = $guestAddress;
60 $replyName = $useHostName == 'yes' ? $hostName : $settingsReplyToName;
61 $fromName = $useHostName == 'yes' ? $hostName : $settingsFromName;
62
63 $replyToEmail = $useHostEmailOnReply == 'yes' ? $author['email'] : $settingsReplyToEmail;
64 $replyFromEmail = $useHostEmailOnReply == 'yes' ? $replyToEmail : $settingsFromEmail;
65
66 $replyTo = sprintf('%1s <%2s>', $replyName, $replyToEmail);
67 $from = sprintf('%1s <%2s>', $fromName, $replyFromEmail);
68 } else {
69 $to[] = $hostName ? sprintf('%1$s <%2$s>', $hostName, $hostAddress) : $hostAddress;
70 }
71 }
72
73 $to = implode(', ', array_unique($to));
74
75 if ('guest' != $emailTo) {
76 $replyTo = sprintf('%1s <%2s>', $settingsReplyToName, $settingsReplyToEmail ?: $settingsFromEmail);
77 $from = sprintf('%1s <%2s>', $settingsFromName, $settingsFromEmail);
78 }
79
80 $headers = self::prepareEmailHeaders($replyTo, $from, $email);
81
82 $body = (string)App::make('view')->make('emails.template', [
83 'email_body' => $emailBody,
84 'email_footer' => self::getGlobalEmailFooter(),
85 ]);
86
87 $emogrifier = new Emogrifier($body);
88 $emogrifier->disableInvisibleNodeRemoval();
89 $body = (string)$emogrifier->emogrify();
90
91 $result = Mailer::send($to, $emailSubject, $body, $headers, $attachments);
92
93 if ($attachments) {
94 wp_delete_file($attachments[0]);
95 }
96
97 $status = $result ? 'sent' : 'sending failed';
98
99 $title = sprintf(__('Booking %s email %s to %s', 'fluent-booking'), $actionType, $status, $emailTo);
100
101 if ($result) {
102 self::addLog($title, $title, $booking->id);
103 } else {
104 self::addLog($title, $title, $booking->id, 'error');
105 }
106
107 return $result;
108 }
109
110 /**
111 * @param \FluentBooking\App\Models\Booking $booking
112 * @param $email
113 * @param $emailTo
114 * @return bool|mixed
115 */
116 public static function reminderEmail(Booking $booking, $email, $emailTo)
117 {
118 $globalSettings = Helper::getGlobalSettings();
119 $useHostName = Arr::get($globalSettings, 'emailing.use_host_name', 'no');
120 $useHostEmailOnReply = Arr::get($globalSettings, 'emailing.use_host_email_on_reply', 'no');
121 $settingsFromName = Arr::get($globalSettings, 'emailing.from_name', '');
122 $settingsFromEmail = Arr::get($globalSettings, 'emailing.from_email', '');
123 $settingsReplyToName = Arr::get($globalSettings, 'emailing.reply_to_name', '');
124 $settingsReplyToEmail = Arr::get($globalSettings, 'emailing.reply_to_email', '');
125
126 $guestAddress = self::getGuestAddress($booking);
127
128 $authors = $booking->getHostsDetails(false);
129
130 if ($emailTo == 'guest') {
131 $authors = [$authors[0]];
132 }
133
134 $to = [];
135 $from = '';
136 $replyTo = '';
137 $result = false;
138
139 foreach ($authors as $author) {
140 $hostAddress = $author['email'];
141 $hostName = $author['name'] ?? '';
142
143 $settingsFromEmail = $settingsFromEmail ?: $author['email'];
144 $settingsReplyToEmail = $settingsReplyToEmail ?: $author['email'];
145
146 if ('guest' == $emailTo) {
147 $to[] = $guestAddress;
148 $replyName = $useHostName == 'yes' ? $hostName : $settingsReplyToName;
149 $fromName = $useHostName == 'yes' ? $hostName : $settingsFromName;
150
151 $replyToEmail = $useHostEmailOnReply == 'yes' ? $author['email'] : $settingsReplyToEmail;
152 $fromEmail = $useHostEmailOnReply == 'yes' ? $replyToEmail : $settingsFromEmail;
153
154 $replyTo = sprintf('%1$s <%2$s>', $replyName, $replyToEmail);
155 $from = sprintf('%1$s <%2$s>', $fromName, $fromEmail);
156 } else {
157 $to[] = $hostName ? sprintf('%1$s <%2$s>', $hostName, $hostAddress) : $hostAddress;
158 }
159 }
160
161 $to = implode(', ', array_unique($to));
162
163 if ('guest' != $emailTo) {
164 $replyTo = sprintf('%1s <%2s>', $settingsReplyToName, $settingsReplyToEmail ?: $settingsFromEmail);
165 $from = sprintf('%1s <%2s>', $settingsFromName, $settingsFromEmail);
166 }
167
168 $headers = self::prepareEmailHeaders($replyTo, $from, $email);
169
170 $subject = EditorShortCodeParser::parse($email['subject'], $booking);
171 $html = EditorShortCodeParser::parse($email['body'], $booking);
172
173 $body = (string)App::make('view')->make('emails.template', [
174 'email_body' => $html,
175 'email_footer' => self::getGlobalEmailFooter()
176 ]);
177
178 $emogrifier = new Emogrifier($body);
179 $emogrifier->disableInvisibleNodeRemoval();
180 $body = (string)$emogrifier->emogrify();
181
182 $result = Mailer::send($to, $subject, $body, $headers);
183
184 if (!$result) {
185 return false;
186 }
187
188 $title = __('Reminder Email Sent', 'fluent-booking');
189 $description = sprintf(__('Reminder email sent to %s.', 'fluent-booking'), $emailTo);
190 self::addLog($title, $description, $booking->id);
191
192 return true;
193 }
194
195 /**
196 * @param \FluentBooking\App\Models\Booking $booking
197 * @param $email
198 * @param $emailTo
199 * @param $actionType
200 * @return bool|mixed
201 */
202 public static function bookingCancelOrRejectEmail(Booking $booking, $email, $emailTo, $actionType = 'cancel')
203 {
204 $globalSettings = Helper::getGlobalSettings();
205 $useHostName = Arr::get($globalSettings, 'emailing.use_host_name', 'no');
206 $useHostEmailOnReply = Arr::get($globalSettings, 'emailing.use_host_email_on_reply', 'no');
207 $settingsFromName = Arr::get($globalSettings, 'emailing.from_name', '');
208 $settingsFromEmail = Arr::get($globalSettings, 'emailing.from_email', '');
209 $settingsReplyToName = Arr::get($globalSettings, 'emailing.reply_to_name', '');
210 $settingsReplyToEmail = Arr::get($globalSettings, 'emailing.reply_to_email', '');
211
212 $guestAddress = self::getGuestAddress($booking);
213
214 $authors = $booking->getHostsDetails(false);
215
216 if ($emailTo == 'guest') {
217 $authors = [$authors[0]];
218 }
219
220 $to = [];
221 $from = '';
222 $replyTo = '';
223 $result = false;
224
225 foreach ($authors as $author) {
226 $hostAddress = $author['email'];
227 $hostName = $author['name'] ?? '';
228
229 $settingsFromEmail = $settingsFromEmail ?: $author['email'];
230 $settingsReplyToEmail = $settingsReplyToEmail ?: $author['email'];
231
232 if ('guest' == $emailTo) {
233 $to[] = $guestAddress;
234 $replyName = $useHostName == 'yes' ? $hostName : $settingsReplyToName;
235 $fromName = $useHostName == 'yes' ? $hostName : $settingsFromName;
236
237 $replyToEmail = $useHostEmailOnReply == 'yes' ? $author['email'] : $settingsReplyToEmail;
238 $replyFromEmail = $useHostEmailOnReply == 'yes' ? $replyToEmail : $settingsFromEmail;
239
240 $replyTo = sprintf('%1s <%2s>', $replyName, $replyToEmail);
241 $from = sprintf('%1s <%2s>', $fromName, $replyFromEmail);
242 } else {
243 $to[] = $hostName ? sprintf('%1s <%2s>', $hostName, $hostAddress) : $hostAddress;
244 }
245 }
246
247 $to = implode(', ', array_unique($to));
248
249 if ('guest' != $emailTo) {
250 $replyTo = sprintf('%1s <%2s>', $settingsReplyToName, $settingsReplyToEmail ?: $settingsFromEmail);
251 $from = sprintf('%1s <%2s>', $settingsFromName, $settingsFromEmail);
252 }
253
254 $headers = self::prepareEmailHeaders($replyTo, $from, $email);
255
256 $subject = EditorShortCodeParser::parse($email['subject'], $booking);
257 $html = EditorShortCodeParser::parse($email['body'], $booking);
258
259 $body = (string)App::make('view')->make('emails.template', [
260 'email_body' => $html,
261 'email_footer' => self::getGlobalEmailFooter()
262 ]);
263
264 $emogrifier = new Emogrifier($body);
265 $emogrifier->disableInvisibleNodeRemoval();
266 $body = (string)$emogrifier->emogrify();
267
268 $result = Mailer::send($to, $subject, $body, $headers);
269
270 $actionType = $actionType == 'reject' ? __('Rejection', 'fluent-booking') : __('Cancellation', 'fluent-booking');
271
272 $status = $result ? 'sent' : 'sending failed';
273
274 $title = sprintf(__('%s email %s to %s', 'fluent-booking'), $actionType, $status, $emailTo);
275
276 if ($result) {
277 self::addLog($title, $title, $booking->id);
278 } else {
279 self::addLog($title, $title, $booking->id, 'error');
280 }
281
282 return $result;
283 }
284
285 /**
286 * @param \FluentBooking\App\Models\Booking $booking
287 * @param $email
288 * @param $emailTo
289 * @return bool|mixed
290 */
291 public static function bookingRescheduledEmail(Booking $booking, $email, $emailTo)
292 {
293 $globalSettings = Helper::getGlobalSettings();
294 $useHostName = Arr::get($globalSettings, 'emailing.use_host_name', 'no');
295 $useHostEmailOnReply = Arr::get($globalSettings, 'emailing.use_host_email_on_reply', 'no');
296 $attachIcsFile = Arr::get($globalSettings, 'emailing.attach_ics_on_confirmation', 'no');
297 $settingsFromName = Arr::get($globalSettings, 'emailing.from_name', '');
298 $settingsFromEmail = Arr::get($globalSettings, 'emailing.from_email', '');
299 $settingsReplyToName = Arr::get($globalSettings, 'emailing.reply_to_name', '');
300 $settingsReplyToEmail = Arr::get($globalSettings, 'emailing.reply_to_email', '');
301
302 $attachments = [];
303 if ($attachIcsFile == 'yes') {
304 $attachments = self::prepareAttachments($booking);
305 }
306
307 $guestAddress = self::getGuestAddress($booking);
308
309 $authors = $booking->getHostsDetails(false);
310
311 if ($emailTo == 'guest') {
312 $authors = [$authors[0]];
313 }
314
315 $to = [];
316 $from = '';
317 $replyTo = '';
318 $result = false;
319
320 foreach ($authors as $author) {
321 $hostAddress = $author['email'];
322 $hostName = $author['name'] ?? '';
323
324 $settingsFromEmail = $settingsFromEmail ?: $author['email'];
325 $settingsReplyToEmail = $settingsReplyToEmail ?: $author['email'];
326
327 if ('guest' == $emailTo) {
328 $to[] = $guestAddress;
329 $replyName = $useHostName == 'yes' ? $hostName : $settingsReplyToName;
330 $fromName = $useHostName == 'yes' ? $hostName : $settingsFromName;
331
332 $replyToEmail = $useHostEmailOnReply == 'yes' ? $author['email'] : $settingsReplyToEmail;
333 $replyFromEmail = $useHostEmailOnReply == 'yes' ? $replyToEmail : $settingsFromEmail;
334
335 $replyTo = sprintf('%1s <%2s>', $replyName, $replyToEmail);
336 $from = sprintf('%1s <%2s>', $fromName, $replyFromEmail);
337 } else {
338 $to[] = $hostName ? sprintf('%1$s <%2$s>', $hostName, $hostAddress) : $hostAddress;
339 }
340 }
341
342 $to = implode(', ', array_unique($to));
343
344 if ('guest' != $emailTo) {
345 $replyTo = sprintf('%1s <%2s>', $settingsReplyToName, $settingsReplyToEmail ?: $settingsFromEmail);
346 $from = sprintf('%1s <%2s>', $settingsFromName, $settingsFromEmail);
347 }
348
349 $headers = self::prepareEmailHeaders($replyTo, $from, $email);
350
351 $subject = EditorShortCodeParser::parse($email['subject'], $booking);
352 $html = EditorShortCodeParser::parse($email['body'], $booking);
353
354 $body = (string)App::make('view')->make('emails.template', [
355 'email_body' => $html,
356 'email_footer' => self::getGlobalEmailFooter()
357 ]);
358
359 $emogrifier = new Emogrifier($body);
360 $emogrifier->disableInvisibleNodeRemoval();
361 $body = (string)$emogrifier->emogrify();
362
363 $result = Mailer::send($to, $subject, $body, $headers, $attachments);
364
365 if ($attachments) {
366 wp_delete_file($attachments[0]);
367 }
368
369 $status = $result ? 'sent' : 'sending failed';
370
371 $title = sprintf(__('Rescheduled booking email %s to $s', 'fluent-booking'), $status, $emailTo);
372
373 $description = sprintf(__('Rescheduling email %s to %s', 'fluent-booking'), $status, $emailTo);
374
375 if ($result) {
376 self::addLog($title, $description, $booking->id);
377 } else {
378 self::addLog($title, $description, $booking->id, 'error');
379 }
380
381 return $result;
382 }
383
384 private static function getGuestAddress($booking)
385 {
386 $guestAddress = $booking->email;
387 if ($booking->first_name && $booking->last_name) {
388 $guestAddress = sprintf('%1s %2s <%3s>', $booking->first_name, $booking->last_name, $booking->email);
389 } else if ($booking->first_name) {
390 $guestAddress = sprintf('%1s <%2s>', $booking->first_name, $booking->email);
391 }
392
393 if ($additionalGuests = $booking->getAdditionalGuests()) {
394 $guestAddress .= ', ' . implode(', ', $additionalGuests);
395 }
396 return $guestAddress;
397 }
398
399 private static function prepareEmailHeaders($replyTo, $from, $email)
400 {
401 $headers = [
402 'Reply-To: ' . $replyTo
403 ];
404
405 if ($from) {
406 $headers[] = 'From: ' . $from;
407 }
408
409 if (isset($email['recipients'])) {
410 $headers[] = 'bcc: ' . implode(', ', $email['recipients']);
411 }
412
413 return $headers;
414 }
415
416 private static function prepareAttachments($booking)
417 {
418 if (!WP_Filesystem()) {
419 return [];
420 }
421
422 $icsContent = BookingService::generateBookingICS($booking);
423
424 $filePath = wp_tempnam(null, 'event') . '.ics';
425
426 global $wp_filesystem;
427 $wp_filesystem->put_contents($filePath, $icsContent);
428 return [$filePath];
429 }
430
431 protected static function addLog($title, $description, $bookingId, $type = 'activity')
432 {
433 do_action('fluent_booking/log_booking_note', [
434 'title' => $title,
435 'description' => $description,
436 'booking_id' => $bookingId,
437 'type' => $type,
438 ]);
439 }
440
441 public static function getGlobalEmailFooter()
442 {
443 $globalSettings = Helper::getGlobalSettings();
444
445 return Arr::get($globalSettings, 'emailing.email_footer', '');
446 }
447
448 }
449