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 / package.php
vikappointments / site / helpers / libraries / mail / templates Last commit date
admin.php 5 days ago cancellation.php 5 days ago customer.php 5 days ago employee.php 5 days ago index.html 5 days ago packadmin.php 5 days ago package.php 5 days ago stock.php 5 days ago waitlist.php 5 days ago
package.php
425 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 * customers that purchase a package.
20 *
21 * @since 1.7
22 */
23 class VAPMailTemplatePackage implements VAPMailTemplate
24 {
25 /**
26 * The order object.
27 *
28 * @var VAPOrderPackage
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 $options['lang'] = null;
57 }
58
59 if (is_numeric($order))
60 {
61 // recover order details for the given language
62 $this->order = VAPOrderFactory::getPackages($order, $options['lang']);
63 }
64 else
65 {
66 // use order as provided
67 $this->order = $order;
68 }
69
70 if (!$options['lang'])
71 {
72 // use order lang tag in case it was not specified
73 $options['lang'] = $this->order->get('langtag', null);
74
75 if (!$options['lang'])
76 {
77 // the order is not assigned to any lang tag, use the current one
78 $options['lang'] = JFactory::getLanguage()->getTag();
79 }
80 }
81
82 // register options
83 $this->options = $options;
84
85 // load given language to translate template contents
86 VikAppointments::loadLanguage($this->options['lang'], JPATH_SITE);
87 }
88
89 /**
90 * Returns the code of the template before being parsed.
91 *
92 * @param string $file An optional template file to use. If not specified,
93 * the one set in configuration will be used.
94 *
95 * @return void
96 */
97 public function setFile($file)
98 {
99 // use specified template file
100 $this->templateFile = $file;
101
102 // check if a filename or a path was passed
103 if ($file && !is_file($file))
104 {
105 // make sure we have a valid file path
106 $this->templateFile = VAPHELPERS . DIRECTORY_SEPARATOR . 'mail_tmpls' . DIRECTORY_SEPARATOR . $file;
107 }
108 }
109
110 /**
111 * Returns the code of the template before being parsed.
112 *
113 * @return string
114 */
115 public function getTemplate()
116 {
117 // copy order details in a local variable for being used directly
118 // within the template file
119 $order = $this->order;
120
121 if ($this->templateFile)
122 {
123 // use specified template file
124 $file = $this->templateFile;
125 }
126 else
127 {
128 // get template file from configuration
129 $file = VAPFactory::getConfig()->get('packmailtmpl');
130
131 // build template path
132 $file = VAPHELPERS . DIRECTORY_SEPARATOR . 'mail_tmpls' . DIRECTORY_SEPARATOR . $file;
133 }
134
135 // make sure the file exists
136 if (!is_file($file))
137 {
138 // missing file, return empty string
139 return '';
140 }
141
142 // start output buffering
143 ob_start();
144 // include file to catch its contents
145 include $file;
146 // write template contents within a variable
147 $content = ob_get_contents();
148 // clear output buffer
149 ob_end_clean();
150
151 // free space
152 unset($order);
153
154 return $content;
155 }
156
157 /**
158 * Fetches the subject to be used in the e-mail.
159 *
160 * @return string
161 */
162 public function getSubject()
163 {
164 // get company name
165 $fromname = VAPFactory::getConfig()->getString('agencyname');
166
167 // fetch subject
168 $subject = JText::sprintf('VAPPACKAGESEMAILSUBJECT', $fromname);
169
170 // let plugins manipulate the subject for this e-mail template
171 $res = VAPMailFactory::letPluginsManipulateMail('package', 'subject', $subject, $this->order);
172
173 if ($res === false)
174 {
175 // a plugin prevented the e-mail sending
176 return '';
177 }
178
179 return $subject;
180 }
181
182 /**
183 * Parses the HTML of the template and returns it.
184 *
185 * @return string
186 */
187 public function getHtml()
188 {
189 $config = VAPFactory::getConfig();
190 $currency = VAPFactory::getCurrency();
191
192 // load template HTML
193 $tmpl = $this->getTemplate();
194
195 $payment_name = '';
196 $payment_notes = '';
197
198 // fetch payment name and notes
199 if ($this->order->payment)
200 {
201 // use payment name
202 $payment_name = $this->order->payment->name;
203
204 if ($this->order->statusRole == 'PENDING')
205 {
206 // show notes before purchase when waiting for the payment
207 $payment_notes = $this->order->payment->notes->beforePurchase;
208 }
209 else if ($this->order->statusRole == 'APPROVED')
210 {
211 // show notes after purchase when the order has been confirmed
212 $payment_notes = $this->order->payment->notes->afterPurchase;
213 }
214 }
215
216 // fetch coupon string
217 if ($this->order->coupon)
218 {
219 $coupon_str = $this->order->coupon->code;
220
221 if ($this->order->coupon->amount > 0)
222 {
223 $coupon_str .= ' : ';
224
225 if ($this->order->coupon->type == 1)
226 {
227 $coupon_str .= $this->order->coupon->amount . '%';
228 }
229 else
230 {
231 $coupon_str .= $currency->format($this->order->coupon->amount);
232 }
233 }
234 }
235 else
236 {
237 $coupon_str = '';
238 }
239
240 $vik = VAPApplication::getInstance();
241
242 // fetch order link HREF
243 $order_link_href = "index.php?option=com_vikappointments&view=packagesorder&ordnum={$this->order->id}&ordkey={$this->order->sid}";
244 $order_link_href = $vik->routeForExternalUse($order_link_href);
245
246 // fetch company logo image
247 $logo_str = $config->get('companylogo');
248
249 if ($logo_str && is_file(VAPMEDIA . DIRECTORY_SEPARATOR . $logo_str))
250 {
251 $logo_str = JHtml::fetch('vaphtml.media.display', $logo_str, [
252 'alt' => $config->get('agencyname'),
253 'small' => false,
254 'style' => 'max-width: 100%;',
255 ]);
256 }
257 else
258 {
259 $logo_str = '';
260 }
261
262 // get name chunks
263 $customerNameChunks = preg_split("/\s+/", (string) $this->order->purchaser_nominative);
264
265 // extract last name from the list
266 $customerLastName = array_pop($customerNameChunks);
267 // join remaining chunks into the first name
268 $customerFirstName = implode(' ', $customerNameChunks);
269
270 if (!$customerFirstName)
271 {
272 // only one name provided, use it as first name
273 $customerFirstName = $customerLastName;
274 $customerLastName = '';
275 }
276
277 // build placeholders lookup
278 $placeholders = array(
279 'logo' => $logo_str,
280 'company_name' => $config->get('agencyname'),
281 'order_number' => $this->order->id,
282 'order_key' => $this->order->sid,
283 'order_status' => JHtml::fetch('vaphtml.status.display', $this->order->status),
284 'order_payment' => $payment_name,
285 'order_payment_notes' => $payment_notes,
286 'order_total_cost' => $currency->format($this->order->totals->gross),
287 'order_total_net' => $currency->format($this->order->totals->net),
288 'order_total_tax' => $currency->format($this->order->totals->tax),
289 'order_total_discount' => $currency->format($this->order->totals->discount),
290 'order_coupon_code' => $coupon_str,
291 'order_link' => $order_link_href,
292 'user_name' => $this->order->author ? $this->order->author->name : '',
293 'user_username' => $this->order->author ? $this->order->author->username : '',
294 'user_email' => $this->order->author ? $this->order->author->email : '',
295 'customer_full_name' => $this->order->purchaser_nominative,
296 'customer_first_name' => $customerFirstName,
297 'customer_last_name' => $customerLastName,
298 );
299
300 // parse e-mail template placeholders
301 foreach ($placeholders as $tag => $value)
302 {
303 $tmpl = str_replace("{{$tag}}", $value, $tmpl);
304 }
305
306 // let plugins manipulate the content for this e-mail template
307 $res = VAPMailFactory::letPluginsManipulateMail('package', 'content', $tmpl, $this->order);
308
309 if ($res === false)
310 {
311 // a plugin prevented the e-mail sending
312 return '';
313 }
314
315 return $tmpl;
316 }
317
318 /**
319 * Sends the HTML contents via e-mail.
320 *
321 * @return boolean
322 */
323 public function send()
324 {
325 $config = VAPFactory::getConfig();
326
327 // get recipient from order detail
328 $recipient = $this->order->purchaser_mail;
329
330 if (!$recipient)
331 {
332 // missing recipient
333 return false;
334 }
335
336 // get sender e-mail address
337 $sendermail = VikAppointments::getSenderMail();
338 // get company name
339 $fromname = $config->getString('agencyname');
340
341 // fetch subject
342 $subject = $this->getSubject();
343
344 // parse e-mail template
345 $html = $this->getHtml();
346
347 if (empty($subject) || empty($html))
348 {
349 // do not send e-mail in case the subject or
350 // the content are empty
351 return false;
352 }
353
354 $attachments = array();
355
356 // let plugins manipulate the attachments for this e-mail template
357 $res = VAPMailFactory::letPluginsManipulateMail('package', 'attachment', $attachments, $this->order);
358
359 if ($res === false)
360 {
361 // a plugin prevented the e-mail sending
362 return false;
363 }
364
365 // send the e-mail notification
366 $sent = VAPApplication::getInstance()->sendMail(
367 $sendermail,
368 $fromname,
369 $recipient,
370 $this->getReplyTo(),
371 $subject,
372 $html,
373 array_keys($attachments)
374 );
375
376 // destroy any temporary attachment here
377 foreach ($attachments as $file => $keep)
378 {
379 // check if the file exists and it should be deleted
380 if (!$keep && is_file($file))
381 {
382 // permanently delete file
383 unlink($file);
384 }
385 }
386
387 return $sent;
388 }
389
390 /**
391 * Checks whether the notification should be sent.
392 *
393 * @return boolean
394 */
395 public function shouldSend()
396 {
397 // get list of statuses for which the notification should be sent
398 $list = VAPFactory::getConfig()->getArray('mailcustwhen');
399
400 // make sure the order status is contained within the list
401 return in_array($this->order->status, $list);
402 }
403
404 /**
405 * Helper function used to obtain the most suitable reply-to mail address.
406 *
407 * @return string|null
408 */
409 protected function getReplyTo()
410 {
411 if ($this->order->statusRole === 'APPROVED')
412 {
413 // use the first administrator e-mail as reply-to for confirmed orders
414 return VikAppointments::getAdminMail();
415 }
416
417 /**
418 * Use the reply-to address specified from the global configuration.
419 *
420 * @since 1.7.7
421 */
422 return VAPFactory::getConfig()->get('replytoemail', null);
423 }
424 }
425