1: | <?php
2: | namespace Opencart\Catalog\Controller\Mail;
3: | /**
4: | * Class Subscription
5: | *
6: | * @package Opencart\Catalog\Controller\Mail
7: | */
8: | class Subscription extends \Opencart\System\Engine\Controller {
9: | /**
10: | * @param string $route
11: | * @param array<int, mixed> $args
12: | * @param array<mixed> $output
13: | *
14: | * addHistory
15: | *
16: | * @return void
17: | */
18: | public function index(string &$route, array &$args, &$output): void {
19: | if (isset($args[0])) {
20: | $subscription_id = $args[0];
21: | } else {
22: | $subscription_id = 0;
23: | }
24: |
25: | if (isset($args[1]['subscription'])) {
26: | $subscription = $args[1]['subscription'];
27: | } else {
28: | $subscription = [];
29: | }
30: |
31: | if (isset($args[2])) {
32: | $comment = $args[2];
33: | } else {
34: | $comment = '';
35: | }
36: |
37: | if (isset($args[3])) {
38: | $notify = $args[3];
39: | } else {
40: | $notify = '';
41: | }
42: | /*
43: | $subscription['order_product_id']
44: | $subscription['customer_id']
45: | $subscription['order_id']
46: | $subscription['subscription_plan_id']
47: | $subscription['customer_payment_id'],
48: | $subscription['name']
49: | $subscription['description']
50: | $subscription['trial_price']
51: | $subscription['trial_frequency']
52: | $subscription['trial_cycle']
53: | $subscription['trial_duration']
54: | $subscription['trial_remaining']
55: | $subscription['trial_status']
56: | $subscription['price']
57: | $subscription['frequency']
58: | $subscription['cycle']
59: | $subscription['duration']
60: | $subscription['remaining']
61: | $subscription['date_next']
62: | $subscription['status']
63: |
64: |
65: | if ($subscription['trial_duration'] && $subscription['trial_remaining']) {
66: | $date_next = date('Y-m-d', strtotime('+' . $subscription['trial_cycle'] . ' ' . $subscription['trial_frequency']));
67: | } elseif ($subscription['duration'] && $subscription['remaining']) {
68: | $date_next = date('Y-m-d', strtotime('+' . $subscription['cycle'] . ' ' . $subscription['frequency']));
69: | }
70: |
71: | // Subscription
72: | $this->load->model('account/subscription');
73: |
74: | $filter_data = [
75: | 'filter_subscription_id' => $subscription_id,
76: | 'filter_date_next' => $date_next,
77: | 'filter_subscription_status_id' => $this->config->get('config_subscription_active_status_id'),
78: | 'start' => 0,
79: | 'limit' => 1
80: | ];
81: |
82: | $subscriptions = $this->model_account_subscription->getSubscriptions($filter_data);
83: |
84: | if ($subscriptions) {
85: | $this->load->language('mail/subscription');
86: |
87: | foreach ($subscriptions as $value) {
88: | // Only match the latest order ID of the same customer ID
89: | // since new subscriptions cannot be re-added with the same
90: | // order ID; only as a new order ID added by an extension
91: | if ($value['customer_id'] == $subscription['customer_id'] && $value['order_id'] == $subscription['order_id']) {
92: | // Payment Methods
93: | $this->load->model('sale/subscription');
94: |
95: | $payment_method = $this->model_sale_subscription->getTotalSubscriptions(['filter_customer_id' => $value['customer_id']]);
96: |
97: | if ($payment_method) {
98: | // Subscription
99: | $this->load->model('checkout/subscription');
100: |
101: | $subscription_order_product = $this->model_checkout_subscription->getSubscriptionByOrderProductId($value['order_product_id']);
102: |
103: | if ($subscription_order_product) {
104: | // Orders
105: | $this->load->model('account/order');
106: |
107: | // Order Products
108: | $order_product = $this->model_account_order->getProduct($value['order_id'], $value['order_product_id']);
109: |
110: | if ($order_product && $order_product['order_product_id'] == $subscription['order_product_id']) {
111: | $products = $this->cart->getProducts();
112: |
113: | $description = '';
114: |
115: | foreach ($products as $product) {
116: | if ($product['product_id'] == $order_product['product_id']) {
117: |
118: |
119: | if ($product['subscription']['trial_status']) {
120: | $trial_price = $this->currency->format($this->tax->calculate($value['trial_price'], $product['tax_class_id'], $this->config->get('config_tax')), $this->config->get('config_currency'));
121: | $trial_cycle = $value['trial_cycle'];
122: | $trial_frequency = $this->language->get('text_' . $value['trial_frequency']);
123: | $trial_duration = $value['trial_duration'];
124: |
125: | $description .= sprintf($this->language->get('text_subscription_trial'), $trial_price, $trial_cycle, $trial_frequency, $trial_duration);
126: | }
127: |
128: | $price = $this->currency->format($this->tax->calculate($value['price'], $product['tax_class_id'], $this->config->get('config_tax')), $this->config->get('config_currency'));
129: | $cycle = $value['cycle'];
130: | $frequency = $this->language->get('text_' . $value['frequency']);
131: | $duration = $value['duration'];
132: |
133: | if ($duration) {
134: | $description .= sprintf($this->language->get('text_subscription_duration'), $price, $cycle, $frequency, $duration);
135: | } else {
136: | $description .= sprintf($this->language->get('text_subscription_cancel'), $price, $cycle, $frequency);
137: | }
138: | }
139: | }
140: |
141: |
142: | // Orders
143: | $this->load->model('checkout/order');
144: |
145: | $order_info = $this->model_checkout_order->getOrder($value['order_id']);
146: |
147: | if ($order_info) {
148: | // Stores
149: | $this->load->model('setting/store');
150: |
151: | // Settings
152: | $this->load->model('setting/setting');
153: |
154: | $store_info = $this->model_setting_store->getStore($order_info['store_id']);
155: |
156: | if ($store_info) {
157: | $store_logo = html_entity_decode($this->model_setting_setting->getValue('config_logo', $store_info['store_id']), ENT_QUOTES, 'UTF-8');
158: | $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8');
159: |
160: | $store_url = $store_info['url'];
161: | } else {
162: | $store_logo = html_entity_decode($this->config->get('config_logo'), ENT_QUOTES, 'UTF-8');
163: | $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8');
164: |
165: | $store_url = HTTP_SERVER;
166: | }
167: |
168: | // Subscription Status
169: | $subscription_status_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "subscription_status` WHERE `subscription_status_id` = '" . (int)$value['subscription_status_id'] . "' AND `language_id` = '" . (int)$order_info['language_id'] . "'");
170: |
171: | if ($subscription_status_query->num_rows) {
172: | $data['order_status'] = $subscription_status_query->row['name'];
173: | } else {
174: | $data['order_status'] = '';
175: | }
176: |
177: | // Languages
178: | $this->load->model('localisation/language');
179: |
180: | $language_info = $this->model_localisation_language->getLanguage($order_info['language_id']);
181: |
182: | // We need to compare both language IDs as they both need to match.
183: | if ($language_info) {
184: | $language_code = $language_info['code'];
185: | } else {
186: | $language_code = $this->config->get('config_language');
187: | }
188: |
189: | // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool.
190: | $this->load->language('default', 'mail', $language_code);
191: | $this->load->language('mail/order_add', 'mail', $language_code);
192: |
193: | // Add language vars to the template folder
194: | $results = $this->language->all('mail');
195: |
196: | foreach ($results as $key => $value) {
197: | $data[$key] = $value;
198: | }
199: |
200: | $subject = sprintf($this->language->get('mail_text_subject'), $store_name, $order_info['order_id']);
201: |
202: | // Image files
203: | $this->load->model('tool/image');
204: |
205: | if (is_file(DIR_IMAGE . $store_logo)) {
206: | $data['logo'] = $store_url . 'image/' . $store_logo;
207: | } else {
208: | $data['logo'] = '';
209: | }
210: |
211: | $data['title'] = sprintf($this->language->get('mail_text_subject'), $store_name, $order_info['order_id']);
212: |
213: | $data['text_greeting'] = sprintf($this->language->get('mail_text_greeting'), $order_info['store_name']);
214: |
215: | $data['store'] = $store_name;
216: | $data['store_url'] = $order_info['store_url'];
217: |
218: | $data['customer_id'] = $order_info['customer_id'];
219: | $data['link'] = $order_info['store_url'] . 'index.php?route=account/subscription.info&subscription_id=' . $subscription_id;
220: |
221: | $data['order_id'] = $order_info['order_id'];
222: | $data['date_added'] = date($this->language->get('date_format_short'), strtotime($value['date_added']));
223: | $data['payment_method'] = $order_info['payment_method'];
224: | $data['email'] = $order_info['email'];
225: | $data['telephone'] = $order_info['telephone'];
226: | $data['ip'] = $order_info['ip'];
227: |
228: | // Order Totals
229: | $data['totals'] = [];
230: |
231: | $order_totals = $this->model_checkout_order->getTotals($subscription['order_id']);
232: |
233: | foreach ($order_totals as $order_total) {
234: | $data['totals'][] = [
235: | 'title' => $order_total['title'],
236: | 'text' => $this->currency->format($order_total['value'], $order_info['currency_code'], $order_info['currency_value']),
237: | ];
238: | }
239: |
240: | // Subscription
241: | if ($comment && $notify) {
242: | $data['comment'] = nl2br($comment);
243: | } else {
244: | $data['comment'] = '';
245: | }
246: |
247: | $data['description'] = $value['description'];
248: |
249: | // Products
250: | $data['name'] = $order_product['name'];
251: | $data['quantity'] = $order_product['quantity'];
252: | $data['price'] = $this->currency->format($order_product['price'], $order_info['currency_code'], $order_info['currency_value']);
253: | $data['total'] = $this->currency->format($order_product['total'], $order_info['currency_code'], $order_info['currency_value']);
254: |
255: | $data['order'] = $this->url->link('account/order.info', 'order_id=' . $value['order_id']);
256: | $data['product'] = $this->url->link('product/product', 'product_id=' . $value['product_id']);
257: |
258: | // Settings
259: | $from = $this->model_setting_setting->getValue('config_email', $order_info['store_id']);
260: |
261: | if (!$from) {
262: | $from = $this->config->get('config_email');
263: | }
264: |
265: | if ($this->config->get('payment_' . $payment_info['code'] . '_status')) {
266: | $this->load->model('extension/payment/' . $payment_info['code']);
267: |
268: | // Promotion
269: | if (isset($this->{'model_extension_payment_' . $payment_info['code']}->promotion)) {
270: | $subscription_status_id = $this->{'model_extension_payment_' . $payment_info['code']}->promotion($value['subscription_id']);
271: |
272: | if ($store_info) {
273: | $config_subscription_active_status_id = $this->model_setting_setting->getValue('config_subscription_active_status_id', $store_info['store_id']);
274: | } else {
275: | $config_subscription_active_status_id = $this->config->get('config_subscription_active_status_id');
276: | }
277: |
278: | if ($config_subscription_active_status_id == $subscription_status_id) {
279: | $subscription_info = $this->model_account_subscription->getSubscription($value['subscription_id']);
280: |
281: | // Validate the latest subscription values with the ones edited
282: | // by promotional extensions
283: | if ($subscription_info && $subscription_info['status'] && $subscription_info['customer_id'] == $value['customer_id'] && $subscription_info['order_id'] == $value['order_id'] && $subscription_info['order_product_id'] == $value['order_product_id']) {
284: | $this->load->model('account/customer');
285: |
286: | $customer_info = $this->model_account_customer->getCustomer($subscription_info['customer_id']);
287: |
288: | $frequencies = [
289: | 'day',
290: | 'week',
291: | 'semi_month',
292: | 'month',
293: | 'year'
294: | ];
295: |
296: | // We need to validate frequencies in compliance of the admin subscription plans
297: | // as with the use of the APIs
298: | if ($customer_info && (int)$subscription_info['cycle'] >= 0 && $subscription_info['cycle'] == $value['cycle'] && in_array($subscription_info['frequency'], $frequencies)) {
299: | if ($subscription_info['frequency'] == 'semi_month') {
300: | $period = strtotime("2 weeks");
301: | } else {
302: | $period = strtotime($subscription_info['cycle'] . ' ' . $subscription_info['frequency']);
303: | }
304: |
305: | // New customer once the trial period has ended
306: | $customer_period = strtotime($customer_info['date_added']);
307: |
308: | $trial_period = 0;
309: | $validate_trial = 0;
310: |
311: | // Trial
312: | if ($subscription_info['trial_cycle'] && $subscription_info['trial_frequency'] && $subscription_info['trial_cycle'] == $value['trial_cycle'] && $subscription_info['trial_frequency'] == $value['trial_frequency']) {
313: | if ($subscription_info['trial_frequency'] == 'semi_month') {
314: | $trial_period = strtotime("2 weeks");
315: | } else {
316: | $trial_period = strtotime($subscription_info['trial_cycle'] . ' ' . $subscription_info['trial_frequency']);
317: | }
318: |
319: | $trial_period = ($trial_period - $customer_period);
320: | $validate_trial = round($trial_period / (60 * 60 * 24));
321: | }
322: |
323: | // Calculates the remaining days between the subscription
324: | // promotional period and the date added period
325: | $period = ($period - $customer_period);
326: |
327: | // Calculate remaining period of each features
328: | $period = round($period / (60 * 60 * 24));
329: |
330: | // Promotional features description must be identical
331: | // until the time period has exceeded. Therefore, the current
332: | // period must be matched as well
333: | if (($period == 0 && ($validate_trial > 0 || !$validate_trial)) && $value['description'] == $description && $subscription_info['subscription_plan_id'] == $value['subscription_plan_id']) {
334: | // Products
335: | $this->load->model('catalog/product');
336: |
337: | $product_subscription_info = $this->model_catalog_product->getSubscription($order_product['product_id'], $subscription_info['subscription_plan_id']);
338: |
339: | if ($product_subscription_info) {
340: | // For the next billing cycle
341: | $this->model_account_subscription->addTransaction($value['subscription_id'], $value['order_id'], $this->language->get('text_promotion'), $subscription_info['amount'], $subscription_info['type'], $subscription_info['payment_method'], $subscription_info['payment_code']);
342: | }
343: | }
344: | }
345: | }
346: | }
347: | }
348: | }
349: |
350: | // Mail
351: | if ($this->config->get('config_mail_engine')) {
352: | $mail_option = [
353: | 'parameter' => $this->config->get('config_mail_parameter'),
354: | 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'),
355: | 'smtp_username' => $this->config->get('config_mail_smtp_username'),
356: | 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'),
357: | 'smtp_port' => $this->config->get('config_mail_smtp_port'),
358: | 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout')
359: | ];
360: |
361: | $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option);
362: | $mail->setTo($order_info['email']);
363: | $mail->setFrom($from);
364: | $mail->setSender($store_name);
365: | $mail->setSubject($subject);
366: | $mail->setHtml($this->load->view('mail/subscription', $data));
367: | $mail->send();
368: | }
369: | }
370: | }
371: | }
372: | }
373: | }
374: | }
375: | }
376: | */
377: | }
378: |
379: | // catalog/model/checkout/order/addHistory/before
380: |
381: | /**
382: | * Alert
383: | *
384: | * @param string $route
385: | * @param array<int, mixed> $args
386: | *
387: | * @throws \Exception
388: | *
389: | * @return void
390: | */
391: | public function alert(string &$route, array &$args): void {
392: | if (isset($args[0])) {
393: | $order_id = $args[0];
394: | } else {
395: | $order_id = 0;
396: | }
397: |
398: | if (isset($args[1])) {
399: | $order_status_id = $args[1];
400: | } else {
401: | $order_status_id = 0;
402: | }
403: |
404: | if (isset($args[2])) {
405: | $comment = $args[2];
406: | } else {
407: | $comment = '';
408: | }
409: |
410: | if (isset($args[3])) {
411: | $notify = $args[3];
412: | } else {
413: | $notify = '';
414: | }
415: |
416: | $order_info = $this->model_checkout_order->getOrder($order_id);
417: |
418: | if ($order_info && !$order_info['order_status_id'] && $order_status_id && in_array('order', (array)$this->config->get('config_mail_alert'))) {
419: | $this->load->language('mail/order_alert');
420: |
421: | $subject = html_entity_decode(sprintf($this->language->get('text_subject'), $this->config->get('config_name'), $order_info['order_id']), ENT_QUOTES, 'UTF-8');
422: |
423: | $data['order_id'] = $order_info['order_id'];
424: | $data['date_added'] = date($this->language->get('date_format_short'), strtotime($order_info['date_added']));
425: |
426: | $order_status_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_status` WHERE `order_status_id` = '" . (int)$order_status_id . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'");
427: |
428: | if ($order_status_query->num_rows) {
429: | $data['order_status'] = $order_status_query->row['name'];
430: | } else {
431: | $data['order_status'] = '';
432: | }
433: |
434: | $this->load->model('tool/upload');
435: |
436: | $data['products'] = [];
437: |
438: | $order_products = $this->model_checkout_order->getProducts($order_id);
439: |
440: | foreach ($order_products as $order_product) {
441: | $option_data = [];
442: |
443: | $order_options = $this->model_checkout_order->getOptions($order_info['order_id'], $order_product['order_product_id']);
444: |
445: | foreach ($order_options as $order_option) {
446: | if ($order_option['type'] != 'file') {
447: | $value = $order_option['value'];
448: | } else {
449: | $upload_info = $this->model_tool_upload->getUploadByCode($order_option['value']);
450: |
451: | if ($upload_info) {
452: | $value = $upload_info['name'];
453: | } else {
454: | $value = '';
455: | }
456: | }
457: |
458: | $option_data[] = [
459: | 'name' => $order_option['name'],
460: | 'value' => (oc_strlen($value) > 20 ? oc_substr($value, 0, 20) . '..' : $value)
461: | ];
462: | }
463: |
464: | $description = '';
465: |
466: | $this->load->model('checkout/subscription');
467: |
468: | $subscription_info = $this->model_checkout_order->getSubscription($order_info['order_id'], $order_product['order_product_id']);
469: |
470: | if ($subscription_info) {
471: | if ($subscription_info['trial_status']) {
472: | $trial_price = $this->currency->format($subscription_info['trial_price'] + ($this->config->get('config_tax') ? $subscription_info['trial_tax'] : 0), $this->session->data['currency']);
473: | $trial_cycle = $subscription_info['trial_cycle'];
474: | $trial_frequency = $this->language->get('text_' . $subscription_info['trial_frequency']);
475: | $trial_duration = $subscription_info['trial_duration'];
476: |
477: | $description .= sprintf($this->language->get('text_subscription_trial'), $trial_price, $trial_cycle, $trial_frequency, $trial_duration);
478: | }
479: |
480: | $price = $this->currency->format($subscription_info['price'] + ($this->config->get('config_tax') ? $subscription_info['tax'] : 0), $this->session->data['currency']);
481: | $cycle = $subscription_info['cycle'];
482: | $frequency = $this->language->get('text_' . $subscription_info['frequency']);
483: | $duration = $subscription_info['duration'];
484: |
485: | if ($duration) {
486: | $description .= sprintf($this->language->get('text_subscription_duration'), $price, $cycle, $frequency, $duration);
487: | } else {
488: | $description .= sprintf($this->language->get('text_subscription_cancel'), $price, $cycle, $frequency);
489: | }
490: | }
491: |
492: | $data['products'][] = [
493: | 'name' => $order_product['name'],
494: | 'model' => $order_product['model'],
495: | 'quantity' => $order_product['quantity'],
496: | 'option' => $option_data,
497: | 'subscription' => $description,
498: | 'total' => html_entity_decode($this->currency->format($order_product['total'] + ($this->config->get('config_tax') ? $order_product['tax'] * $order_product['quantity'] : 0), $order_info['currency_code'], $order_info['currency_value']), ENT_NOQUOTES, 'UTF-8')
499: | ];
500: | }
501: |
502: | $data['vouchers'] = [];
503: |
504: | $order_vouchers = $this->model_checkout_order->getVouchers($order_id);
505: |
506: | foreach ($order_vouchers as $order_voucher) {
507: | $data['vouchers'][] = [
508: | 'description' => $order_voucher['description'],
509: | 'amount' => html_entity_decode($this->currency->format($order_voucher['amount'], $order_info['currency_code'], $order_info['currency_value']), ENT_NOQUOTES, 'UTF-8')
510: | ];
511: | }
512: |
513: | $data['totals'] = [];
514: |
515: | $order_totals = $this->model_checkout_order->getTotals($order_id);
516: |
517: | foreach ($order_totals as $order_total) {
518: | $data['totals'][] = [
519: | 'title' => $order_total['title'],
520: | 'value' => html_entity_decode($this->currency->format($order_total['value'], $order_info['currency_code'], $order_info['currency_value']), ENT_NOQUOTES, 'UTF-8')
521: | ];
522: | }
523: |
524: | $data['comment'] = nl2br($order_info['comment']);
525: |
526: | $data['store'] = html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8');
527: | $data['store_url'] = $order_info['store_url'];
528: |
529: | if ($this->config->get('config_mail_engine')) {
530: | $mail_option = [
531: | 'parameter' => $this->config->get('config_mail_parameter'),
532: | 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'),
533: | 'smtp_username' => $this->config->get('config_mail_smtp_username'),
534: | 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'),
535: | 'smtp_port' => $this->config->get('config_mail_smtp_port'),
536: | 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout')
537: | ];
538: |
539: | $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option);
540: | $mail->setTo($this->config->get('config_email'));
541: | $mail->setFrom($this->config->get('config_email'));
542: | $mail->setSender(html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8'));
543: | $mail->setSubject($subject);
544: | $mail->setHtml($this->load->view('mail/order_alert', $data));
545: | $mail->send();
546: |
547: | // Send to additional alert emails
548: | $emails = explode(',', $this->config->get('config_mail_alert_email'));
549: |
550: | foreach ($emails as $email) {
551: | if ($email && filter_var($email, FILTER_VALIDATE_EMAIL)) {
552: | $mail->setTo(trim($email));
553: | $mail->send();
554: | }
555: | }
556: | }
557: | }
558: | }
559: | }
560: |

OpenCart API API documentation generated by ApiGen dev-master