1: <?php
2: namespace Opencart\Catalog\Controller\Checkout;
3: /**
4: * Class Cart
5: *
6: * @package Opencart\Catalog\Controller\Checkout
7: */
8: class Cart extends \Opencart\System\Engine\Controller {
9: /**
10: * @return void
11: */
12: public function index(): void {
13: $this->load->language('checkout/cart');
14:
15: $this->document->setTitle($this->language->get('heading_title'));
16:
17: $data['breadcrumbs'] = [];
18:
19: $data['breadcrumbs'][] = [
20: 'text' => $this->language->get('text_home'),
21: 'href' => $this->url->link('common/home', 'language=' . $this->config->get('config_language'))
22: ];
23:
24: $data['breadcrumbs'][] = [
25: 'text' => $this->language->get('heading_title'),
26: 'href' => $this->url->link('checkout/cart', 'language=' . $this->config->get('config_language'))
27: ];
28:
29: if ($this->cart->hasProducts() || !empty($this->session->data['vouchers'])) {
30: if (!$this->cart->hasStock() && (!$this->config->get('config_stock_checkout') || $this->config->get('config_stock_warning'))) {
31: $data['error_warning'] = $this->language->get('error_stock');
32: } elseif (isset($this->session->data['error'])) {
33: $data['error_warning'] = $this->session->data['error'];
34:
35: unset($this->session->data['error']);
36: } else {
37: $data['error_warning'] = '';
38: }
39:
40: if ($this->config->get('config_customer_price') && !$this->customer->isLogged()) {
41: $data['attention'] = sprintf($this->language->get('text_login'), $this->url->link('account/login', 'language=' . $this->config->get('config_language')), $this->url->link('account/register', 'language=' . $this->config->get('config_language')));
42: } else {
43: $data['attention'] = '';
44: }
45:
46: if (isset($this->session->data['success'])) {
47: $data['success'] = $this->session->data['success'];
48:
49: unset($this->session->data['success']);
50: } else {
51: $data['success'] = '';
52: }
53:
54: if ($this->config->get('config_cart_weight')) {
55: $data['weight'] = $this->weight->format($this->cart->getWeight(), $this->config->get('config_weight_class_id'), $this->language->get('decimal_point'), $this->language->get('thousand_point'));
56: } else {
57: $data['weight'] = '';
58: }
59:
60: $data['list'] = $this->load->controller('checkout/cart.getList');
61:
62: $data['modules'] = [];
63:
64: $this->load->model('setting/extension');
65:
66: $extensions = $this->model_setting_extension->getExtensionsByType('total');
67:
68: foreach ($extensions as $extension) {
69: $result = $this->load->controller('extension/' . $extension['extension'] . '/total/' . $extension['code']);
70:
71: if (!$result instanceof \Exception) {
72: $data['modules'][] = $result;
73: }
74: }
75:
76: $data['language'] = $this->config->get('config_language');
77:
78: $data['continue'] = $this->url->link('common/home', 'language=' . $this->config->get('config_language'));
79: $data['checkout'] = $this->url->link('checkout/checkout', 'language=' . $this->config->get('config_language'));
80:
81: $data['column_left'] = $this->load->controller('common/column_left');
82: $data['column_right'] = $this->load->controller('common/column_right');
83: $data['content_top'] = $this->load->controller('common/content_top');
84: $data['content_bottom'] = $this->load->controller('common/content_bottom');
85: $data['footer'] = $this->load->controller('common/footer');
86: $data['header'] = $this->load->controller('common/header');
87:
88: $this->response->setOutput($this->load->view('checkout/cart', $data));
89: } else {
90: $data['text_error'] = $this->language->get('text_no_results');
91:
92: $data['continue'] = $this->url->link('common/home', 'language=' . $this->config->get('config_language'));
93:
94: $data['column_left'] = $this->load->controller('common/column_left');
95: $data['column_right'] = $this->load->controller('common/column_right');
96: $data['content_top'] = $this->load->controller('common/content_top');
97: $data['content_bottom'] = $this->load->controller('common/content_bottom');
98: $data['footer'] = $this->load->controller('common/footer');
99: $data['header'] = $this->load->controller('common/header');
100:
101: $this->response->setOutput($this->load->view('error/not_found', $data));
102: }
103: }
104:
105: /**
106: * List
107: *
108: * @return void
109: */
110: public function list(): void {
111: $this->load->language('checkout/cart');
112:
113: $this->response->setOutput($this->getList());
114: }
115:
116: /**
117: * Get List
118: *
119: * @return string
120: */
121: public function getList(): string {
122: $data['list'] = $this->url->link(' ', 'language=' . $this->config->get('config_language'));
123: $data['product_edit'] = $this->url->link('checkout/cart.edit', 'language=' . $this->config->get('config_language'));
124: $data['product_remove'] = $this->url->link('checkout/cart.remove', 'language=' . $this->config->get('config_language'));
125: $data['voucher_remove'] = $this->url->link('checkout/voucher.remove', 'language=' . $this->config->get('config_language'));
126:
127: // Display prices
128: if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
129: $price_status = true;
130: } else {
131: $price_status = false;
132: }
133:
134: $this->load->model('tool/image');
135: $this->load->model('tool/upload');
136:
137: $data['products'] = [];
138:
139: $this->load->model('checkout/cart');
140:
141: $products = $this->model_checkout_cart->getProducts();
142:
143: foreach ($products as $product) {
144: if (!$product['minimum']) {
145: $data['error_warning'] = sprintf($this->language->get('error_minimum'), $product['name'], $product['minimum']);
146: }
147:
148: if ($product['option']) {
149: foreach ($product['option'] as $key => $option) {
150: $product['option'][$key]['value'] = (oc_strlen($option['value']) > 20 ? oc_substr($option['value'], 0, 20) . '..' : $option['value']);
151: }
152: }
153:
154: $description = '';
155:
156: if ($product['subscription']) {
157: if ($product['subscription']['trial_status']) {
158: $trial_price = $this->currency->format($this->tax->calculate($product['subscription']['trial_price'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
159: $trial_cycle = $product['subscription']['trial_cycle'];
160: $trial_frequency = $this->language->get('text_' . $product['subscription']['trial_frequency']);
161: $trial_duration = $product['subscription']['trial_duration'];
162:
163: $description .= sprintf($this->language->get('text_subscription_trial'), $price_status ? $trial_price : '', $trial_cycle, $trial_frequency, $trial_duration);
164: }
165:
166: $price = $this->currency->format($this->tax->calculate($product['subscription']['price'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
167:
168: $cycle = $product['subscription']['cycle'];
169: $frequency = $this->language->get('text_' . $product['subscription']['frequency']);
170: $duration = $product['subscription']['duration'];
171:
172: if ($duration) {
173: $description .= sprintf($this->language->get('text_subscription_duration'), $price_status ? $price : '', $cycle, $frequency, $duration);
174: } else {
175: $description .= sprintf($this->language->get('text_subscription_cancel'), $price_status ? $price : '', $cycle, $frequency);
176: }
177: }
178:
179: $data['products'][] = [
180: 'cart_id' => $product['cart_id'],
181: 'thumb' => $product['image'],
182: 'name' => $product['name'],
183: 'model' => $product['model'],
184: 'option' => $product['option'],
185: 'subscription' => $description,
186: 'quantity' => $product['quantity'],
187: 'stock' => $product['stock'] ? true : !(!$this->config->get('config_stock_checkout') || $this->config->get('config_stock_warning')),
188: 'minimum' => $product['minimum'],
189: 'reward' => $product['reward'],
190: 'price' => $price_status ? $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']) : '',
191: 'total' => $price_status ? $this->currency->format($this->tax->calculate($product['total'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']) : '',
192: 'href' => $this->url->link('product/product', 'language=' . $this->config->get('config_language') . '&product_id=' . $product['product_id']),
193: 'remove' => $this->url->link('checkout/cart.remove', 'language=' . $this->config->get('config_language') . '&key=' . $product['cart_id'])
194: ];
195: }
196:
197: // Gift Voucher
198: $data['vouchers'] = [];
199:
200: $vouchers = $this->model_checkout_cart->getVouchers();
201:
202: foreach ($vouchers as $key => $voucher) {
203: $data['vouchers'][] = [
204: 'key' => $key,
205: 'description' => $voucher['description'],
206: 'amount' => $this->currency->format($voucher['amount'], $this->session->data['currency']),
207: 'remove' => $this->url->link('checkout/voucher.remove', 'language=' . $this->config->get('config_language') . '&key=' . $key)
208: ];
209: }
210:
211: $data['totals'] = [];
212:
213: $totals = [];
214: $taxes = $this->cart->getTaxes();
215: $total = 0;
216:
217: // Display prices
218: if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
219: ($this->model_checkout_cart->getTotals)($totals, $taxes, $total);
220:
221: foreach ($totals as $result) {
222: $data['totals'][] = [
223: 'title' => $result['title'],
224: 'text' => $price_status ? $this->currency->format($result['value'], $this->session->data['currency']) : ''
225: ];
226: }
227: }
228:
229: return $this->load->view('checkout/cart_list', $data);
230: }
231:
232: /**
233: * Add
234: *
235: * @return void
236: */
237: public function add(): void {
238: $this->load->language('checkout/cart');
239:
240: $json = [];
241:
242: if (isset($this->request->post['product_id'])) {
243: $product_id = (int)$this->request->post['product_id'];
244: } else {
245: $product_id = 0;
246: }
247:
248: if (isset($this->request->post['quantity'])) {
249: $quantity = (int)$this->request->post['quantity'];
250: } else {
251: $quantity = 1;
252: }
253:
254: if (isset($this->request->post['option'])) {
255: $option = array_filter($this->request->post['option']);
256: } else {
257: $option = [];
258: }
259:
260: if (isset($this->request->post['subscription_plan_id'])) {
261: $subscription_plan_id = (int)$this->request->post['subscription_plan_id'];
262: } else {
263: $subscription_plan_id = 0;
264: }
265:
266: $this->load->model('catalog/product');
267:
268: $product_info = $this->model_catalog_product->getProduct($product_id);
269:
270: if ($product_info) {
271: // If variant get master product
272: if ($product_info['master_id']) {
273: $product_id = $product_info['master_id'];
274: }
275:
276: // Only use values in the override
277: if (isset($product_info['override']['variant'])) {
278: $override = $product_info['override']['variant'];
279: } else {
280: $override = [];
281: }
282:
283: // Merge variant code with options
284: foreach ($product_info['variant'] as $key => $value) {
285: if (array_key_exists($key, $override)) {
286: $option[$key] = $value;
287: }
288: }
289:
290: // Validate options
291: $product_options = $this->model_catalog_product->getOptions($product_id);
292:
293: foreach ($product_options as $product_option) {
294: if ($product_option['required'] && empty($option[$product_option['product_option_id']])) {
295: $json['error']['option_' . $product_option['product_option_id']] = sprintf($this->language->get('error_required'), $product_option['name']);
296: }
297: }
298:
299: // Validate subscription products
300: $subscriptions = $this->model_catalog_product->getSubscriptions($product_id);
301:
302: if ($subscriptions) {
303: $subscription_plan_ids = [];
304:
305: foreach ($subscriptions as $subscription) {
306: $subscription_plan_ids[] = $subscription['subscription_plan_id'];
307: }
308:
309: if (!in_array($subscription_plan_id, $subscription_plan_ids)) {
310: $json['error']['subscription'] = $this->language->get('error_subscription');
311: }
312: }
313: } else {
314: $json['error']['warning'] = $this->language->get('error_product');
315: }
316:
317: if (!$json) {
318: $this->cart->add($product_id, $quantity, $option, $subscription_plan_id);
319:
320: $json['success'] = sprintf($this->language->get('text_success'), $this->url->link('product/product', 'language=' . $this->config->get('config_language') . '&product_id=' . $product_id), $product_info['name'], $this->url->link('checkout/cart', 'language=' . $this->config->get('config_language')));
321:
322: // Unset all shipping and payment methods
323: unset($this->session->data['shipping_method']);
324: unset($this->session->data['shipping_methods']);
325: unset($this->session->data['payment_method']);
326: unset($this->session->data['payment_methods']);
327: } else {
328: $json['redirect'] = $this->url->link('product/product', 'language=' . $this->config->get('config_language') . '&product_id=' . $product_id, true);
329: }
330:
331: $this->response->addHeader('Content-Type: application/json');
332: $this->response->setOutput(json_encode($json));
333: }
334:
335: /**
336: * Edit
337: *
338: * @return void
339: */
340: public function edit(): void {
341: $this->load->language('checkout/cart');
342:
343: $json = [];
344:
345: if (isset($this->request->post['key'])) {
346: $key = (int)$this->request->post['key'];
347: } else {
348: $key = 0;
349: }
350:
351: if (isset($this->request->post['quantity'])) {
352: $quantity = (int)$this->request->post['quantity'];
353: } else {
354: $quantity = 1;
355: }
356:
357: if (!$this->cart->has($key)) {
358: $json['error'] = $this->language->get('error_product');
359: }
360:
361: if (!$json) {
362: // Handles single item update
363: $this->cart->update($key, $quantity);
364:
365: if ($this->cart->hasProducts() || !empty($this->session->data['vouchers'])) {
366: $json['success'] = $this->language->get('text_edit');
367: } else {
368: $json['redirect'] = $this->url->link('checkout/cart', 'language=' . $this->config->get('config_language'), true);
369: }
370:
371: unset($this->session->data['shipping_method']);
372: unset($this->session->data['shipping_methods']);
373: unset($this->session->data['payment_method']);
374: unset($this->session->data['payment_methods']);
375: unset($this->session->data['reward']);
376: }
377:
378: $this->response->addHeader('Content-Type: application/json');
379: $this->response->setOutput(json_encode($json));
380: }
381:
382: /**
383: * Remove
384: *
385: * @return void
386: */
387: public function remove(): void {
388: $this->load->language('checkout/cart');
389:
390: $json = [];
391:
392: if (isset($this->request->get['key'])) {
393: $key = (int)$this->request->get['key'];
394: } else {
395: $key = 0;
396: }
397:
398: if (!$this->cart->has($key)) {
399: $json['error'] = $this->language->get('error_product');
400: }
401:
402: // Remove
403: if (!$json) {
404: $this->cart->remove($key);
405:
406: if ($this->cart->hasProducts() || !empty($this->session->data['vouchers'])) {
407: $json['success'] = $this->language->get('text_remove');
408: } else {
409: $json['redirect'] = $this->url->link('checkout/cart', 'language=' . $this->config->get('config_language'), true);
410: }
411:
412: unset($this->session->data['shipping_method']);
413: unset($this->session->data['shipping_methods']);
414: unset($this->session->data['payment_method']);
415: unset($this->session->data['payment_methods']);
416: unset($this->session->data['reward']);
417: }
418:
419: $this->response->addHeader('Content-Type: application/json');
420: $this->response->setOutput(json_encode($json));
421: }
422: }
423: