1: <?php
2: namespace Opencart\Admin\Model\Catalog;
3: /**
4: * Class Category
5: *
6: * @package Opencart\Admin\Model\Catalog
7: */
8: class Category extends \Opencart\System\Engine\Model {
9: /**
10: * Add Category
11: *
12: * @param array<string, mixed> $data
13: *
14: * @return int
15: */
16: public function addCategory(array $data): int {
17: $this->db->query("INSERT INTO `" . DB_PREFIX . "category` SET `image` = '" . $this->db->escape((string)$data['image']) . "', `parent_id` = '" . (int)$data['parent_id'] . "', `column` = '" . (int)$data['column'] . "', `sort_order` = '" . (int)$data['sort_order'] . "', `status` = '" . (bool)($data['status'] ?? 0) . "', `date_modified` = NOW(), `date_added` = NOW()");
18:
19: $category_id = $this->db->getLastId();
20:
21: foreach ($data['category_description'] as $language_id => $category_description) {
22: $this->model_catalog_category->addDescription($category_id, $language_id, $category_description);
23: }
24:
25: $level = 0;
26:
27: // MySQL Hierarchical Data Closure Table Pattern
28: $results = $this->model_catalog_category->getPaths($data['parent_id']);
29:
30: foreach ($results as $result) {
31: $this->model_catalog_category->addPath($category_id, $result['path_id'], $level);
32:
33: $level++;
34: }
35:
36: $this->model_catalog_category->addPath($category_id, $category_id, $level);
37:
38: if (isset($data['category_filter'])) {
39: foreach ($data['category_filter'] as $filter_id) {
40: $this->model_catalog_category->addFilter($category_id, $filter_id);
41: }
42: }
43:
44: if (isset($data['category_store'])) {
45: foreach ($data['category_store'] as $store_id) {
46: $this->model_catalog_category->addStore($category_id, $store_id);
47: }
48: }
49:
50: // Seo urls on categories need to be done differently to they include the full keyword path
51: $parent_path = $this->model_catalog_category->getPath($data['parent_id']);
52:
53: if (!$parent_path) {
54: $path = $category_id;
55: } else {
56: $path = $parent_path . '_' . $category_id;
57: }
58:
59: $this->load->model('design/seo_url');
60:
61: foreach ($data['category_seo_url'] as $store_id => $language) {
62: foreach ($language as $language_id => $keyword) {
63: $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyValue('path', $parent_path, $store_id, $language_id);
64:
65: if ($seo_url_info) {
66: $keyword = $seo_url_info['keyword'] . '/' . $keyword;
67: }
68:
69: $this->model_design_seo_url->addSeoUrl('path', $path, $keyword, $store_id, $language_id);
70: }
71: }
72:
73: // Set which layout to use with this category
74: if (isset($data['category_layout'])) {
75: foreach ($data['category_layout'] as $store_id => $layout_id) {
76: if ($layout_id) {
77: $this->model_catalog_category->addLayout($category_id, $store_id, $layout_id);
78: }
79: }
80: }
81:
82: return $category_id;
83: }
84:
85: /**
86: * Edit Category
87: *
88: * @param int $category_id
89: * @param array<string, mixed> $data
90: *
91: * @return void
92: */
93: public function editCategory(int $category_id, array $data): void {
94: $this->db->query("UPDATE `" . DB_PREFIX . "category` SET `image` = '" . $this->db->escape((string)$data['image']) . "', `parent_id` = '" . (int)$data['parent_id'] . "', `column` = '" . (int)$data['column'] . "', `sort_order` = '" . (int)$data['sort_order'] . "', `status` = '" . (bool)($data['status'] ?? 0) . "', `date_modified` = NOW() WHERE `category_id` = '" . (int)$category_id . "'");
95:
96: $this->model_catalog_category->deleteDescriptions($category_id);
97:
98: foreach ($data['category_description'] as $language_id => $category_description) {
99: $this->model_catalog_category->addDescription($category_id, $language_id, $category_description);
100: }
101:
102: // Old path
103: $path_old = $this->model_catalog_category->getPath($category_id);
104:
105: // Delete the category paths
106: $this->model_catalog_category->deletePaths($category_id);
107:
108: // Delete paths
109: $results = $this->model_catalog_category->getPathsByPathId($category_id);
110:
111: foreach ($results as $result) {
112: // Delete old paths
113: $this->model_catalog_category->deletePathsByLevel($result['category_id'], $result['level']);
114: }
115:
116: $paths = [];
117:
118: // Build new path
119: $results = $this->model_catalog_category->getPaths($data['parent_id']);
120:
121: foreach ($results as $result) {
122: $paths[] = $result['path_id'];
123: }
124:
125: // Get what's left of the nodes current path
126: $results = $this->model_catalog_category->getPaths($category_id);
127:
128: foreach ($results as $result) {
129: $paths[] = $result['path_id'];
130: }
131:
132: // Combine the paths with a new level
133: $level = 0;
134:
135: foreach ($paths as $path_id) {
136: $this->model_catalog_category->addPath($category_id, $path_id, $level);
137:
138: $level++;
139: }
140:
141: $this->model_catalog_category->addPath($category_id, $category_id, $level);
142:
143: // Filters
144: $this->model_catalog_category->deleteFilters($category_id);
145:
146: if (isset($data['category_filter'])) {
147: foreach ($data['category_filter'] as $filter_id) {
148: $this->model_catalog_category->addFilter($category_id, $filter_id);
149: }
150: }
151:
152: // Stores
153: $this->model_catalog_category->deleteStores($category_id);
154:
155: if (isset($data['category_store'])) {
156: foreach ($data['category_store'] as $store_id) {
157: $this->model_catalog_category->addStore($category_id, $store_id);
158: }
159: }
160:
161: // Seo urls on categories need to be done differently to they include the full keyword path
162: $seo_urls = [];
163:
164: $value = '';
165:
166: $this->load->model('design/seo_url');
167:
168: foreach ($paths as $path_id) {
169: // Get all sub paths
170: if (!$value) {
171: $value = $path_id;
172: } else {
173: $value = $value . '_' . $path_id;
174: }
175:
176: $results = $this->model_design_seo_url->getSeoUrlsByKeyValue('path', $value);
177:
178: $this->model_design_seo_url->deleteSeoUrlsByKeyValue('path', $value);
179:
180: foreach ($results as $store_id => $language) {
181: foreach ($language as $language_id => $keyword) {
182: $pos = strrpos($keyword, '/');
183:
184: if ($pos !== false) {
185: $keyword = substr($keyword, $pos + 1);
186: }
187:
188: $seo_urls[$store_id][$language_id][$path_id] = $keyword;
189: }
190: }
191: }
192:
193: // Delete the old path
194: $this->model_design_seo_url->deleteSeoUrlsByKeyValue('path', $path_old);
195:
196: // Current SEO URL
197: foreach ($data['category_seo_url'] as $store_id => $language) {
198: foreach ($language as $language_id => $keyword) {
199: $seo_urls[$store_id][$language_id][$category_id] = $keyword;
200: }
201: }
202:
203: // All sub paths
204: $filter_data = [
205: 'filter_key' => 'path',
206: 'filter_value' => $path_old . '\_%'
207: ];
208:
209: $results = $this->model_design_seo_url->getSeoUrls($filter_data);
210:
211: // Delete the old SEO URL paths
212: $this->model_design_seo_url->deleteSeoUrlsByKeyValue('path', $path_old . '\_%');
213:
214: foreach ($results as $result) {
215: $keyword = $result['keyword'];
216:
217: $pos = strrpos($keyword, '/');
218:
219: if ($pos !== false) {
220: $keyword = substr($keyword, $pos + 1);
221: }
222:
223: $seo_urls[$result['store_id']][$result['language_id']][substr($result['value'], strrpos($result['value'], '_') + 1)] = $keyword;
224: }
225:
226: // Get all sub paths
227: foreach ($seo_urls as $store_id => $language) {
228: foreach ($language as $language_id => $path) {
229: $value = '';
230:
231: $string = '';
232:
233: foreach ($path as $path_id => $keyword) {
234: // Get all sub paths
235: if (!$value) {
236: $value = $path_id;
237: } else {
238: $value = $value . '_' . $path_id;
239: }
240:
241: if (!$string) {
242: $string = $keyword;
243: } else {
244: $string = $string . '/' . $keyword;
245: }
246:
247: $this->model_design_seo_url->addSeoUrl('path', $value, $string, $store_id, $language_id);
248: }
249: }
250: }
251:
252: // Layouts
253: $this->model_catalog_category->deleteLayouts($category_id);
254:
255: if (isset($data['category_layout'])) {
256: foreach ($data['category_layout'] as $store_id => $layout_id) {
257: if ($layout_id) {
258: $this->model_catalog_category->addLayout($category_id, $store_id, $layout_id);
259: }
260: }
261: }
262: }
263:
264: /**
265: * Delete Category
266: *
267: * @param int $category_id
268: *
269: * @return void
270: */
271: public function deleteCategory(int $category_id): void {
272: $this->db->query("DELETE FROM `" . DB_PREFIX . "category` WHERE `category_id` = '" . (int)$category_id . "'");
273:
274: $this->model_catalog_category->deleteDescriptions($category_id);
275: $this->model_catalog_category->deleteFilters($category_id);
276: $this->model_catalog_category->deleteStores($category_id);
277: $this->model_catalog_category->deleteLayouts($category_id);
278:
279: $this->load->model('catalog/product');
280:
281: $this->model_catalog_product->deletesCategoriesByCategoryId($category_id);
282:
283: $this->load->model('marketing/coupon');
284:
285: $this->model_marketing_coupon->deleteCategoriesByCategoryId($category_id);
286:
287: $this->load->model('design/seo_url');
288:
289: $path = $this->model_catalog_category->getPath($category_id);
290:
291: $this->model_design_seo_url->deleteSeoUrlsByKeyValue('path', $path);
292: $this->model_design_seo_url->deleteSeoUrlsByKeyValue('path', $path . '_%');
293:
294: // Delete connected paths
295: $results = $this->model_catalog_category->getPathsByPathId($category_id);
296:
297: foreach ($results as $result) {
298: if ($result['category_id'] != $category_id) {
299: $this->model_catalog_category->deleteCategory($result['category_id']);
300: }
301: }
302:
303: $this->model_catalog_category->deletePaths($category_id);
304:
305: $this->cache->delete('category');
306: }
307:
308: /**
309: * Repair Categories
310: *
311: * @param int $parent_id
312: *
313: * @return void
314: */
315: public function repairCategories(int $parent_id = 0): void {
316: $categories = $this->model_catalog_category->getCategories(['filter_parent_id' => $parent_id]);
317:
318: // Delete the path below the current one
319: foreach ($categories as $category) {
320: // Delete the path below the current one
321: $this->model_catalog_category->deletePath($category['category_id']);
322:
323: // Fix for records with no paths
324: $level = 0;
325:
326: $paths = $this->model_catalog_category->getPaths($parent_id);
327:
328: foreach ($paths as $path) {
329: $this->model_catalog_category->addPath($category['category_id'], $path['path_id'], $level);
330:
331: $level++;
332: }
333:
334: $this->model_catalog_category->addPath($category['category_id'], $category['category_id'], $level);
335:
336: $this->model_catalog_category->repairCategories($category['category_id']);
337: }
338: }
339:
340: /**
341: * Get Category
342: *
343: * @param int $category_id
344: *
345: * @return array<string, mixed>
346: */
347: public function getCategory(int $category_id): array {
348: $query = $this->db->query("SELECT DISTINCT *, (SELECT GROUP_CONCAT(`cd1`.`name` ORDER BY `level` SEPARATOR ' > ') FROM `" . DB_PREFIX . "category_path` `cp` LEFT JOIN `" . DB_PREFIX . "category_description` `cd1` ON (`cp`.`path_id` = cd1.`category_id` AND `cp`.`category_id` != `cp`.`path_id`) WHERE `cp`.`category_id` = `c`.`category_id` AND `cd1`.`language_id` = '" . (int)$this->config->get('config_language_id') . "' GROUP BY `cp`.`category_id`) AS `path` FROM `" . DB_PREFIX . "category` `c` LEFT JOIN `" . DB_PREFIX . "category_description` `cd2` ON (`c`.`category_id` = `cd2`.`category_id`) WHERE `c`.`category_id` = '" . (int)$category_id . "' AND `cd2`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'");
349:
350: return $query->row;
351: }
352:
353: /**
354: * Get Categories
355: *
356: * @param array<string, mixed> $data
357: *
358: * @return array<int, array<string, mixed>>
359: */
360: public function getCategories(array $data = []): array {
361: $sql = "SELECT `cp`.`category_id` AS `category_id`, GROUP_CONCAT(`cd1`.`name` ORDER BY `cp`.`level` SEPARATOR ' > ') AS `name`, `c1`.`parent_id`, `c1`.`sort_order`, `c1`.`status` FROM `" . DB_PREFIX . "category_path` `cp` LEFT JOIN `" . DB_PREFIX . "category` `c1` ON (`cp`.`category_id` = `c1`.`category_id`) LEFT JOIN `" . DB_PREFIX . "category` `c2` ON (`cp`.`path_id` = `c2`.`category_id`) LEFT JOIN `" . DB_PREFIX . "category_description` `cd1` ON (`cp`.`path_id` = `cd1`.`category_id`) LEFT JOIN `" . DB_PREFIX . "category_description` `cd2` ON (`cp`.`category_id` = `cd2`.`category_id`) WHERE `cd1`.`language_id` = '" . (int)$this->config->get('config_language_id') . "' AND `cd2`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
362:
363: if (!empty($data['filter_name'])) {
364: $sql .= " AND LCASE(`cd2`.`name`) LIKE '" . $this->db->escape(oc_strtolower($data['filter_name'])) . "'";
365: }
366:
367: if (isset($data['filter_parent_id'])) {
368: $sql .= " AND `c1`.`parent_id` = '" . (int)$data['filter_parent_id'] . "'";
369: }
370:
371: $sql .= " GROUP BY `cp`.`category_id`";
372:
373: $sort_data = [
374: 'name',
375: 'sort_order'
376: ];
377:
378: if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
379: $sql .= " ORDER BY " . $data['sort'];
380: } else {
381: $sql .= " ORDER BY `sort_order`";
382: }
383:
384: if (isset($data['order']) && ($data['order'] == 'DESC')) {
385: $sql .= " DESC";
386: } else {
387: $sql .= " ASC";
388: }
389:
390: if (isset($data['start']) || isset($data['limit'])) {
391: if ($data['start'] < 0) {
392: $data['start'] = 0;
393: }
394:
395: if ($data['limit'] < 1) {
396: $data['limit'] = 20;
397: }
398:
399: $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
400: }
401:
402: $query = $this->db->query($sql);
403:
404: return $query->rows;
405: }
406:
407: /**
408: * Get Total Categories
409: *
410: * @param array<string, mixed> $data
411: *
412: * @return int
413: */
414: public function getTotalCategories(array $data = []): int {
415: $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "category`";
416:
417: $implode = [];
418:
419: if (!empty($data['filter_name'])) {
420: $sql .= " AND LCASE(`cd2`.`name`) LIKE '" . $this->db->escape(oc_strtolower($data['filter_name'])) . "'";
421: }
422:
423: if (isset($data['filter_parent_id'])) {
424: $sql .= " AND `parent_id` = '" . (int)$data['filter_parent_id'] . "'";
425: }
426:
427: // `cd1`.`language_id` = '" . (int)$this->config->get('config_language_id') . "' AND category_description
428:
429: if ($implode) {
430: $sql .= " WHERE " . implode(" AND ", $implode);
431: }
432:
433: $query = $this->db->query($sql);
434:
435: return (int)$query->row['total'];
436: }
437:
438: /**
439: * Add Description
440: *
441: * @param int $category_id primary key of the attribute record to be fetched
442: * @param int $language_id
443: * @param array<string, mixed> $data
444: *
445: * @return void
446: */
447: public function addDescription(int $category_id, int $language_id, array $data): void {
448: $this->db->query("INSERT INTO `" . DB_PREFIX . "category_description` SET `category_id` = '" . (int)$category_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($data['name']) . "', `description` = '" . $this->db->escape($data['description']) . "', `meta_title` = '" . $this->db->escape($data['meta_title']) . "', `meta_description` = '" . $this->db->escape($data['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($data['meta_keyword']) . "'");
449: }
450:
451: /**
452: * Delete Descriptions
453: *
454: * @param int $category_id
455: *
456: * @return void
457: */
458: public function deleteDescriptions(int $category_id): void {
459: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_description` WHERE `category_id` = '" . (int)$category_id . "'");
460: }
461:
462: /**
463: * Delete Descriptions By Language ID
464: *
465: * @param int $language_id
466: *
467: * @return void
468: */
469: public function deleteDescriptionsByLanguageId(int $language_id): void {
470: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_description` WHERE `language_id` = '" . (int)$language_id . "'");
471: }
472:
473: /**
474: * Get Descriptions
475: *
476: * @param int $category_id
477: *
478: * @return array<int, array<string, string>>
479: */
480: public function getDescriptions(int $category_id): array {
481: $category_description_data = [];
482:
483: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_description` WHERE `category_id` = '" . (int)$category_id . "'");
484:
485: foreach ($query->rows as $result) {
486: $category_description_data[$result['language_id']] = [
487: 'name' => $result['name'],
488: 'meta_title' => $result['meta_title'],
489: 'meta_description' => $result['meta_description'],
490: 'meta_keyword' => $result['meta_keyword'],
491: 'description' => $result['description']
492: ];
493: }
494:
495: return $category_description_data;
496: }
497:
498: /**
499: * Get Descriptions By Language ID
500: *
501: * @param int $language_id
502: *
503: * @return array<int, array<string, string>>
504: */
505: public function getDescriptionsByLanguageId(int $language_id): array {
506: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_description` WHERE `language_id` = '" . (int)$language_id . "'");
507:
508: return $query->rows;
509: }
510:
511: /**
512: * Add Path
513: *
514: * @param int $category_id
515: * @param int $path_id
516: * @param int $level
517: *
518: * @return void
519: */
520: public function addPath(int $category_id, int $path_id, int $level): void {
521: $this->db->query("INSERT INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int)$category_id . "', `path_id` = '" . (int)$path_id . "', `level` = '" . (int)$level . "'");
522: }
523:
524: /**
525: * Delete Paths
526: *
527: * @param int $category_id
528: *
529: * @return void
530: */
531: public function deletePaths(int $category_id): void {
532: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category_id . "'");
533: }
534:
535: /**
536: * Delete Paths By Level
537: *
538: * @param int $category_id
539: * @param int $level
540: *
541: * @return void
542: */
543: public function deletePathsByLevel(int $category_id, int $level = 0): void {
544: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category_id . "' AND `level` < '" . (int)$level . "'");
545: }
546:
547: /**
548: * Get Path
549: *
550: * @param int $category_id
551: *
552: * @return string
553: */
554: public function getPath(int $category_id): string {
555: return implode('_', array_column($this->model_catalog_category->getPaths($category_id), 'path_id'));
556: }
557:
558: /**
559: * Get Paths
560: *
561: * @param int $category_id
562: *
563: * @return array<int, array<string, mixed>>
564: */
565: public function getPaths(int $category_id): array {
566: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category_id . "' ORDER BY `level` ASC");
567:
568: return $query->rows;
569: }
570:
571: /**
572: * Get Paths By Path ID
573: *
574: * @param int $path_id
575: *
576: * @return array<int, array<string, mixed>>
577: */
578: public function getPathsByPathId(int $path_id): array {
579: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `path_id` = '" . (int)$path_id . "' ORDER BY `level` ASC");
580:
581: return $query->rows;
582: }
583:
584: /**
585: * Add Filter
586: *
587: * @param int $category_id
588: * @param int $filter_id
589: *
590: * @return void
591: */
592: public function addFilter(int $category_id, int $filter_id): void {
593: $this->db->query("INSERT INTO `" . DB_PREFIX . "category_filter` SET `category_id` = '" . (int)$category_id . "', `filter_id` = '" . (int)$filter_id . "'");
594: }
595:
596: /**
597: * Delete Filters
598: *
599: * @param int $category_id
600: *
601: * @return void
602: */
603: public function deleteFilters(int $category_id): void {
604: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_filter` WHERE `category_id` = '" . (int)$category_id . "'");
605: }
606:
607: /**
608: * Get Filters
609: *
610: * @param int $category_id
611: *
612: * @return array<int, int>
613: */
614: public function getFilters(int $category_id): array {
615: $category_filter_data = [];
616:
617: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_filter` WHERE `category_id` = '" . (int)$category_id . "'");
618:
619: foreach ($query->rows as $result) {
620: $category_filter_data[] = $result['filter_id'];
621: }
622:
623: return $category_filter_data;
624: }
625:
626: /**
627: * Add Store
628: *
629: * @param int $category_id
630: * @param int $store_id
631: *
632: * @return void
633: */
634: public function addStore(int $category_id, int $store_id): void {
635: $this->db->query("INSERT INTO `" . DB_PREFIX . "category_to_store` SET `category_id` = '" . (int)$category_id . "', `store_id` = '" . (int)$store_id . "'");
636: }
637:
638: /**
639: * Delete Stores
640: *
641: * @param int $category_id
642: *
643: * @return void
644: */
645: public function deleteStores(int $category_id): void {
646: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_store` WHERE `category_id` = '" . (int)$category_id . "'");
647: }
648:
649: /**
650: * Delete Stores By Store ID
651: *
652: * @param int $store_id
653: *
654: * @return void
655: */
656: public function deleteStoresByStoreId(int $store_id): void {
657: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_store` WHERE `store_id` = '" . (int)$store_id . "'");
658: }
659:
660: /**
661: * Get Stores
662: *
663: * @param int $category_id
664: *
665: * @return array<int, int>
666: */
667: public function getStores(int $category_id): array {
668: $category_store_data = [];
669:
670: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_to_store` WHERE `category_id` = '" . (int)$category_id . "'");
671:
672: foreach ($query->rows as $result) {
673: $category_store_data[] = $result['store_id'];
674: }
675:
676: return $category_store_data;
677: }
678:
679: /**
680: * Add Layout
681: *
682: * @param int $category_id
683: * @param int $store_id
684: * @param int $layout_id
685: *
686: * @return void
687: */
688: public function addLayout(int $category_id, int $store_id, int $layout_id): void {
689: $this->db->query("INSERT INTO `" . DB_PREFIX . "category_to_layout` SET `category_id` = '" . (int)$category_id . "', store_id = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'");
690: }
691:
692: /**
693: * Delete Layouts
694: *
695: * @param int $category_id
696: *
697: * @return void
698: */
699: public function deleteLayouts(int $category_id): void {
700: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_layout` WHERE `category_id` = '" . (int)$category_id . "'");
701: }
702:
703: /**
704: * Delete Layouts By Layout ID
705: *
706: * @param int $layout_id
707: *
708: * @return void
709: */
710: public function deleteLayoutsByLayoutId(int $layout_id): void {
711: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'");
712: }
713:
714: /**
715: * Delete Layouts By Store ID
716: *
717: * @param int $store_id
718: *
719: * @return void
720: */
721: public function deleteLayoutsByStoreId(int $store_id): void {
722: $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_layout` WHERE `store_id` = '" . (int)$store_id . "'");
723: }
724:
725: /**
726: * Get Layouts
727: *
728: * @param int $category_id
729: *
730: * @return array<int, int>
731: */
732: public function getLayouts(int $category_id): array {
733: $category_layout_data = [];
734:
735: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_to_layout` WHERE `category_id` = '" . (int)$category_id . "'");
736:
737: foreach ($query->rows as $result) {
738: $category_layout_data[$result['store_id']] = $result['layout_id'];
739: }
740:
741: return $category_layout_data;
742: }
743:
744: /**
745: * Get Total Layouts By Layout ID
746: *
747: * @param int $layout_id
748: *
749: * @return int
750: */
751: public function getTotalLayoutsByLayoutId(int $layout_id): int {
752: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "category_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'");
753:
754: return (int)$query->row['total'];
755: }
756: }
757: