PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.7.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.7.0
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.7.0, at app/Services/EmailNotificationService.php

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