PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.21
VikAppointments Services Booking Calendar v1.2.21
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / site / helpers / libraries / mail / templates / employee.php
vikappointments / site / helpers / libraries / mail / templates Last commit date
admin.php 4 days ago cancellation.php 4 days ago customer.php 4 days ago employee.php 4 days ago index.html 4 days ago packadmin.php 4 days ago package.php 4 days ago stock.php 4 days ago waitlist.php 4 days ago
employee.php
499 lines
1 <?php
2 /**
3 * @package VikAppointments
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 VAPLoader::import('libraries.mail.template');
15 VAPLoader::import('libraries.order.factory');
16
17 /**
18 * Wrapper used to handle mail notifications for the
19 * employee after a purchase of an appointment.
20 *
21 * @since 1.7
22 */
23 class VAPMailTemplateEmployee implements VAPMailTemplate
24 {
25 /**
26 * The order object.
27 *
28 * @var VAPOrderAppointment
29 */
30 protected $order;
31
32 /**
33 * An optional template file to use.
34 *
35 * @var string
36 */
37 protected $templateFile;
38
39 /**
40 * An array of options.
41 *
42 * @var array
43 */
44 protected $options;
45
46 /**
47 * Class constructor.
48 *
49 * @param mixed $order Either the order ID or the order object.
50 * @param array $options An array of options.
51 */
52 public function __construct($order, array $options = array())
53 {
54 if (empty($options['lang']))
55 {
56 // always use default language in case it is not specified
57 $options['lang'] = VikAppointments::getDefaultLanguage();
58 }
59
60 if (is_numeric($order))
61 {
62 // recover order details for the given language
63 $this->order = VAPOrderFactory::getAppointments($order, $options['lang']);
64 }
65 else
66 {
67 // use order as provided
68 $this->order = $order;
69 }
70
71 if (!isset($options['id_employee']))
72 {
73 // extract employee ID from the first appointment
74 if ($this->order->appointments)
75 {
76 $options['id_employee'] = $this->order->appointments[0]->employee->id;
77 }
78 else
79 {
80 $options['id_employee'] = 0;
81 }
82 }
83
84 // now filter the appointments by employee
85 foreach ($this->order->appointments as $k => $app)
86 {
87 if ($app->employee->id != $options['id_employee'])
88 {
89 // subtract appointment totals from order totals
90 foreach ($app->totals as $tk => $tv)
91 {
92 if (isset($this->order->totals->{$tk}))
93 {
94 $this->order->totals->{$tk} -= $tv;
95 }
96 }
97
98 // remove appointment from the list
99 unset($this->order->appointments[$k]);
100 }
101 }
102
103 // back to linear keys
104 $this->order->appointments = array_values($this->order->appointments);
105
106 // register options
107 $this->options = $options;
108
109 // load given language to translate template contents
110 VikAppointments::loadLanguage($this->options['lang'], JPATH_SITE);
111 }
112
113 /**
114 * Returns the code of the template before being parsed.
115 *
116 * @param string $file An optional template file to use. If not specified,
117 * the one set in configuration will be used.
118 *
119 * @return void
120 */
121 public function setFile($file)
122 {
123 // use specified template file
124 $this->templateFile = $file;
125
126 // check if a filename or a path was passed
127 if ($file && !is_file($file))
128 {
129 // make sure we have a valid file path
130 $this->templateFile = VAPHELPERS . DIRECTORY_SEPARATOR . 'mail_tmpls' . DIRECTORY_SEPARATOR . $file;
131 }
132 }
133
134 /**
135 * Returns the code of the template before being parsed.
136 *
137 * @return string
138 */
139 public function getTemplate()
140 {
141 // copy order details in a local variable for being used directly
142 // within the template file
143 $order = $this->order;
144
145 if (!$this->templateFile)
146 {
147 // get template file from configuration
148 $file = VAPFactory::getConfig()->get('empmailtmpl');
149
150 // build template path
151 $this->templateFile = VAPHELPERS . DIRECTORY_SEPARATOR . 'mail_tmpls' . DIRECTORY_SEPARATOR . $file;
152 }
153
154 // make sure the file exists
155 if (!is_file($this->templateFile))
156 {
157 // missing file, return empty string
158 return '';
159 }
160
161 // start output buffering
162 ob_start();
163 // include file to catch its contents
164 include $this->templateFile;
165 // write template contents within a variable
166 $content = ob_get_contents();
167 // clear output buffer
168 ob_end_clean();
169
170 // free space
171 unset($order);
172
173 return $content;
174 }
175
176 /**
177 * Fetches the subject to be used in the e-mail.
178 *
179 * @return string
180 */
181 public function getSubject()
182 {
183 // get company name
184 $fromname = VAPFactory::getConfig()->getString('agencyname');
185
186 /**
187 * Fetch subject.
188 *
189 * @since 1.7.7 Added the possibility to use a custom subject.
190 */
191 $subject = !empty($this->options['subject']) ? $this->options['subject'] : 'VAPADMINEMAILSUBJECT';
192 $subject = JText::sprintf($subject, $fromname);
193
194 // let plugins manipulate the subject for this e-mail template
195 $res = VAPMailFactory::letPluginsManipulateMail('employee', 'subject', $subject, $this->order);
196
197 if ($res === false)
198 {
199 // a plugin prevented the e-mail sending
200 return '';
201 }
202
203 /**
204 * Parse e-mail subject to replace tags with the related order details.
205 *
206 * @since 1.6.6
207 */
208 VikAppointments::parseEmailSubject($subject, $this->order);
209
210 return $subject;
211 }
212
213 /**
214 * Parses the HTML of the template and returns it.
215 *
216 * @return string
217 */
218 public function getHtml()
219 {
220 $config = VAPFactory::getConfig();
221 $currency = VAPFactory::getCurrency();
222
223 // load template HTML
224 $tmpl = $this->getTemplate();
225
226 // fetch payment name
227 if ($this->order->payment)
228 {
229 // use payment name
230 $payment_name = $this->order->payment->name;
231 }
232 else
233 {
234 $payment_name = '';
235 }
236
237 // fetch coupon string
238 if ($this->order->coupon)
239 {
240 $coupon_str = $this->order->coupon->code;
241
242 if ($this->order->coupon->amount > 0)
243 {
244 $coupon_str .= ' : ';
245
246 if ($this->order->coupon->type == 1)
247 {
248 $coupon_str .= $this->order->coupon->amount . '%';
249 }
250 else
251 {
252 $coupon_str .= $currency->format($this->order->coupon->amount);
253 }
254 }
255 }
256 else
257 {
258 $coupon_str = '';
259 }
260
261 $vik = VAPApplication::getInstance();
262
263 // fetch order link HREF
264 $order_link_href = "index.php?option=com_vikappointments&view=order&ordnum={$this->order->id}&ordkey={$this->order->sid}";
265 $order_link_href = $vik->routeForExternalUse($order_link_href);
266
267 // fetch confirmation link HREF
268 $confirmation_link_href = "index.php?option=com_vikappointments&view=order&task=order.confirm&id={$this->order->id}&conf_key={$this->order->conf_key}";
269 $confirmation_link_href = $vik->routeForExternalUse($confirmation_link_href);
270
271 // fetch company logo image
272 $logo_str = $config->get('companylogo');
273
274 if ($logo_str && is_file(VAPMEDIA . DIRECTORY_SEPARATOR . $logo_str))
275 {
276 $logo_str = JHtml::fetch('vaphtml.media.display', $logo_str, [
277 'alt' => $config->get('agencyname'),
278 'small' => false,
279 'style' => 'max-width: 100%;',
280 ]);
281 }
282 else
283 {
284 $logo_str = '';
285 }
286
287 // get name chunks
288 $customerNameChunks = preg_split("/\s+/", (string) $this->order->purchaser_nominative);
289
290 // extract last name from the list
291 $customerLastName = array_pop($customerNameChunks);
292 // join remaining chunks into the first name
293 $customerFirstName = implode(' ', $customerNameChunks);
294
295 if (!$customerFirstName)
296 {
297 // only one name provided, use it as first name
298 $customerFirstName = $customerLastName;
299 $customerLastName = '';
300 }
301
302 // build placeholders lookup
303 $placeholders = array(
304 'logo' => $logo_str,
305 'company_name' => $config->get('agencyname'),
306 'order_status' => JHtml::fetch('vaphtml.status.display', $this->order->status),
307 'order_payment' => $payment_name,
308 'order_total_cost' => $currency->format($this->order->totals->gross),
309 'order_total_net' => $currency->format($this->order->totals->net),
310 'order_total_tax' => $currency->format($this->order->totals->tax),
311 'order_total_discount' => $currency->format($this->order->totals->discount),
312 'order_coupon_code' => $coupon_str,
313 'order_link' => $order_link_href,
314 'confirmation_link' => $confirmation_link_href,
315 'user_name' => $this->order->author ? $this->order->author->name : '',
316 'user_username' => $this->order->author ? $this->order->author->username : '',
317 'user_email' => $this->order->author ? $this->order->author->email : '',
318 'customer_full_name' => $this->order->purchaser_nominative,
319 'customer_first_name' => $customerFirstName,
320 'customer_last_name' => $customerLastName,
321 );
322
323 // get e-mail custom text model
324 $model = JModelVAP::getInstance('mailtext');
325
326 // set up options
327 $options = $this->options;
328 $options['file'] = $this->templateFile;
329
330 // parse e-mail template
331 $tmpl = $model->parseTemplate($tmpl, $this->order, $options);
332
333 // parse e-mail template placeholders
334 foreach ($placeholders as $tag => $value)
335 {
336 $tmpl = str_replace("{{$tag}}", $value, $tmpl);
337 }
338
339 // let plugins manipulate the content for this e-mail template
340 $res = VAPMailFactory::letPluginsManipulateMail('employee', 'content', $tmpl, $this->order);
341
342 if ($res === false)
343 {
344 // a plugin prevented the e-mail sending
345 return '';
346 }
347
348 return $tmpl;
349 }
350
351 /**
352 * Sends the HTML contents via e-mail.
353 *
354 * @return boolean
355 */
356 public function send()
357 {
358 if (!$this->order->appointments)
359 {
360 return false;
361 }
362
363 $config = VAPFactory::getConfig();
364
365 // get employee e-mail address
366 $recipient = $this->order->appointments[0]->employee->email;
367
368 if (!$recipient)
369 {
370 // missing recipient
371 return false;
372 }
373
374 // get sender e-mail address
375 $sendermail = VikAppointments::getSenderMail();
376 // get company name
377 $fromname = $config->getString('agencyname');
378
379 // fetch subject
380 $subject = $this->getSubject();
381
382 // parse e-mail template
383 $html = $this->getHtml();
384
385 if (empty($subject) || empty($html))
386 {
387 // do not send e-mail in case the subject or
388 // the content are empty
389 return false;
390 }
391
392 $attachments = array();
393
394 /**
395 * ICS attachment is included only for confirmed appointments.
396 *
397 * @since 1.7
398 */
399 if ($this->order->statusRole == 'APPROVED' && VikAppointments::getAttachmentPropertiesICS('employee'))
400 {
401 // get export ICS file
402 $file = VikAppointments::composeFileICS($this->order->id, $is_admin = true, $this->options['id_employee']);
403
404 if ($file)
405 {
406 // register into the list with status 0, meaning that
407 // the file is volatile and should be deleted
408 $attachments[$file] = 0;
409 }
410 }
411
412 /**
413 * CSV attachment is included only for confirmed appointments.
414 *
415 * @since 1.7
416 */
417 if ($this->order->statusRole == 'APPROVED' && VikAppointments::getAttachmentPropertiesCSV('employee'))
418 {
419 // get export CSV file
420 $file = VikAppointments::composeFileCSV($this->order->id, $is_admin = true, $this->options['id_employee']);
421
422 if ($file)
423 {
424 // register into the list with status 0, meaning that
425 // the file is volatile and should be deleted
426 $attachments[$file] = 0;
427 }
428 }
429
430 // iterate files uploaded by the customer
431 foreach (VikAppointments::includeMailAttachments($this->order) as $file)
432 {
433 // Register into the list with status 0, meaning that
434 // the file is volatile and should be deleted. This
435 // because we are attaching a copy of the original file,
436 // which owns a more readable file name.
437 $attachments[$file] = 0;
438 }
439
440 // let plugins manipulate the attachments for this e-mail template
441 $res = VAPMailFactory::letPluginsManipulateMail('employee', 'attachment', $attachments, $this->order);
442
443 $sent = false;
444
445 // make sure the plugin didn't prevent e-mail sending
446 if ($res !== false)
447 {
448 // send the e-mail notification
449 $sent = VAPApplication::getInstance()->sendMail(
450 $sendermail,
451 $fromname,
452 $recipient,
453 $this->order->purchaser_mail,
454 $subject,
455 $html,
456 array_keys($attachments)
457 );
458 }
459
460 // destroy any temporary attachment here
461 foreach ($attachments as $file => $keep)
462 {
463 // check if the file exists and it should be deleted
464 if (!$keep && is_file($file))
465 {
466 // permanently delete file
467 unlink($file);
468 }
469 }
470
471 return $sent;
472 }
473
474 /**
475 * Checks whether the notification should be sent.
476 *
477 * @return boolean
478 */
479 public function shouldSend()
480 {
481 if (!$this->order->appointments)
482 {
483 return false;
484 }
485
486 if (!$this->order->appointments[0]->employee->notify)
487 {
488 // the employee disabled the notifications
489 return false;
490 }
491
492 // get list of statuses for which the notification should be sent
493 $list = VAPFactory::getConfig()->getArray('mailempwhen');
494
495 // make sure the order status is contained within the list
496 return in_array($this->order->status, $list);
497 }
498 }
499