1: <?php
2: namespace Opencart\Admin\Model\Catalog;
3: /**
4: * Class Product
5: *
6: * @package Opencart\Admin\Model\Catalog
7: */
8: class Product extends \Opencart\System\Engine\Model {
9: /**
10: * Add Product
11: *
12: * @param array<string, mixed> $data
13: *
14: * @return int
15: */
16: public function addProduct(array $data): int {
17: $this->db->query("INSERT INTO `" . DB_PREFIX . "product` SET `master_id` = '" . (int)$data['master_id'] . "', `model` = '" . $this->db->escape((string)$data['model']) . "', `sku` = '" . $this->db->escape((string)$data['sku']) . "', `upc` = '" . $this->db->escape((string)$data['upc']) . "', `ean` = '" . $this->db->escape((string)$data['ean']) . "', `jan` = '" . $this->db->escape((string)$data['jan']) . "', `isbn` = '" . $this->db->escape((string)$data['isbn']) . "', `mpn` = '" . $this->db->escape((string)$data['mpn']) . "', `location` = '" . $this->db->escape((string)$data['location']) . "', `variant` = '" . $this->db->escape(!empty($data['variant']) ? json_encode($data['variant']) : '') . "', `override` = '" . $this->db->escape(!empty($data['override']) ? json_encode($data['override']) : '') . "', `quantity` = '" . (int)$data['quantity'] . "', `minimum` = '" . (int)$data['minimum'] . "', `subtract` = '" . (isset($data['subtract']) ? (bool)$data['subtract'] : 0) . "', `stock_status_id` = '" . (int)$data['stock_status_id'] . "', `date_available` = '" . $this->db->escape((string)$data['date_available']) . "', `manufacturer_id` = '" . (int)$data['manufacturer_id'] . "', `shipping` = '" . (isset($data['shipping']) ? (bool)$data['shipping'] : 0) . "', `price` = '" . (float)$data['price'] . "', `points` = '" . (int)$data['points'] . "', `weight` = '" . (float)$data['weight'] . "', `weight_class_id` = '" . (int)$data['weight_class_id'] . "', `length` = '" . (float)$data['length'] . "', `width` = '" . (float)$data['width'] . "', `height` = '" . (float)$data['height'] . "', `length_class_id` = '" . (int)$data['length_class_id'] . "', `status` = '" . (bool)($data['status'] ?? 0) . "', `tax_class_id` = '" . (int)$data['tax_class_id'] . "', `sort_order` = '" . (int)$data['sort_order'] . "', `date_added` = NOW(), `date_modified` = NOW()");
18:
19: $product_id = $this->db->getLastId();
20:
21: if ($data['image']) {
22: $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `image` = '" . $this->db->escape((string)$data['image']) . "' WHERE `product_id` = '" . (int)$product_id . "'");
23: }
24:
25: // Description
26: foreach ($data['product_description'] as $language_id => $value) {
27: $this->model_catalog_product->addDescription($product_id, $language_id, $value);
28: }
29:
30: // Categories
31: if (isset($data['product_category'])) {
32: foreach ($data['product_category'] as $category_id) {
33: $this->model_catalog_product->addCategory($product_id, $category_id);
34:
35: }
36: }
37:
38: // Filters
39: if (isset($data['product_filter'])) {
40: foreach ($data['product_filter'] as $filter_id) {
41: $this->model_catalog_product->addFilter($product_id, $filter_id);
42: }
43: }
44:
45: // Stores
46: if (isset($data['product_store'])) {
47: foreach ($data['product_store'] as $store_id) {
48: $this->model_catalog_product->addStore($product_id, $store_id);
49: }
50: }
51:
52: // Downloads
53: if (isset($data['product_download'])) {
54: foreach ($data['product_download'] as $download_id) {
55: $this->model_catalog_product->addDownload($product_id, $download_id);
56: }
57: }
58:
59: // Related
60: if (isset($data['product_related'])) {
61: foreach ($data['product_related'] as $related_id) {
62: $this->model_catalog_product->addRelated($product_id, $related_id);
63: }
64: }
65:
66: // Attributes
67: if (isset($data['product_attribute'])) {
68: foreach ($data['product_attribute'] as $product_attribute) {
69: if ($product_attribute['attribute_id']) {
70: // Removes duplicates
71: $this->model_catalog_product->deleteAttributes($product_id, $product_attribute['attribute_id']);
72:
73: foreach ($product_attribute['product_attribute_description'] as $language_id => $product_attribute_description) {
74: $this->model_catalog_product->addAttribute($product_id, $product_attribute['attribute_id'], $language_id, $product_attribute_description);
75: }
76: }
77: }
78: }
79:
80: // Options
81: if (isset($data['product_option'])) {
82: foreach ($data['product_option'] as $product_option) {
83: $this->model_catalog_product->addOption($product_id, $product_option);
84: }
85: }
86:
87: // Subscription
88: if (isset($data['product_subscription'])) {
89: foreach ($data['product_subscription'] as $product_subscription) {
90: $this->model_catalog_product->addSubscription($product_id, $product_subscription);
91: }
92: }
93:
94: // Discounts
95: if (isset($data['product_discount'])) {
96: foreach ($data['product_discount'] as $product_discount) {
97: $this->model_catalog_product->addDiscount($product_id, $product_discount);
98: }
99: }
100:
101: // Specials
102: if (isset($data['product_special'])) {
103: foreach ($data['product_special'] as $product_special) {
104: $this->model_catalog_product->addSpecial($product_id, $product_special);
105: }
106: }
107:
108: // Images
109: if (isset($data['product_image'])) {
110: foreach ($data['product_image'] as $product_image) {
111: $this->model_catalog_product->addImage($product_id, $product_image);
112:
113: }
114: }
115:
116: // Reward
117: if (isset($data['product_reward'])) {
118: foreach ($data['product_reward'] as $customer_group_id => $product_reward) {
119: if ((int)$product_reward['points'] > 0) {
120: $this->model_catalog_product->addReward($product_id, $customer_group_id, $product_reward);
121: }
122: }
123: }
124:
125: // SEO URL
126: if (isset($data['product_seo_url'])) {
127: $this->load->model('design/seo_url');
128:
129: foreach ($data['product_seo_url'] as $store_id => $language) {
130: foreach ($language as $language_id => $keyword) {
131: $this->model_design_seo_url->addSeoUrl('product_id', $product_id, $keyword, $store_id, $language_id);
132: }
133: }
134: }
135:
136: // Layout
137: if (isset($data['product_layout'])) {
138: foreach ($data['product_layout'] as $store_id => $layout_id) {
139: if ($layout_id) {
140: $this->model_catalog_product->addLayout($product_id, $store_id, $layout_id);
141: }
142: }
143: }
144:
145: $this->cache->delete('product');
146:
147: return $product_id;
148: }
149:
150: /**
151: * Edit Product
152: *
153: * @param int $product_id
154: * @param array<string, mixed> $data
155: *
156: * @return void
157: */
158: public function editProduct(int $product_id, array $data): void {
159: $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `model` = '" . $this->db->escape((string)$data['model']) . "', `sku` = '" . $this->db->escape((string)$data['sku']) . "', `upc` = '" . $this->db->escape((string)$data['upc']) . "', `ean` = '" . $this->db->escape((string)$data['ean']) . "', `jan` = '" . $this->db->escape((string)$data['jan']) . "', `isbn` = '" . $this->db->escape((string)$data['isbn']) . "', `mpn` = '" . $this->db->escape((string)$data['mpn']) . "', `location` = '" . $this->db->escape((string)$data['location']) . "', `variant` = '" . $this->db->escape(!empty($data['variant']) ? json_encode($data['variant']) : '') . "', `override` = '" . $this->db->escape(!empty($data['override']) ? json_encode($data['override']) : '') . "', `quantity` = '" . (int)$data['quantity'] . "', `minimum` = '" . (int)$data['minimum'] . "', `subtract` = '" . (isset($data['subtract']) ? (bool)$data['subtract'] : 0) . "', `stock_status_id` = '" . (int)$data['stock_status_id'] . "', `date_available` = '" . $this->db->escape((string)$data['date_available']) . "', `manufacturer_id` = '" . (int)$data['manufacturer_id'] . "', `shipping` = '" . (isset($data['shipping']) ? (bool)$data['shipping'] : 0) . "', `price` = '" . (float)$data['price'] . "', `points` = '" . (int)$data['points'] . "', `weight` = '" . (float)$data['weight'] . "', `weight_class_id` = '" . (int)$data['weight_class_id'] . "', `length` = '" . (float)$data['length'] . "', `width` = '" . (float)$data['width'] . "', `height` = '" . (float)$data['height'] . "', `length_class_id` = '" . (int)$data['length_class_id'] . "', `status` = '" . (bool)($data['status'] ?? 0) . "', `tax_class_id` = '" . (int)$data['tax_class_id'] . "', `sort_order` = '" . (int)$data['sort_order'] . "', `date_modified` = NOW() WHERE `product_id` = '" . (int)$product_id . "'");
160:
161: if ($data['image']) {
162: $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `image` = '" . $this->db->escape((string)$data['image']) . "' WHERE `product_id` = '" . (int)$product_id . "'");
163: }
164:
165: // Description
166: $this->model_catalog_product->deleteDescriptions($product_id);
167:
168: foreach ($data['product_description'] as $language_id => $value) {
169: $this->model_catalog_product->addDescription($product_id, $language_id, $value);
170: }
171:
172: // Categories
173: $this->model_catalog_product->deleteCategories($product_id);
174:
175: if (isset($data['product_category'])) {
176: foreach ($data['product_category'] as $category_id) {
177: $this->model_catalog_product->addCategory($product_id, $category_id);
178: }
179: }
180:
181: // Filters
182: $this->model_catalog_product->deleteFilters($product_id);
183:
184: if (isset($data['product_filter'])) {
185: foreach ($data['product_filter'] as $filter_id) {
186: $this->model_catalog_product->addFilter($product_id, $filter_id);
187: }
188: }
189:
190: // Stores
191: $this->model_catalog_product->deleteStores($product_id);
192:
193: if (isset($data['product_store'])) {
194: foreach ($data['product_store'] as $store_id) {
195: $this->model_catalog_product->addStore($product_id, $store_id);
196: }
197: }
198:
199: // Downloads
200: $this->model_catalog_product->deleteDownloads($product_id);
201:
202: if (isset($data['product_download'])) {
203: foreach ($data['product_download'] as $download_id) {
204: $this->model_catalog_product->addDownload($product_id, $download_id);
205: }
206: }
207:
208: // Related
209: $this->model_catalog_product->deleteRelated($product_id);
210:
211: if (isset($data['product_related'])) {
212: foreach ($data['product_related'] as $related_id) {
213: $this->model_catalog_product->addRelated($product_id, $related_id);
214: }
215: }
216:
217: // Attributes
218: $this->model_catalog_product->deleteAttributes($product_id);
219:
220: if (!empty($data['product_attribute'])) {
221: foreach ($data['product_attribute'] as $product_attribute) {
222: if ($product_attribute['attribute_id']) {
223: // Removes duplicates
224: $this->model_catalog_product->deleteAttributes($product_id, $product_attribute['attribute_id']);
225:
226: foreach ($product_attribute['product_attribute_description'] as $language_id => $product_attribute_description) {
227: $this->model_catalog_product->addAttribute($product_id, $product_attribute['attribute_id'], $language_id, $product_attribute_description);
228: }
229: }
230: }
231: }
232:
233: // Options
234: $this->model_catalog_product->deleteOptions($product_id);
235:
236: if (isset($data['product_option'])) {
237: foreach ($data['product_option'] as $product_option) {
238: $this->model_catalog_product->addOption($product_id, $product_option);
239: }
240: }
241:
242: // Subscription
243: $this->model_catalog_product->deleteSubscriptions($product_id);
244:
245: if (isset($data['product_subscription'])) {
246: foreach ($data['product_subscription'] as $product_subscription) {
247: $this->model_catalog_product->addSubscription($product_id, $product_subscription);
248: }
249: }
250:
251: // Discounts
252: $this->model_catalog_product->deleteDiscounts($product_id);
253:
254: if (isset($data['product_discount'])) {
255: foreach ($data['product_discount'] as $product_discount) {
256: $this->model_catalog_product->addDiscount($product_id, $product_discount);
257: }
258: }
259:
260: // Specials
261: $this->model_catalog_product->deleteSpecials($product_id);
262:
263: if (isset($data['product_special'])) {
264: foreach ($data['product_special'] as $product_special) {
265: $this->model_catalog_product->addSpecial($product_id, $product_special);
266: }
267: }
268:
269: // Images
270: $this->model_catalog_product->deleteImages($product_id);
271:
272: if (isset($data['product_image'])) {
273: foreach ($data['product_image'] as $product_image) {
274: $this->model_catalog_product->addImage($product_id, $product_image);
275: }
276: }
277:
278: // Rewards
279: $this->model_catalog_product->deleteRewards($product_id);
280:
281: if (isset($data['product_reward'])) {
282: foreach ($data['product_reward'] as $customer_group_id => $value) {
283: if ((int)$value['points'] > 0) {
284: $this->model_catalog_product->addReward($product_id, $customer_group_id, $value);
285: }
286: }
287: }
288:
289: // SEO URL
290: $this->model_design_seo_url->deleteSeoUrlsByKeyValue('product_id', $product_id);
291:
292: if (isset($data['product_seo_url'])) {
293: foreach ($data['product_seo_url'] as $store_id => $language) {
294: foreach ($language as $language_id => $keyword) {
295: $this->model_design_seo_url->addSeoUrl('product_id', $product_id, $keyword, $store_id, $language_id);
296: }
297: }
298: }
299:
300: // Layout
301: $this->model_catalog_product->deleteLayouts($product_id);
302:
303: if (isset($data['product_layout'])) {
304: foreach ($data['product_layout'] as $store_id => $layout_id) {
305: if ($layout_id) {
306: $this->model_catalog_product->addLayout($product_id, $store_id, $layout_id);
307: }
308: }
309: }
310:
311: $this->cache->delete('product');
312: }
313:
314: /**
315: * Copy Product
316: *
317: * @param int $product_id
318: *
319: * @return void
320: */
321: public function copyProduct(int $product_id): void {
322: $product_info = $this->model_catalog_product->getProduct($product_id);
323:
324: if ($product_info) {
325: $product_data = $product_info;
326:
327: $product_data['sku'] = '';
328: $product_data['upc'] = '';
329: $product_data['status'] = '0';
330:
331: $product_data['product_attribute'] = $this->model_catalog_product->getAttributes($product_id);
332: $product_data['product_category'] = $this->model_catalog_product->getCategories($product_id);
333: $product_data['product_description'] = $this->model_catalog_product->getDescriptions($product_id);
334: $product_data['product_discount'] = $this->model_catalog_product->getDiscounts($product_id);
335: $product_data['product_download'] = $this->model_catalog_product->getDownloads($product_id);
336: $product_data['product_filter'] = $this->model_catalog_product->getFilters($product_id);
337: $product_data['product_image'] = $this->model_catalog_product->getImages($product_id);
338: $product_data['product_layout'] = $this->model_catalog_product->getLayouts($product_id);
339: $product_data['product_option'] = $this->model_catalog_product->getOptions($product_id);
340: $product_data['product_subscription'] = $this->model_catalog_product->getSubscriptions($product_id);
341: $product_data['product_related'] = $this->model_catalog_product->getRelated($product_id);
342: $product_data['product_reward'] = $this->model_catalog_product->getRewards($product_id);
343: $product_data['product_special'] = $this->model_catalog_product->getSpecials($product_id);
344: $product_data['product_store'] = $this->model_catalog_product->getStores($product_id);
345:
346: $this->model_catalog_product->addProduct($product_data);
347: }
348: }
349:
350: /**
351: * Delete Product
352: *
353: * @param int $product_id
354: *
355: * @return void
356: */
357: public function deleteProduct(int $product_id): void {
358: $this->db->query("DELETE FROM `" . DB_PREFIX . "product` WHERE `product_id` = '" . (int)$product_id . "'");
359:
360: $this->model_catalog_product->deleteAttributes($product_id);
361: $this->model_catalog_product->deleteCategories($product_id);
362: $this->model_catalog_product->deleteDescriptions($product_id);
363: $this->model_catalog_product->deleteDiscounts($product_id);
364: $this->model_catalog_product->deleteDownloads($product_id);
365: $this->model_catalog_product->deleteFilters($product_id);
366: $this->model_catalog_product->deleteImages($product_id);
367: $this->model_catalog_product->deleteLayouts($product_id);
368: $this->model_catalog_product->deleteOptions($product_id);
369: $this->model_catalog_product->deleteRelated($product_id);
370: $this->model_catalog_product->deleteReports($product_id);
371: $this->model_catalog_product->deleteRewards($product_id);
372: $this->model_catalog_product->deleteSpecials($product_id);
373: $this->model_catalog_product->deleteStores($product_id);
374: $this->model_catalog_product->deleteSubscriptions($product_id);
375:
376: $this->load->model('catalog/review');
377:
378: $this->model_catalog_review->deleteReviewsByProductId($product_id);
379:
380: $this->load->model('design/seo_url');
381:
382: $this->model_design_seo_url->deleteSeoUrlsByKeyValue('product_id', $product_id);
383:
384: $this->load->model('marketing/coupon');
385:
386: $this->model_marketing_coupon->deleteProductsByProductId($product_id);
387:
388: $this->model_catalog_product->editMasterId($product_id, 0);
389:
390: $this->cache->delete('product');
391: }
392:
393: /**
394: * Add Variant
395: *
396: * @param int $master_id
397: * @param array<string, mixed> $data
398: *
399: * @return int
400: */
401: public function addVariant(int $master_id, array $data): int {
402: $product_data = [];
403:
404: // Use master values to override the values
405: $master_info = $this->model_catalog_product->getProduct($master_id);
406:
407: if ($master_info) {
408: // We use the override to override the master product values
409: if (isset($data['override'])) {
410: $override = (array)$data['override'];
411: } else {
412: $override = [];
413: }
414:
415: $ignore = [
416: 'product_id',
417: 'master_id',
418: 'quantity',
419: 'override',
420: 'variant'
421: ];
422:
423: foreach ($master_info as $key => $value) {
424: // So if key not in override or ignore list we replace with master value
425: if (!array_key_exists($key, $override) && !in_array($key, $ignore)) {
426: $product_data[$key] = $value;
427: }
428: }
429:
430: // Descriptions
431: $product_descriptions = $this->model_catalog_product->getDescriptions($master_id);
432:
433: foreach ($product_descriptions as $language_id => $product_description) {
434: foreach ($product_description as $key => $value) {
435: // If an override has been found, we use the POST data values
436: if (!isset($override['product_description'][$language_id][$key])) {
437: $product_data['product_description'][$language_id][$key] = $value;
438: }
439: }
440: }
441:
442: // Attributes
443: if (!isset($override['product_attribute'])) {
444: $product_data['product_attribute'] = $this->model_catalog_product->getAttributes($master_id);
445: }
446:
447: // Category
448: if (!isset($override['product_category'])) {
449: $product_data['product_category'] = $this->model_catalog_product->getCategories($master_id);
450: }
451:
452: // Discounts
453: if (!isset($override['product_discount'])) {
454: $product_data['product_discount'] = $this->model_catalog_product->getDiscounts($master_id);
455: }
456:
457: // Downloads
458: if (!isset($override['product_download'])) {
459: $product_data['product_download'] = $this->model_catalog_product->getDownloads($master_id);
460: }
461:
462: // Filters
463: if (!isset($override['product_filter'])) {
464: $product_data['product_filter'] = $this->model_catalog_product->getFilters($master_id);
465: }
466:
467: // Images
468: if (!isset($override['product_image'])) {
469: $product_data['product_image'] = $this->model_catalog_product->getImages($master_id);
470: }
471:
472: // Layouts
473: if (!isset($override['product_layout'])) {
474: $product_data['product_layout'] = $this->model_catalog_product->getLayouts($master_id);
475: }
476:
477: // Options
478: // product_option should not be used if variant product
479:
480: // Subscriptions
481: if (!isset($override['product_subscription'])) {
482: $product_data['product_subscription'] = $this->model_catalog_product->getSubscriptions($master_id);
483: }
484:
485: // Related
486: if (!isset($override['product_related'])) {
487: $product_data['product_related'] = $this->model_catalog_product->getRelated($master_id);
488: }
489:
490: // Rewards
491: if (!isset($override['product_reward'])) {
492: $product_data['product_reward'] = $this->model_catalog_product->getRewards($master_id);
493: }
494:
495: // SEO
496: // product_seo table is not overwritten because that needs to have unique seo keywords for every product
497:
498: // Specials
499: if (!isset($override['product_special'])) {
500: $product_data['product_special'] = $this->model_catalog_product->getSpecials($master_id);
501: }
502:
503: // Stores
504: if (!isset($override['product_store'])) {
505: $product_data['product_store'] = $this->model_catalog_product->getStores($master_id);
506: }
507: }
508:
509: // If override set the POST data values
510: foreach ($data as $key => $value) {
511: if (!isset($product_data[$key])) {
512: $product_data[$key] = $value;
513: }
514: }
515:
516: // Product Description
517: if (isset($data['product_description'])) {
518: foreach ($data['product_description'] as $language_id => $product_description) {
519: foreach ($product_description as $key => $value) {
520: if (!isset($product_data['product_description'][$language_id][$key])) {
521: $product_data['product_description'][$language_id][$key] = $value;
522: }
523: }
524: }
525: }
526:
527: // Product add with master product overridden values
528: return $this->model_catalog_product->addProduct($product_data);
529: }
530:
531: /**
532: * Edit Variant
533: *
534: * @param int $master_id
535: * @param int $product_id
536: * @param array<string, mixed> $data
537: *
538: * @return void
539: */
540: public function editVariant(int $master_id, int $product_id, array $data): void {
541: $product_data = [];
542:
543: // Use master values to override the values
544: $master_info = $this->model_catalog_product->getProduct($master_id);
545:
546: if ($master_info) {
547: // We use the override to override the master product values
548: if (isset($data['override'])) {
549: $override = (array)$data['override'];
550: } else {
551: $override = [];
552: }
553:
554: $ignore = [
555: 'product_id',
556: 'master_id',
557: 'quantity',
558: 'override',
559: 'variant'
560: ];
561:
562: foreach ($master_info as $key => $value) {
563: // So if key not in override or ignore list we replace with master value
564: if (!array_key_exists($key, $override) && !in_array($key, $ignore)) {
565: $product_data[$key] = $value;
566: }
567: }
568:
569: // Description
570: $product_descriptions = $this->model_catalog_product->getDescriptions($master_id);
571:
572: foreach ($product_descriptions as $language_id => $product_description) {
573: foreach ($product_description as $key => $value) {
574: if (!isset($override['product_description'][$language_id][$key])) {
575: $product_data['product_description'][$language_id][$key] = $value;
576: }
577: }
578: }
579:
580: // Attributes
581: if (!isset($override['product_attribute'])) {
582: $product_data['product_attribute'] = $this->model_catalog_product->getAttributes($master_id);
583: }
584:
585: // Category
586: if (!isset($override['product_category'])) {
587: $product_data['product_category'] = $this->model_catalog_product->getCategories($master_id);
588: }
589:
590: // Discounts
591: if (!isset($override['product_discount'])) {
592: $product_data['product_discount'] = $this->model_catalog_product->getDiscounts($master_id);
593: }
594:
595: // Downloads
596: if (!isset($override['product_download'])) {
597: $product_data['product_download'] = $this->model_catalog_product->getDownloads($master_id);
598: }
599:
600: // Filters
601: if (!isset($override['product_filter'])) {
602: $product_data['product_filter'] = $this->model_catalog_product->getFilters($master_id);
603: }
604:
605: // Images
606: if (!isset($override['product_image'])) {
607: $product_data['product_image'] = $this->model_catalog_product->getImages($master_id);
608: }
609:
610: // Layouts
611: if (!isset($override['product_layout'])) {
612: $product_data['product_layout'] = $this->model_catalog_product->getLayouts($master_id);
613: }
614:
615: // Options
616: // product_option should not be used if variant product
617:
618: // Subscription
619: if (!isset($override['product_subscription'])) {
620: $product_data['product_subscription'] = $this->model_catalog_product->getSubscriptions($master_id);
621: }
622:
623: // Related
624: if (!isset($override['product_related'])) {
625: $product_data['product_related'] = $this->model_catalog_product->getRelated($master_id);
626: }
627:
628: // Rewards
629: if (!isset($override['product_reward'])) {
630: $product_data['product_reward'] = $this->model_catalog_product->getRewards($master_id);
631: }
632:
633: // SEO
634: // product_seo table is not overwritten because that needs to have unique seo keywords for every product
635:
636: // Specials
637: if (!isset($override['product_special'])) {
638: $product_data['product_special'] = $this->model_catalog_product->getSpecials($master_id);
639: }
640:
641: // Stores
642: if (!isset($override['product_store'])) {
643: $product_data['product_store'] = $this->model_catalog_product->getStores($master_id);
644: }
645: }
646:
647: // If override set the POST data values
648: foreach ($data as $key => $value) {
649: if (!isset($product_data[$key])) {
650: $product_data[$key] = $value;
651: }
652: }
653:
654: // Product Description
655: if (isset($data['product_description'])) {
656: foreach ($data['product_description'] as $language_id => $product_description) {
657: foreach ($product_description as $key => $value) {
658: if (!isset($product_data['product_description'][$language_id][$key])) {
659: $product_data['product_description'][$language_id][$key] = $value;
660: }
661: }
662: }
663: }
664:
665: // Override the variant product data with the master product values
666: $this->model_catalog_product->editProduct($product_id, $product_data);
667: }
668:
669: /**
670: * Edit Variants
671: *
672: * @param int $master_id
673: * @param array<string, mixed> $data
674: *
675: * @return void
676: */
677: public function editVariants(int $master_id, array $data): void {
678: // product_option should not be passed to product variants
679: unset($data['product_option']);
680:
681: // If product is master update variants
682: $products = $this->model_catalog_product->getProducts(['filter_master_id' => $master_id]);
683:
684: foreach ($products as $product) {
685: $product_data = [];
686:
687: // We need to convert JSON strings back into an array so they can be re-encoded to a string to go back into the database.
688: $product['override'] = (array)json_decode($product['override'], true);
689: $product['variant'] = (array)json_decode($product['variant'], true);
690:
691: // We use the override to override the master product values
692: if ($product['override']) {
693: $override = $product['override'];
694: } else {
695: $override = [];
696: }
697:
698: $replace = [
699: 'product_id',
700: 'master_id',
701: 'quantity',
702: 'override',
703: 'variant'
704: ];
705:
706: // Now we want to
707: foreach ($product as $key => $value) {
708: // So if key not in override or ignore list we replace with master value
709: if (array_key_exists($key, $override) || in_array($key, $replace)) {
710: $product_data[$key] = $value;
711: }
712: }
713:
714: // Descriptions
715: $product_descriptions = $this->model_catalog_product->getDescriptions($product['product_id']);
716:
717: foreach ($product_descriptions as $language_id => $product_description) {
718: foreach ($product_description as $key => $value) {
719: // If override set use the POST data values
720: if (isset($override['product_description'][$language_id][$key])) {
721: $product_data['product_description'][$language_id][$key] = $value;
722: }
723: }
724: }
725:
726: // Attributes
727: if (isset($override['product_attribute'])) {
728: $product_data['product_attribute'] = $this->model_catalog_product->getAttributes($product['product_id']);
729: }
730:
731: // Category
732: if (isset($override['product_category'])) {
733: $product_data['product_category'] = $this->model_catalog_product->getCategories($product['product_id']);
734: }
735:
736: // Discounts
737: if (isset($override['product_discount'])) {
738: $product_data['product_discount'] = $this->model_catalog_product->getDiscounts($product['product_id']);
739: }
740:
741: // Downloads
742: if (isset($override['product_download'])) {
743: $product_data['product_download'] = $this->model_catalog_product->getDownloads($product['product_id']);
744: }
745:
746: // Filters
747: if (isset($override['product_filter'])) {
748: $product_data['product_filter'] = $this->model_catalog_product->getFilters($product['product_id']);
749: }
750:
751: // Images
752: if (isset($override['product_image'])) {
753: $product_data['product_image'] = $this->model_catalog_product->getImages($product['product_id']);
754: }
755:
756: // Layouts
757: if (isset($override['product_layout'])) {
758: $product_data['product_layout'] = $this->model_catalog_product->getLayouts($product['product_id']);
759: }
760:
761: // Subscription
762: if (isset($override['product_subscription'])) {
763: $product_data['product_subscription'] = $this->model_catalog_product->getSubscriptions($product['product_id']);
764: }
765:
766: // Related
767: if (isset($override['product_related'])) {
768: $product_data['product_related'] = $this->model_catalog_product->getRelated($product['product_id']);
769: }
770:
771: // Rewards
772: if (isset($override['product_reward'])) {
773: $product_data['product_reward'] = $this->model_catalog_product->getRewards($product['product_id']);
774: }
775:
776: // SEO
777: $product_data['product_seo_url'] = $this->model_catalog_product->getSeoUrls($product['product_id']);
778:
779: // Specials
780: if (isset($override['product_special'])) {
781: $product_data['product_special'] = $this->model_catalog_product->getSpecials($product['product_id']);
782: }
783:
784: // Stores
785: if (isset($override['product_store'])) {
786: $product_data['product_store'] = $this->model_catalog_product->getStores($product['product_id']);
787: }
788:
789: // If override set the POST data values
790: foreach ($data as $key => $value) {
791: if (!isset($product_data[$key])) {
792: $product_data[$key] = $value;
793: }
794: }
795:
796: // Descriptions
797: if (isset($data['product_description'])) {
798: foreach ($data['product_description'] as $language_id => $product_description) {
799: foreach ($product_description as $key => $value) {
800: // If override set use the POST data values
801: if (!isset($product_data['product_description'][$language_id][$key])) {
802: $product_data['product_description'][$language_id][$key] = $value;
803: }
804: }
805: }
806: }
807:
808: $this->model_catalog_product->editProduct($product['product_id'], $product_data);
809: }
810: }
811:
812: /**
813: * Edit Rating
814: *
815: * @param int $product_id
816: * @param int $rating
817: *
818: * @return void
819: */
820: public function editRating(int $product_id, int $rating): void {
821: $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `rating` = '" . (int)$rating . "', `date_modified` = NOW() WHERE `product_id` = '" . (int)$product_id . "'");
822: }
823:
824: /**
825: * Edit Master ID
826: *
827: * @param int $product_id
828: * @param int $master_id
829: *
830: * @return void
831: */
832: public function editMasterId(int $product_id, int $master_id): void {
833: $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `master_id` = '" . (int)$master_id . "', `date_modified` = NOW() WHERE `product_id` = '" . (int)$product_id . "'");
834: }
835:
836: /**
837: * Get Product
838: *
839: * @param int $product_id
840: *
841: * @return array<string, mixed>
842: */
843: public function getProduct(int $product_id): array {
844: $product_data = [];
845:
846: $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "product` `p` LEFT JOIN `" . DB_PREFIX . "product_description` `pd` ON (`p`.`product_id` = `pd`.`product_id`) WHERE `p`.`product_id` = '" . (int)$product_id . "' AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'");
847:
848: if ($query->num_rows) {
849: $product_data = $query->row;
850:
851: $product_data['variant'] = json_decode($product_data['variant'], true);
852: $product_data['override'] = json_decode($product_data['override'], true);
853: }
854:
855: return $product_data;
856: }
857:
858: /**
859: * Get Products
860: *
861: * @param array<string, mixed> $data
862: *
863: * @return array<int, array<string, mixed>>
864: */
865: public function getProducts(array $data = []): array {
866: $sql = "SELECT * FROM `" . DB_PREFIX . "product` `p` LEFT JOIN `" . DB_PREFIX . "product_description` `pd` ON (`p`.`product_id` = `pd`.`product_id`) WHERE `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
867:
868: if (!empty($data['filter_master_id'])) {
869: $sql .= " AND `p`.`master_id` = '" . (int)$data['filter_master_id'] . "'";
870: }
871:
872: if (!empty($data['filter_name'])) {
873: $sql .= " AND LCASE(`pd`.`name`) LIKE '" . $this->db->escape(oc_strtolower($data['filter_name']) . '%') . "'";
874: }
875:
876: if (!empty($data['filter_model'])) {
877: $sql .= " AND LCASE(`p`.`model`) LIKE '" . $this->db->escape(oc_strtolower($data['filter_model']) . '%') . "'";
878: }
879:
880: if (!empty($data['filter_price'])) {
881: $sql .= " AND `p`.`price` LIKE '" . (float)$data['filter_price'] . "'";
882: }
883:
884: if (isset($data['filter_quantity']) && $data['filter_quantity'] !== '') {
885: $sql .= " AND `p`.`quantity` = '" . (int)$data['filter_quantity'] . "'";
886: }
887:
888: if (isset($data['filter_status']) && $data['filter_status'] !== '') {
889: $sql .= " AND `p`.`status` = '" . (int)$data['filter_status'] . "'";
890: }
891:
892: $sql .= " GROUP BY `p`.`product_id`";
893:
894: $sort_data = [
895: 'pd.name',
896: 'p.model',
897: 'p.price',
898: 'p.quantity',
899: 'p.status',
900: 'p.sort_order'
901: ];
902:
903: if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
904: $sql .= " ORDER BY " . $data['sort'];
905: } else {
906: $sql .= " ORDER BY `pd`.`name`";
907: }
908:
909: if (isset($data['order']) && ($data['order'] == 'DESC')) {
910: $sql .= " DESC";
911: } else {
912: $sql .= " ASC";
913: }
914:
915: if (isset($data['start']) || isset($data['limit'])) {
916: if ($data['start'] < 0) {
917: $data['start'] = 0;
918: }
919:
920: if ($data['limit'] < 1) {
921: $data['limit'] = 20;
922: }
923:
924: $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
925: }
926:
927: $product_data = [];
928:
929: $query = $this->db->query($sql);
930:
931: foreach ($query->rows as $key => $result) {
932: $product_data[$key] = $result;
933:
934: $product_data[$key]['variant'] = json_decode($result['variant'], true);
935: $product_data[$key]['override'] = json_decode($result['override'], true);
936: }
937:
938: return $product_data;
939: }
940:
941: /**
942: * Get Total Products
943: *
944: * @param array<string, mixed> $data
945: *
946: * @return int
947: */
948: public function getTotalProducts(array $data = []): int {
949: $sql = "SELECT COUNT(DISTINCT `p`.`product_id`) AS `total` FROM `" . DB_PREFIX . "product` `p` LEFT JOIN `" . DB_PREFIX . "product_description` `pd` ON (`p`.`product_id` = `pd`.`product_id`) WHERE `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
950:
951: if (!empty($data['filter_master_id'])) {
952: $sql .= " AND `p`.`master_id` = '" . (int)$data['filter_master_id'] . "'";
953: }
954:
955: if (!empty($data['filter_name'])) {
956: $sql .= " AND LCASE(`pd`.`name`) LIKE '" . $this->db->escape(oc_strtolower($data['filter_name']) . '%') . "'";
957: }
958:
959: if (!empty($data['filter_model'])) {
960: $sql .= " AND LCASE(`p`.`model`) LIKE '" . $this->db->escape(oc_strtolower($data['filter_model']) . '%') . "'";
961: }
962:
963: if (isset($data['filter_price']) && $data['filter_price'] !== '') {
964: $sql .= " AND `p`.`price` LIKE '" . (float)$data['filter_price'] . "'";
965: }
966:
967: if (isset($data['filter_quantity']) && $data['filter_quantity'] !== '') {
968: $sql .= " AND `p`.`quantity` = '" . (int)$data['filter_quantity'] . "'";
969: }
970:
971: if (isset($data['filter_status']) && $data['filter_status'] !== '') {
972: $sql .= " AND `p`.`status` = '" . (int)$data['filter_status'] . "'";
973: }
974:
975: $query = $this->db->query($sql);
976:
977: return (int)$query->row['total'];
978: }
979:
980: /**
981: * Get Total Products By Manufacturer ID
982: *
983: * @param int $manufacturer_id
984: *
985: * @return int
986: */
987: public function getTotalProductsByManufacturerId(int $manufacturer_id): int {
988: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'");
989:
990: return (int)$query->row['total'];
991: }
992:
993: /**
994: * Get Total Products By Tax Class ID
995: *
996: * @param int $tax_class_id
997: *
998: * @return int
999: */
1000: public function getTotalProductsByTaxClassId(int $tax_class_id): int {
1001: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `tax_class_id` = '" . (int)$tax_class_id . "'");
1002:
1003: return (int)$query->row['total'];
1004: }
1005:
1006: /**
1007: * Get Total Products By Stock Status ID
1008: *
1009: * @param int $stock_status_id
1010: *
1011: * @return int
1012: */
1013: public function getTotalProductsByStockStatusId(int $stock_status_id): int {
1014: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `stock_status_id` = '" . (int)$stock_status_id . "'");
1015:
1016: return (int)$query->row['total'];
1017: }
1018:
1019: /**
1020: * Get Total Products By Weight Class ID
1021: *
1022: * @param int $weight_class_id
1023: *
1024: * @return int
1025: */
1026: public function getTotalProductsByWeightClassId(int $weight_class_id): int {
1027: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `weight_class_id` = '" . (int)$weight_class_id . "'");
1028:
1029: return (int)$query->row['total'];
1030: }
1031:
1032: /**
1033: * Get Total Products By Length Class ID
1034: *
1035: * @param int $length_class_id
1036: *
1037: * @return int
1038: */
1039: public function getTotalProductsByLengthClassId(int $length_class_id): int {
1040: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `length_class_id` = '" . (int)$length_class_id . "'");
1041:
1042: return (int)$query->row['total'];
1043: }
1044:
1045: /**
1046: * Add Description
1047: *
1048: * @param int $product_id
1049: * @param int $language_id
1050: * @param array<string, mixed> $data
1051: *
1052: * @return void
1053: */
1054: public function addDescription(int $product_id, int $language_id, array $data): void {
1055: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_description` SET `product_id` = '" . (int)$product_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($data['name']) . "', `description` = '" . $this->db->escape($data['description']) . "', `tag` = '" . $this->db->escape($data['tag']) . "', `meta_title` = '" . $this->db->escape($data['meta_title']) . "', `meta_description` = '" . $this->db->escape($data['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($data['meta_keyword']) . "'");
1056: }
1057:
1058: /**
1059: * Delete Description
1060: *
1061: * @param int $product_id
1062: *
1063: * @return void
1064: */
1065: public function deleteDescriptions(int $product_id): void {
1066: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_description` WHERE `product_id` = '" . (int)$product_id . "'");
1067: }
1068:
1069: /**
1070: * Delete Descriptions By Language ID
1071: *
1072: * @param int $language_id
1073: *
1074: * @return void
1075: */
1076: public function deleteDescriptionsByLanguageId(int $language_id): void {
1077: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_description` WHERE `language_id` = '" . (int)$language_id . "'");
1078: }
1079:
1080: /**
1081: * Get Descriptions
1082: *
1083: * @param int $product_id
1084: *
1085: * @return array<int, array<string, mixed>>
1086: */
1087: public function getDescriptions(int $product_id): array {
1088: $product_description_data = [];
1089:
1090: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_description` WHERE `product_id` = '" . (int)$product_id . "'");
1091:
1092: foreach ($query->rows as $result) {
1093: $product_description_data[$result['language_id']] = [
1094: 'name' => $result['name'],
1095: 'description' => $result['description'],
1096: 'meta_title' => $result['meta_title'],
1097: 'meta_description' => $result['meta_description'],
1098: 'meta_keyword' => $result['meta_keyword'],
1099: 'tag' => $result['tag']
1100: ];
1101: }
1102:
1103: return $product_description_data;
1104: }
1105:
1106: /**
1107: * Get Descriptions By Language ID
1108: *
1109: * @param int $language_id
1110: *
1111: * @return array<int, array<string, string>>
1112: */
1113: public function getDescriptionsByLanguageId(int $language_id): array {
1114: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_description` WHERE `language_id` = '" . (int)$language_id . "'");
1115:
1116: return $query->rows;
1117: }
1118:
1119: /**
1120: * Add Category
1121: *
1122: * @param int $product_id
1123: * @param int $category_id
1124: *
1125: * @return void
1126: */
1127: public function addCategory(int $product_id, int $category_id): void {
1128: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_category` SET `product_id` = '" . (int)$product_id . "', `category_id` = '" . (int)$category_id . "'");
1129: }
1130:
1131: /**
1132: * Delete Categories
1133: *
1134: * @param int $product_id
1135: *
1136: * @return void
1137: */
1138: public function deleteCategories(int $product_id): void {
1139: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_category` WHERE `product_id` = '" . (int)$product_id . "'");
1140: }
1141:
1142: /**
1143: * Delete Categories By Category ID
1144: *
1145: * @param int $category_id
1146: *
1147: * @return void
1148: */
1149: public function deleteCategoriesByCategoryId(int $category_id): void {
1150: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_category` WHERE `category_id` = '" . (int)$category_id . "'");
1151: }
1152:
1153: /**
1154: * Get Categories
1155: *
1156: * @param int $product_id
1157: *
1158: * @return array<int, int>
1159: */
1160: public function getCategories(int $product_id): array {
1161: $product_category_data = [];
1162:
1163: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_category` WHERE `product_id` = '" . (int)$product_id . "'");
1164:
1165: foreach ($query->rows as $result) {
1166: $product_category_data[] = $result['category_id'];
1167: }
1168:
1169: return $product_category_data;
1170: }
1171:
1172: /**
1173: * Add Filter
1174: *
1175: * @param int $product_id
1176: * @param int $filter_id
1177: *
1178: * @return void
1179: */
1180: public function addFilter(int $product_id, int $filter_id): void {
1181: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_filter` SET `product_id` = '" . (int)$product_id . "', `filter_id` = '" . (int)$filter_id . "'");
1182: }
1183:
1184: /**
1185: * Delete Filters
1186: *
1187: * @param int $product_id
1188: *
1189: * @return void
1190: */
1191: public function deleteFilters(int $product_id): void {
1192: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_filter` WHERE `product_id` = '" . (int)$product_id . "'");
1193: }
1194:
1195: /**
1196: * Get Filters
1197: *
1198: * @param int $product_id
1199: *
1200: * @return array<int, int>
1201: */
1202: public function getFilters(int $product_id): array {
1203: $product_filter_data = [];
1204:
1205: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_filter` WHERE `product_id` = '" . (int)$product_id . "'");
1206:
1207: foreach ($query->rows as $result) {
1208: $product_filter_data[] = $result['filter_id'];
1209: }
1210:
1211: return $product_filter_data;
1212: }
1213:
1214: /**
1215: * Add Attribute
1216: *
1217: * @param int $product_id primary key of the attribute record to be fetched
1218: * @param int $attribute_id
1219: * @param int $language_id
1220: * @param array<string, mixed> $data
1221: *
1222: * @return void
1223: */
1224: public function addAttribute(int $product_id, int $attribute_id, int $language_id, array $data): void {
1225: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_attribute` SET `product_id` = '" . (int)$product_id . "', `attribute_id` = '" . (int)$attribute_id . "', `language_id` = '" . (int)$language_id . "', `text` = '" . $this->db->escape($data['text']) . "'");
1226: }
1227:
1228: /**
1229: * Delete Attributes
1230: *
1231: * @param int $product_id primary key of the product record to be fetched
1232: * @param int $attribute_id
1233: *
1234: * @return void
1235: */
1236: public function deleteAttributes(int $product_id, int $attribute_id = 0): void {
1237: $sql = "DELETE FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "'";
1238:
1239: if ($attribute_id) {
1240: $sql .= " AND `attribute_id` = '" . (int)$attribute_id . "'";
1241: }
1242:
1243: $this->db->query($sql);
1244: }
1245:
1246: /**
1247: * Delete Attributes By Language ID
1248: *
1249: * @param int $language_id
1250: *
1251: * @return void
1252: */
1253: public function deleteAttributesByLanguageId(int $language_id): void {
1254: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_attribute` WHERE `language_id` = '" . (int)$language_id . "'");
1255: }
1256:
1257: /**
1258: * Get Attributes
1259: *
1260: * @param int $product_id
1261: *
1262: * @return array<int, array<string, mixed>>
1263: */
1264: public function getAttributes(int $product_id): array {
1265: $product_attribute_data = [];
1266:
1267: $product_attribute_query = $this->db->query("SELECT `attribute_id` FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "' GROUP BY `attribute_id`");
1268:
1269: foreach ($product_attribute_query->rows as $product_attribute) {
1270: $product_attribute_description_data = [];
1271:
1272: $product_attribute_description_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "' AND `attribute_id` = '" . (int)$product_attribute['attribute_id'] . "'");
1273:
1274: foreach ($product_attribute_description_query->rows as $product_attribute_description) {
1275: $product_attribute_description_data[$product_attribute_description['language_id']] = ['text' => $product_attribute_description['text']];
1276: }
1277:
1278: $product_attribute_data[] = [
1279: 'attribute_id' => $product_attribute['attribute_id'],
1280: 'product_attribute_description' => $product_attribute_description_data
1281: ];
1282: }
1283:
1284: return $product_attribute_data;
1285: }
1286:
1287: /**
1288: * Get Attributes By Language ID
1289: *
1290: * @param int $language_id
1291: *
1292: * @return array<int, array<string, mixed>>
1293: */
1294: public function getAttributesByLanguageId(int $language_id): array {
1295: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_attribute` WHERE `language_id` = '" . (int)$language_id . "'");
1296:
1297: return $query->rows;
1298: }
1299:
1300: /**
1301: * Get Total Products By Attribute ID
1302: *
1303: * @param int $attribute_id
1304: *
1305: * @return int
1306: */
1307: public function getTotalAttributesByAttributeId(int $attribute_id): int {
1308: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_attribute` WHERE `attribute_id` = '" . (int)$attribute_id . "'");
1309:
1310: return (int)$query->row['total'];
1311: }
1312:
1313: /**
1314: * Add Option
1315: *
1316: * @param int $product_id primary key of the attribute record to be fetched
1317: * @param array<string, mixed> $data
1318: *
1319: * @return int
1320: */
1321: public function addOption(int $product_id, array $data): int {
1322: if (isset($data['product_option_value'])) {
1323: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option` SET `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$data['option_id'] . "', `required` = '" . (int)$data['required'] . "'");
1324: } else {
1325: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option` SET `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$data['option_id'] . "', `value` = '" . $this->db->escape($data['value']) . "', `required` = '" . (int)$data['required'] . "'");
1326: }
1327:
1328: $product_option_id = $this->db->getLastId();
1329:
1330: if (isset($data['product_option_value'])) {
1331: foreach ($data['product_option_value'] as $product_option_value) {
1332: $this->model_catalog_product->addOptionValue($product_id, $product_option_id, $data['option_id'], $product_option_value);
1333: }
1334: }
1335:
1336: return $product_option_id;
1337: }
1338:
1339: /**
1340: * Delete Options
1341: *
1342: * @param int $product_id primary key of the product record to be fetched
1343: *
1344: * @return void
1345: */
1346: public function deleteOptions(int $product_id): void {
1347: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_option` WHERE `product_id` = '" . (int)$product_id . "'");
1348:
1349: $this->model_catalog_product->deleteOptionValues($product_id);
1350: }
1351:
1352: /**
1353: * Get Options
1354: *
1355: * @param int $product_id
1356: *
1357: * @return array<int, array<string, mixed>>
1358: */
1359: public function getOptions(int $product_id): array {
1360: $product_option_data = [];
1361:
1362: $product_option_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_option` `po` LEFT JOIN `" . DB_PREFIX . "option` `o` ON (`po`.`option_id` = `o`.`option_id`) LEFT JOIN `" . DB_PREFIX . "option_description` `od` ON (`o`.`option_id` = `od`.`option_id`) WHERE `po`.`product_id` = '" . (int)$product_id . "' AND `od`.`language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `o`.`sort_order` ASC");
1363:
1364: foreach ($product_option_query->rows as $product_option) {
1365: $product_option_value_data = [];
1366:
1367: $product_option_value_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_option_value` `pov` LEFT JOIN `" . DB_PREFIX . "option_value` `ov` ON (`pov`.`option_value_id` = `ov`.`option_value_id`) WHERE `pov`.`product_option_id` = '" . (int)$product_option['product_option_id'] . "' ORDER BY `ov`.`sort_order` ASC");
1368:
1369: foreach ($product_option_value_query->rows as $product_option_value) {
1370: $product_option_value_data[] = [
1371: 'product_option_value_id' => $product_option_value['product_option_value_id'],
1372: 'option_value_id' => $product_option_value['option_value_id'],
1373: 'quantity' => $product_option_value['quantity'],
1374: 'subtract' => $product_option_value['subtract'],
1375: 'price' => $product_option_value['price'],
1376: 'price_prefix' => $product_option_value['price_prefix'],
1377: 'points' => $product_option_value['points'],
1378: 'points_prefix' => $product_option_value['points_prefix'],
1379: 'weight' => $product_option_value['weight'],
1380: 'weight_prefix' => $product_option_value['weight_prefix']
1381: ];
1382: }
1383:
1384: $product_option_data[] = [
1385: 'product_option_id' => $product_option['product_option_id'],
1386: 'product_option_value' => $product_option_value_data,
1387: 'option_id' => $product_option['option_id'],
1388: 'name' => $product_option['name'],
1389: 'type' => $product_option['type'],
1390: 'value' => $product_option['value'],
1391: 'required' => $product_option['required']
1392: ];
1393: }
1394:
1395: return $product_option_data;
1396: }
1397:
1398: /**
1399: * Get Total Options By Option ID
1400: *
1401: * @param int $option_id
1402: *
1403: * @return int
1404: */
1405: public function getTotalOptionsByOptionId(int $option_id): int {
1406: $query = $this->db->query("SELECT COUNT(DISTINCT `product_id`) AS `total` FROM `" . DB_PREFIX . "product_option` WHERE `option_id` = '" . (int)$option_id . "'");
1407:
1408: return (int)$query->row['total'];
1409: }
1410:
1411: /**
1412: * Add Option Value
1413: *
1414: * @param int $product_id primary key of the attribute record to be fetched
1415: * @param int $product_option_id
1416: * @param int $option_id
1417: * @param array<string, mixed> $data
1418: *
1419: * @return int
1420: */
1421: public function addOptionValue(int $product_id, int $product_option_id, int $option_id, array $data): int {
1422: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option_value` SET `product_option_id` = '" . (int)$product_option_id . "', `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$option_id . "', `option_value_id` = '" . (int)$data['option_value_id'] . "', `quantity` = '" . (int)$data['quantity'] . "', `subtract` = '" . (int)$data['subtract'] . "', `price` = '" . (float)$data['price'] . "', `price_prefix` = '" . $this->db->escape($data['price_prefix']) . "', `points` = '" . (int)$data['points'] . "', `points_prefix` = '" . $this->db->escape($data['points_prefix']) . "', `weight` = '" . (float)$data['weight'] . "', `weight_prefix` = '" . $this->db->escape($data['weight_prefix']) . "'");
1423:
1424: return $this->db->getLastId();
1425: }
1426:
1427: /**
1428: * Delete Option Values
1429: *
1430: * @param int $product_id primary key of the product record to be fetched
1431: *
1432: * @return void
1433: */
1434: public function deleteOptionValues(int $product_id): void {
1435: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_option_value` WHERE `product_id` = '" . (int)$product_id . "'");
1436: }
1437:
1438: /**
1439: * Get Option Value
1440: *
1441: * @param int $product_id
1442: * @param int $product_option_value_id
1443: *
1444: * @return array<string, mixed>
1445: */
1446: public function getOptionValue(int $product_id, int $product_option_value_id): array {
1447: $query = $this->db->query("SELECT `pov`.`option_value_id`, `ovd`.`name`, `pov`.`quantity`, `pov`.`subtract`, `pov`.`price`, `pov`.`price_prefix`, `pov`.`points`, `pov`.`points_prefix`, `pov`.`weight`, `pov`.`weight_prefix` FROM `" . DB_PREFIX . "product_option_value` `pov` LEFT JOIN `" . DB_PREFIX . "option_value` `ov` ON (`pov`.`option_value_id` = `ov`.`option_value_id`) LEFT JOIN `" . DB_PREFIX . "option_value_description` `ovd` ON (`ov`.`option_value_id` = `ovd`.`option_value_id`) WHERE `pov`.`product_id` = '" . (int)$product_id . "' AND `pov`.`product_option_value_id` = '" . (int)$product_option_value_id . "' AND `ovd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'");
1448:
1449: return $query->row;
1450: }
1451:
1452: /**
1453: * Get Option Values By Option ID
1454: *
1455: * @param int $option_id
1456: *
1457: * @return array<int, array<string, mixed>>
1458: */
1459: public function getOptionValuesByOptionId(int $option_id): array {
1460: $query = $this->db->query("SELECT DISTINCT `option_value_id` FROM `" . DB_PREFIX . "product_option_value` WHERE `option_id` = '" . (int)$option_id . "'");
1461:
1462: return $query->rows;
1463: }
1464:
1465: /**
1466: * Get Total Option Values By Option Value ID
1467: *
1468: * @param int $option_value_id
1469: *
1470: * @return int
1471: */
1472: public function getTotalOptionValuesByOptionValueId(int $option_value_id): int {
1473: $query = $this->db->query("SELECT COUNT(DISTINCT `product_id`) AS `total` FROM `" . DB_PREFIX . "product_option_value` WHERE `option_value_id` = '" . (int)$option_value_id . "'");
1474:
1475: return (int)$query->row['total'];
1476: }
1477:
1478: /**
1479: * Add Image
1480: *
1481: * @param int $product_id primary key of the product record to be fetched
1482: * @param array<string, mixed> $data
1483: *
1484: * @return void
1485: */
1486: public function addImage(int $product_id, array $data): void {
1487: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_image` SET `product_id` = '" . (int)$product_id . "', `image` = '" . $this->db->escape($data['image']) . "', `sort_order` = '" . (int)$data['sort_order'] . "'");
1488: }
1489:
1490: /**
1491: * Delete Images
1492: *
1493: * @param int $product_id primary key of the product record to be fetched
1494: *
1495: * @return void
1496: */
1497: public function deleteImages(int $product_id): void {
1498: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_image` WHERE `product_id` = '" . (int)$product_id . "'");
1499: }
1500:
1501: /**
1502: * Get Images
1503: *
1504: * @param int $product_id
1505: *
1506: * @return array<int, array<string, mixed>>
1507: */
1508: public function getImages(int $product_id): array {
1509: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_image` WHERE `product_id` = '" . (int)$product_id . "' ORDER BY `sort_order` ASC");
1510:
1511: return $query->rows;
1512: }
1513:
1514: /**
1515: * Add Discount
1516: *
1517: * @param int $product_id primary key of the product record to be fetched
1518: * @param array<string, mixed> $data
1519: *
1520: * @return void
1521: */
1522: public function addDiscount(int $product_id, array $data): void {
1523: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_discount` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$data['customer_group_id'] . "', `quantity` = '" . (int)$data['quantity'] . "', `priority` = '" . (int)$data['priority'] . "', `price` = '" . (float)$data['price'] . "', `date_start` = '" . $this->db->escape($data['date_start']) . "', `date_end` = '" . $this->db->escape($data['date_end']) . "'");
1524: }
1525:
1526: /**
1527: * Delete Discounts
1528: *
1529: * @param int $product_id primary key of the product record to be fetched
1530: *
1531: * @return void
1532: */
1533: public function deleteDiscounts(int $product_id): void {
1534: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_discount` WHERE `product_id` = '" . (int)$product_id . "'");
1535: }
1536:
1537: /**
1538: * Get Discounts
1539: *
1540: * @param int $product_id
1541: *
1542: * @return array<int, array<string, mixed>>
1543: */
1544: public function getDiscounts(int $product_id): array {
1545: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_discount` WHERE `product_id` = '" . (int)$product_id . "' ORDER BY `quantity`, `priority`, `price`");
1546:
1547: return $query->rows;
1548: }
1549:
1550: /**
1551: * Add Special
1552: *
1553: * @param int $product_id primary key of the product record to be fetched
1554: * @param array<string, mixed> $data
1555: *
1556: * @return void
1557: */
1558: public function addSpecial(int $product_id, array $data): void {
1559: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_special` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$data['customer_group_id'] . "', `priority` = '" . (int)$data['priority'] . "', `price` = '" . (float)$data['price'] . "', `date_start` = '" . $this->db->escape($data['date_start']) . "', `date_end` = '" . $this->db->escape($data['date_end']) . "'");
1560: }
1561:
1562: /**
1563: * Delete Specials
1564: *
1565: * @param int $product_id primary key of the product record to be fetched
1566: *
1567: * @return void
1568: */
1569: public function deleteSpecials(int $product_id): void {
1570: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_special` WHERE `product_id` = '" . (int)$product_id . "'");
1571: }
1572:
1573: /**
1574: * Get Specials
1575: *
1576: * @param int $product_id
1577: *
1578: * @return array<int, array<string, mixed>>
1579: */
1580: public function getSpecials(int $product_id): array {
1581: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_special` WHERE `product_id` = '" . (int)$product_id . "' ORDER BY `priority`, `price`");
1582:
1583: return $query->rows;
1584: }
1585:
1586: /**
1587: * Add Reward
1588: *
1589: * @param int $product_id primary key of the product record to be fetched
1590: * @param int $customer_group_id
1591: * @param array<string, mixed> $data
1592: *
1593: * @return void
1594: */
1595: public function addReward(int $product_id, int $customer_group_id, array $data): void {
1596: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_reward` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$customer_group_id . "', `points` = '" . (int)$data['points'] . "'");
1597: }
1598:
1599: /**
1600: * Delete Rewards
1601: *
1602: * @param int $product_id primary key of the product record to be fetched
1603: *
1604: * @return void
1605: */
1606: public function deleteRewards(int $product_id): void {
1607: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_reward` WHERE `product_id` = '" . (int)$product_id . "'");
1608: }
1609:
1610: /**
1611: * Get Rewards
1612: *
1613: * @param int $product_id
1614: *
1615: * @return array<int, array<string, mixed>>
1616: */
1617: public function getRewards(int $product_id): array {
1618: $product_reward_data = [];
1619:
1620: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_reward` WHERE `product_id` = '" . (int)$product_id . "'");
1621:
1622: foreach ($query->rows as $result) {
1623: $product_reward_data[$result['customer_group_id']] = ['points' => $result['points']];
1624: }
1625:
1626: return $product_reward_data;
1627: }
1628:
1629: /**
1630: * Add Download
1631: *
1632: * @param int $product_id primary key of the product record to be fetched
1633: * @param int $download_id
1634: *
1635: * @return void
1636: */
1637: public function addDownload(int $product_id, int $download_id): void {
1638: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_download` SET `product_id` = '" . (int)$product_id . "', `download_id` = '" . (int)$download_id . "'");
1639: }
1640:
1641: /**
1642: * Delete Downloads
1643: *
1644: * @param int $product_id primary key of the product record to be fetched
1645: *
1646: * @return void
1647: */
1648: public function deleteDownloads(int $product_id): void {
1649: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_download` WHERE `product_id` = '" . (int)$product_id . "'");
1650: }
1651:
1652: /**
1653: * Get Downloads
1654: *
1655: * @param int $product_id
1656: *
1657: * @return array<int, int>
1658: */
1659: public function getDownloads(int $product_id): array {
1660: $product_download_data = [];
1661:
1662: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_download` WHERE `product_id` = '" . (int)$product_id . "'");
1663:
1664: foreach ($query->rows as $result) {
1665: $product_download_data[] = $result['download_id'];
1666: }
1667:
1668: return $product_download_data;
1669: }
1670:
1671: /**
1672: * Get Total Downloads By Download ID
1673: *
1674: * @param int $download_id
1675: *
1676: * @return int
1677: */
1678: public function getTotalDownloadsByDownloadId(int $download_id): int {
1679: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_to_download` WHERE `download_id` = '" . (int)$download_id . "'");
1680:
1681: return (int)$query->row['total'];
1682: }
1683:
1684: /**
1685: * Add Store
1686: *
1687: * @param int $product_id
1688: * @param int $store_id
1689: *
1690: * @return void
1691: */
1692: public function addStore(int $product_id, int $store_id): void {
1693: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_store` SET `product_id` = '" . (int)$product_id . "', `store_id` = '" . (int)$store_id . "'");
1694: }
1695:
1696: /**
1697: * Delete Stores
1698: *
1699: * @param int $product_id
1700: *
1701: * @return void
1702: */
1703: public function deleteStores(int $product_id): void {
1704: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_store` WHERE `product_id` = '" . (int)$product_id . "'");
1705: }
1706:
1707: /**
1708: * Get Stores
1709: *
1710: * @param int $product_id
1711: *
1712: * @return array<int, int>
1713: */
1714: public function getStores(int $product_id): array {
1715: $product_store_data = [];
1716:
1717: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_store` WHERE `product_id` = '" . (int)$product_id . "'");
1718:
1719: foreach ($query->rows as $result) {
1720: $product_store_data[] = $result['store_id'];
1721: }
1722:
1723: return $product_store_data;
1724: }
1725:
1726: /**
1727: * Add Layout
1728: *
1729: * @param int $product_id
1730: * @param int $store_id
1731: * @param int $layout_id
1732: *
1733: * @return void
1734: */
1735: public function addLayout(int $product_id, int $store_id, int $layout_id): void {
1736: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_layout` SET `product_id` = '" . (int)$product_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'");
1737: }
1738:
1739: /**
1740: * Delete Layouts
1741: *
1742: * @param int $product_id
1743: *
1744: * @return void
1745: */
1746: public function deleteLayouts(int $product_id): void {
1747: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_layout` WHERE `product_id` = '" . (int)$product_id . "'");
1748: }
1749:
1750: /**
1751: * Delete Layouts By Layout ID
1752: *
1753: * @param int $layout_id
1754: *
1755: * @return void
1756: */
1757: public function deleteLayoutsByLayoutId(int $layout_id): void {
1758: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'");
1759: }
1760:
1761: /**
1762: * Delete Layouts By Store ID
1763: *
1764: * @param int $store_id
1765: *
1766: * @return void
1767: */
1768: public function deleteLayoutsByStoreId(int $store_id): void {
1769: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_layout` WHERE `store_id` = '" . (int)$store_id . "'");
1770: }
1771:
1772: /**
1773: * Get Layouts
1774: *
1775: * @param int $product_id
1776: *
1777: * @return array<int, int>
1778: */
1779: public function getLayouts(int $product_id): array {
1780: $product_layout_data = [];
1781:
1782: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_layout` WHERE `product_id` = '" . (int)$product_id . "'");
1783:
1784: foreach ($query->rows as $result) {
1785: $product_layout_data[$result['store_id']] = $result['layout_id'];
1786: }
1787:
1788: return $product_layout_data;
1789: }
1790:
1791: /**
1792: * Get Total Products By Layout ID
1793: *
1794: * @param int $layout_id
1795: *
1796: * @return int
1797: */
1798: public function getTotalLayoutsByLayoutId(int $layout_id): int {
1799: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'");
1800:
1801: return (int)$query->row['total'];
1802: }
1803:
1804: /**
1805: * Add Related
1806: *
1807: * @param int $product_id primary key of the product record to be fetched
1808: * @param int $related_id
1809: *
1810: * @return void
1811: */
1812: public function addRelated(int $product_id, int $related_id): void {
1813: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$product_id . "' AND `related_id` = '" . (int)$related_id . "'");
1814: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_related` SET `product_id` = '" . (int)$product_id . "', `related_id` = '" . (int)$related_id . "'");
1815: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$related_id . "' AND `related_id` = '" . (int)$product_id . "'");
1816: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_related` SET `product_id` = '" . (int)$related_id . "', `related_id` = '" . (int)$product_id . "'");
1817: }
1818:
1819: /**
1820: * Delete Related
1821: *
1822: * @param int $product_id primary key of the product record to be fetched
1823: *
1824: * @return void
1825: */
1826: public function deleteRelated(int $product_id): void {
1827: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$product_id . "'");
1828: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `related_id` = '" . (int)$product_id . "'");
1829: }
1830:
1831: /**
1832: * Get Related
1833: *
1834: * @param int $product_id
1835: *
1836: * @return array<int, int>
1837: */
1838: public function getRelated(int $product_id): array {
1839: $product_related_data = [];
1840:
1841: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$product_id . "'");
1842:
1843: foreach ($query->rows as $result) {
1844: $product_related_data[] = $result['related_id'];
1845: }
1846:
1847: return $product_related_data;
1848: }
1849:
1850: /**
1851: * Add Subscription
1852: *
1853: * @param int $product_id
1854: * @param array<string, mixed> $data
1855: */
1856: public function addSubscription(int $product_id, array $data): void {
1857: $query = $this->db->query("SELECT `product_id` FROM `" . DB_PREFIX . "product_subscription` WHERE `product_id` = '" . (int)$product_id . "' AND `customer_group_id` = '" . (int)$data['customer_group_id'] . "' AND `subscription_plan_id` = '" . (int)$data['subscription_plan_id'] . "'");
1858:
1859: if (!$query->num_rows) {
1860: $this->db->query("INSERT INTO `" . DB_PREFIX . "product_subscription` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$data['customer_group_id'] . "', `subscription_plan_id` = '" . (int)$data['subscription_plan_id'] . "', `trial_price` = '" . (float)$data['trial_price'] . "', `price` = '" . (float)$data['price'] . "'");
1861: }
1862: }
1863:
1864: /**
1865: * Delete Subscriptions
1866: *
1867: * @param int $product_id
1868: *
1869: * @return void
1870: */
1871: public function deleteSubscriptions(int $product_id): void {
1872: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_subscription` WHERE `product_id` = '" . (int)$product_id . "'");
1873: }
1874:
1875: /**
1876: * Get Subscriptions
1877: *
1878: * @param int $product_id
1879: *
1880: * @return array<int, array<string, mixed>>
1881: */
1882: public function getSubscriptions(int $product_id): array {
1883: $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_subscription` WHERE `product_id` = '" . (int)$product_id . "'");
1884:
1885: return $query->rows;
1886: }
1887:
1888: /**
1889: * Delete Subscriptions By Subscription Plan ID
1890: *
1891: * @param int $subscription_plan_id
1892: *
1893: * @return void
1894: */
1895: public function deleteSubscriptionsBySubscriptionPlanId(int $subscription_plan_id): void {
1896: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_subscription` WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'");
1897: }
1898:
1899: /**
1900: * Get Total Subscriptions By Subscription Plan ID
1901: *
1902: * @param int $subscription_plan_id
1903: *
1904: * @return int
1905: */
1906: public function getTotalSubscriptionsBySubscriptionPlanId(int $subscription_plan_id): int {
1907: $query = $this->db->query("SELECT COUNT(DISTINCT `product_id`) AS `total` FROM `" . DB_PREFIX . "product_subscription` WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'");
1908:
1909: return (int)$query->row['total'];
1910: }
1911:
1912: /**
1913: * Delete Reports
1914: *
1915: * @param int $product_id
1916: *
1917: * @return void
1918: */
1919: public function deleteReports(int $product_id): void {
1920: $this->db->query("DELETE FROM `" . DB_PREFIX . "product_report` WHERE `product_id` = '" . (int)$product_id . "'");
1921: }
1922:
1923: /**
1924: * Get Reports
1925: *
1926: * @param int $product_id
1927: * @param int $start
1928: * @param int $limit
1929: *
1930: * @return array<int, array<string, mixed>>
1931: */
1932: public function getReports(int $product_id, int $start = 0, int $limit = 10): array {
1933: if ($start < 0) {
1934: $start = 0;
1935: }
1936:
1937: if ($limit < 1) {
1938: $limit = 10;
1939: }
1940:
1941: $query = $this->db->query("SELECT `ip`, `store_id`, `country`, `date_added` FROM `" . DB_PREFIX . "product_report` WHERE `product_id` = '" . (int)$product_id . "' ORDER BY `date_added` ASC LIMIT " . (int)$start . "," . (int)$limit);
1942:
1943: return $query->rows;
1944: }
1945:
1946: /**
1947: * Get Total Reports
1948: *
1949: * @param int $product_id
1950: *
1951: * @return int
1952: */
1953: public function getTotalReports(int $product_id): int {
1954: $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_report` WHERE `product_id` = '" . (int)$product_id . "'");
1955:
1956: return (int)$query->row['total'];
1957: }
1958: }
1959: