1: <?php
2: namespace Opencart\Catalog\Controller\Product;
3: /**
4: * Class Category
5: *
6: * @package Opencart\Catalog\Controller\Product
7: */
8: class Category extends \Opencart\System\Engine\Controller {
9: /**
10: * @return \Opencart\System\Engine\Action|null
11: */
12: public function index(): ?\Opencart\System\Engine\Action {
13: $this->load->language('product/category');
14:
15: if (isset($this->request->get['path'])) {
16: $path = (string)$this->request->get['path'];
17: } else {
18: $path = '';
19: }
20:
21: if (isset($this->request->get['filter'])) {
22: $filter = $this->request->get['filter'];
23: } else {
24: $filter = '';
25: }
26:
27: if (isset($this->request->get['sort'])) {
28: $sort = $this->request->get['sort'];
29: } else {
30: $sort = 'p.sort_order';
31: }
32:
33: if (isset($this->request->get['order'])) {
34: $order = $this->request->get['order'];
35: } else {
36: $order = 'ASC';
37: }
38:
39: if (isset($this->request->get['page'])) {
40: $page = (int)$this->request->get['page'];
41: } else {
42: $page = 1;
43: }
44:
45: if (isset($this->request->get['limit']) && (int)$this->request->get['limit']) {
46: $limit = (int)$this->request->get['limit'];
47: } else {
48: $limit = $this->config->get('config_pagination');
49: }
50:
51: $parts = explode('_', $path);
52:
53: $category_id = (int)array_pop($parts);
54:
55: $this->load->model('catalog/category');
56:
57: $category_info = $this->model_catalog_category->getCategory($category_id);
58:
59: if ($category_info) {
60: $this->document->setTitle($category_info['meta_title']);
61: $this->document->setDescription($category_info['meta_description']);
62: $this->document->setKeywords($category_info['meta_keyword']);
63:
64: $data['breadcrumbs'] = [];
65:
66: $data['breadcrumbs'][] = [
67: 'text' => $this->language->get('text_home'),
68: 'href' => $this->url->link('common/home', 'language=' . $this->config->get('config_language'))
69: ];
70:
71: $url = '';
72:
73: if (isset($this->request->get['sort'])) {
74: $url .= '&sort=' . $this->request->get['sort'];
75: }
76:
77: if (isset($this->request->get['order'])) {
78: $url .= '&order=' . $this->request->get['order'];
79: }
80:
81: if (isset($this->request->get['limit'])) {
82: $url .= '&limit=' . $this->request->get['limit'];
83: }
84:
85: $path = '';
86:
87: foreach ($parts as $path_id) {
88: if (!$path) {
89: $path = (int)$path_id;
90: } else {
91: $path .= '_' . (int)$path_id;
92: }
93:
94: $parent_info = $this->model_catalog_category->getCategory((int)$path_id);
95:
96: if ($parent_info) {
97: $data['breadcrumbs'][] = [
98: 'text' => $parent_info['name'],
99: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&path=' . $path . $url)
100: ];
101: }
102: }
103:
104: $url = '';
105:
106: if (isset($this->request->get['path'])) {
107: $url .= '&path=' . $this->request->get['path'];
108: }
109:
110: if (isset($this->request->get['filter'])) {
111: $url .= '&filter=' . $this->request->get['filter'];
112: }
113:
114: if (isset($this->request->get['sort'])) {
115: $url .= '&sort=' . $this->request->get['sort'];
116: }
117:
118: if (isset($this->request->get['order'])) {
119: $url .= '&order=' . $this->request->get['order'];
120: }
121:
122: if (isset($this->request->get['page'])) {
123: $url .= '&page=' . $this->request->get['page'];
124: }
125:
126: if (isset($this->request->get['limit'])) {
127: $url .= '&limit=' . $this->request->get['limit'];
128: }
129:
130: // Set the last category breadcrumb
131: $data['breadcrumbs'][] = [
132: 'text' => $category_info['name'],
133: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . $url)
134: ];
135:
136: $data['heading_title'] = $category_info['name'];
137:
138: $data['text_compare'] = sprintf($this->language->get('text_compare'), isset($this->session->data['compare']) ? count($this->session->data['compare']) : 0);
139:
140: $this->load->model('tool/image');
141:
142: if (!empty($category_info['image']) && is_file(DIR_IMAGE . html_entity_decode($category_info['image'], ENT_QUOTES, 'UTF-8'))) {
143: $data['image'] = $this->model_tool_image->resize($category_info['image'], $this->config->get('config_image_category_width'), $this->config->get('config_image_category_height'));
144: } else {
145: $data['image'] = '';
146: }
147:
148: $data['description'] = html_entity_decode($category_info['description'], ENT_QUOTES, 'UTF-8');
149: $data['compare'] = $this->url->link('product/compare', 'language=' . $this->config->get('config_language'));
150:
151: $url = '';
152:
153: if (isset($this->request->get['filter'])) {
154: $url .= '&filter=' . $this->request->get['filter'];
155: }
156:
157: if (isset($this->request->get['sort'])) {
158: $url .= '&sort=' . $this->request->get['sort'];
159: }
160:
161: if (isset($this->request->get['order'])) {
162: $url .= '&order=' . $this->request->get['order'];
163: }
164:
165: if (isset($this->request->get['limit'])) {
166: $url .= '&limit=' . $this->request->get['limit'];
167: }
168:
169: $data['categories'] = [];
170:
171: $this->load->model('catalog/product');
172:
173: $results = $this->model_catalog_category->getCategories($category_id);
174:
175: foreach ($results as $result) {
176: $filter_data = [
177: 'filter_category_id' => $result['category_id'],
178: 'filter_sub_category' => false
179: ];
180:
181: $data['categories'][] = [
182: 'name' => $result['name'] . ($this->config->get('config_product_count') ? ' (' . $this->model_catalog_product->getTotalProducts($filter_data) . ')' : ''),
183: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&path=' . $this->request->get['path'] . '_' . $result['category_id'] . $url)
184: ];
185: }
186:
187: $url = '';
188:
189: if (isset($this->request->get['path'])) {
190: $url .= '&path=' . $this->request->get['path'];
191: }
192:
193: if (isset($this->request->get['filter'])) {
194: $url .= '&filter=' . $this->request->get['filter'];
195: }
196:
197: if (isset($this->request->get['sort'])) {
198: $url .= '&sort=' . $this->request->get['sort'];
199: }
200:
201: if (isset($this->request->get['order'])) {
202: $url .= '&order=' . $this->request->get['order'];
203: }
204:
205: if (isset($this->request->get['page'])) {
206: $url .= '&page=' . $this->request->get['page'];
207: }
208:
209: if (isset($this->request->get['limit'])) {
210: $url .= '&limit=' . $this->request->get['limit'];
211: }
212:
213: $data['products'] = [];
214:
215: $filter_data = [
216: 'filter_category_id' => $category_id,
217: 'filter_sub_category' => false,
218: 'filter_filter' => $filter,
219: 'sort' => $sort,
220: 'order' => $order,
221: 'start' => ($page - 1) * $limit,
222: 'limit' => $limit
223: ];
224:
225: $results = $this->model_catalog_product->getProducts($filter_data);
226:
227: foreach ($results as $result) {
228: $description = trim(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8')));
229:
230: if (oc_strlen($description) > $this->config->get('config_product_description_length')) {
231: $description = oc_substr($description, 0, $this->config->get('config_product_description_length')) . '..';
232: }
233:
234: if ($result['image'] && is_file(DIR_IMAGE . html_entity_decode($result['image'], ENT_QUOTES, 'UTF-8'))) {
235: $image = $result['image'];
236: } else {
237: $image = 'placeholder.png';
238: }
239:
240: if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
241: $price = $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
242: } else {
243: $price = false;
244: }
245:
246: if ((float)$result['special']) {
247: $special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
248: } else {
249: $special = false;
250: }
251:
252: if ($this->config->get('config_tax')) {
253: $tax = $this->currency->format((float)$result['special'] ? $result['special'] : $result['price'], $this->session->data['currency']);
254: } else {
255: $tax = false;
256: }
257:
258: $product_data = [
259: 'product_id' => $result['product_id'],
260: 'name' => $result['name'],
261: 'description' => $description,
262: 'thumb' => $this->model_tool_image->resize($image, $this->config->get('config_image_product_width'), $this->config->get('config_image_product_height')),
263: 'price' => $price,
264: 'special' => $special,
265: 'tax' => $tax,
266: 'minimum' => $result['minimum'] > 0 ? $result['minimum'] : 1,
267: 'rating' => $result['rating'],
268: 'href' => $this->url->link('product/product', 'language=' . $this->config->get('config_language') . '&product_id=' . $result['product_id'] . $url)
269: ];
270:
271: $data['products'][] = $this->load->controller('product/thumb', $product_data);
272: }
273:
274: $url = '';
275:
276: if (isset($this->request->get['path'])) {
277: $url .= '&path=' . $this->request->get['path'];
278: }
279:
280: if (isset($this->request->get['filter'])) {
281: $url .= '&filter=' . $this->request->get['filter'];
282: }
283:
284: if (isset($this->request->get['limit'])) {
285: $url .= '&limit=' . $this->request->get['limit'];
286: }
287:
288: $data['sorts'] = [];
289:
290: $data['sorts'][] = [
291: 'text' => $this->language->get('text_default'),
292: 'value' => 'p.sort_order-ASC',
293: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=p.sort_order&order=ASC' . $url)
294: ];
295:
296: $data['sorts'][] = [
297: 'text' => $this->language->get('text_name_asc'),
298: 'value' => 'pd.name-ASC',
299: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=pd.name&order=ASC' . $url)
300: ];
301:
302: $data['sorts'][] = [
303: 'text' => $this->language->get('text_name_desc'),
304: 'value' => 'pd.name-DESC',
305: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=pd.name&order=DESC' . $url)
306: ];
307:
308: $data['sorts'][] = [
309: 'text' => $this->language->get('text_price_asc'),
310: 'value' => 'p.price-ASC',
311: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=p.price&order=ASC' . $url)
312: ];
313:
314: $data['sorts'][] = [
315: 'text' => $this->language->get('text_price_desc'),
316: 'value' => 'p.price-DESC',
317: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=p.price&order=DESC' . $url)
318: ];
319:
320: if ($this->config->get('config_review_status')) {
321: $data['sorts'][] = [
322: 'text' => $this->language->get('text_rating_desc'),
323: 'value' => 'rating-DESC',
324: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=rating&order=DESC' . $url)
325: ];
326:
327: $data['sorts'][] = [
328: 'text' => $this->language->get('text_rating_asc'),
329: 'value' => 'rating-ASC',
330: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=rating&order=ASC' . $url)
331: ];
332: }
333:
334: $data['sorts'][] = [
335: 'text' => $this->language->get('text_model_asc'),
336: 'value' => 'p.model-ASC',
337: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=p.model&order=ASC' . $url)
338: ];
339:
340: $data['sorts'][] = [
341: 'text' => $this->language->get('text_model_desc'),
342: 'value' => 'p.model-DESC',
343: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&sort=p.model&order=DESC' . $url)
344: ];
345:
346: $url = '';
347:
348: if (isset($this->request->get['path'])) {
349: $url .= '&path=' . $this->request->get['path'];
350: }
351:
352: if (isset($this->request->get['filter'])) {
353: $url .= '&filter=' . $this->request->get['filter'];
354: }
355:
356: if (isset($this->request->get['sort'])) {
357: $url .= '&sort=' . $this->request->get['sort'];
358: }
359:
360: if (isset($this->request->get['order'])) {
361: $url .= '&order=' . $this->request->get['order'];
362: }
363:
364: $data['limits'] = [];
365:
366: $limits = array_unique([$this->config->get('config_pagination'), 25, 50, 75, 100]);
367:
368: sort($limits);
369:
370: foreach ($limits as $value) {
371: $data['limits'][] = [
372: 'text' => $value,
373: 'value' => $value,
374: 'href' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . $url . '&limit=' . $value)
375: ];
376: }
377:
378: $url = '';
379:
380: if (isset($this->request->get['path'])) {
381: $url .= '&path=' . $this->request->get['path'];
382: }
383:
384: if (isset($this->request->get['filter'])) {
385: $url .= '&filter=' . $this->request->get['filter'];
386: }
387:
388: if (isset($this->request->get['sort'])) {
389: $url .= '&sort=' . $this->request->get['sort'];
390: }
391:
392: if (isset($this->request->get['order'])) {
393: $url .= '&order=' . $this->request->get['order'];
394: }
395:
396: if (isset($this->request->get['limit'])) {
397: $url .= '&limit=' . $this->request->get['limit'];
398: }
399:
400: $product_total = $this->model_catalog_product->getTotalProducts($filter_data);
401:
402: $data['pagination'] = $this->load->controller('common/pagination', [
403: 'total' => $product_total,
404: 'page' => $page,
405: 'limit' => $limit,
406: 'url' => $this->url->link('product/category', 'language=' . $this->config->get('config_language') . $url . '&page={page}')
407: ]);
408:
409: $data['results'] = sprintf($this->language->get('text_pagination'), ($product_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($product_total - $limit)) ? $product_total : ((($page - 1) * $limit) + $limit), $product_total, ceil($product_total / $limit));
410:
411: // https://developers.google.com/search/blog/2011/09/pagination-with-relnext-and-relprev
412: if ($page == 1) {
413: $this->document->addLink($this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&path=' . $this->request->get['path']), 'canonical');
414: } else {
415: $this->document->addLink($this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&path=' . $this->request->get['path'] . '&page=' . $page), 'canonical');
416: }
417:
418: if ($page > 1) {
419: $this->document->addLink($this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&path=' . $this->request->get['path'] . (($page - 2) ? '&page=' . ($page - 1) : '')), 'prev');
420: }
421:
422: if ($limit && ceil($product_total / $limit) > $page) {
423: $this->document->addLink($this->url->link('product/category', 'language=' . $this->config->get('config_language') . '&path=' . $this->request->get['path'] . '&page=' . ($page + 1)), 'next');
424: }
425:
426: $data['sort'] = $sort;
427: $data['order'] = $order;
428: $data['limit'] = $limit;
429:
430: $data['continue'] = $this->url->link('common/home', 'language=' . $this->config->get('config_language'));
431:
432: $data['column_left'] = $this->load->controller('common/column_left');
433: $data['column_right'] = $this->load->controller('common/column_right');
434: $data['content_top'] = $this->load->controller('common/content_top');
435: $data['content_bottom'] = $this->load->controller('common/content_bottom');
436: $data['footer'] = $this->load->controller('common/footer');
437: $data['header'] = $this->load->controller('common/header');
438:
439: $this->response->setOutput($this->load->view('product/category', $data));
440: } else {
441: return new \Opencart\System\Engine\Action('error/not_found');
442: }
443:
444: return null;
445: }
446: }
447: