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