Skip to content

Commit f13cf55

Browse files
authored
Merge pull request #10 from magefan/12273-configurable-products-compatibility
12273 configurable products compatibility
2 parents e2063ac + a8b4c4a commit f13cf55

File tree

18 files changed

+592
-118
lines changed

18 files changed

+592
-118
lines changed

Controller/Label/Get.php

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
/**
3+
* Copyright © Magefan (support@magefan.com). All rights reserved.
4+
* Please visit Magefan.com for license details (https://magefan.com/end-user-license-agreement).
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magefan\ProductLabel\Controller\Label;
9+
10+
use Magento\Framework\App\Action\Context;
11+
use Magento\Framework\Controller\Result\JsonFactory;
12+
use Magento\Framework\View\Result\PageFactory;
13+
use Magento\Catalog\Model\Product;
14+
use Magefan\ProductLabel\Model\GetLabels;
15+
use Magento\Catalog\Api\ProductRepositoryInterface;
16+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
17+
18+
class Get extends \Magento\Framework\App\Action\Action
19+
{
20+
/**
21+
* @var JsonFactory
22+
*/
23+
protected $jsonResultFactory;
24+
25+
/**
26+
* @var GetLabels
27+
*/
28+
protected $getLabels;
29+
30+
/**
31+
* @var ProductRepositoryInterface
32+
*/
33+
protected $productRepository;
34+
35+
/**
36+
* Get constructor.
37+
* @param Context $context
38+
* @param JsonFactory $jsonResultFactory
39+
* @param GetLabels $getLabels
40+
* @param ProductRepositoryInterface $productRepository
41+
*/
42+
public function __construct(
43+
Context $context,
44+
JsonFactory $jsonResultFactory,
45+
GetLabels $getLabels,
46+
ProductRepositoryInterface $productRepository
47+
) {
48+
parent::__construct($context);
49+
$this->jsonResultFactory = $jsonResultFactory;
50+
$this->getLabels = $getLabels;
51+
$this->productRepository = $productRepository;
52+
}
53+
54+
public function execute()
55+
{
56+
$result = $this->jsonResultFactory->create();
57+
58+
$productIds = $this->getProductIds();
59+
$productIdsForProductPage = $this->getProductIdsForProductPage();
60+
61+
if ($this->getRequest()->getParam('get_children') && isset($this->getProductIds()[0])) {
62+
$productIds = $this->getChildProductIds($this->getProductIds()[0]);
63+
64+
if ($this->getRequest()->getParam('product_page')) {
65+
$productIdsForProductPage = $productIds;
66+
}
67+
}
68+
69+
$replaceMap = $this->getLabels->execute($productIds, $productIdsForProductPage);
70+
71+
$result->setData([
72+
'labels' => $replaceMap
73+
]);
74+
75+
$result->setHeader('X-Magento-Tags', implode(',', $this->getCacheTags()));
76+
77+
return $result;
78+
}
79+
80+
/**
81+
* @return array
82+
*/
83+
private function getCacheTags(): array
84+
{
85+
$tags = [];
86+
87+
foreach ($this->getProductIds() as $productId) {
88+
$tags[] = Product::CACHE_TAG . '_' . $productId;
89+
}
90+
91+
return $tags;
92+
}
93+
94+
/**
95+
* Retrieve and process product IDs from the request.
96+
*
97+
* @param string $paramName
98+
* @return array
99+
*/
100+
private function getProductIdsFromRequest(string $paramName): array
101+
{
102+
$productIds = (string) $this->getRequest()->getParam($paramName, '');
103+
104+
return array_map('intval', explode(',', $productIds));
105+
}
106+
107+
/**
108+
* @return array
109+
*/
110+
private function getProductIds(): array
111+
{
112+
return $this->getProductIdsFromRequest('product_ids');
113+
}
114+
115+
/**
116+
* @return array
117+
*/
118+
private function getProductIdsForProductPage(): array
119+
{
120+
return $this->getProductIdsFromRequest('product_ids_for_product_page');
121+
}
122+
123+
/**
124+
* @param int $parentProductId
125+
* @return array
126+
*/
127+
private function getChildProductIds(int $parentProductId): array
128+
{
129+
$childProductIds = [];
130+
131+
$currentProduct = $this->productRepository->getById($parentProductId);
132+
133+
if ('configurable' != $currentProduct->getTypeId()) {
134+
return $childProductIds;
135+
}
136+
137+
$childProducts = $currentProduct->getTypeInstance()->getUsedProducts($currentProduct, null);
138+
139+
foreach ($childProducts as $childProduct) {
140+
if ((int) $childProduct->getStatus() === Status::STATUS_ENABLED) {
141+
$childProductIds[] = $childProduct->getId();
142+
}
143+
}
144+
145+
return $childProductIds;
146+
}
147+
}

Model/GetLabels.php

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
/**
3+
* Copyright © Magefan (support@magefan.com). All rights reserved.
4+
* Please visit Magefan.com for license details (https://magefan.com/end-user-license-agreement).
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magefan\ProductLabel\Model;
9+
10+
use Magefan\ProductLabel\Model\Config;
11+
use Magento\Store\Model\StoreManagerInterface;
12+
use Magefan\ProductLabel\Model\GetProductIdsToRuleIdsMap;
13+
use Magefan\ProductLabel\Model\ResourceModel\Rule\CollectionFactory as RuleCollectionFactory;
14+
use Magefan\ProductLabel\Api\LabelProcessorInterface;
15+
use Magento\Framework\View\LayoutInterface;
16+
17+
class GetLabels
18+
{
19+
/**
20+
* @var Config
21+
*/
22+
protected $config;
23+
24+
/**
25+
* @var StoreManagerInterface
26+
*/
27+
protected $storeManager;
28+
29+
/**
30+
* @var GetProductIdsToRuleIdsMap
31+
*/
32+
protected $getProductIdsToRuleIdsMap;
33+
34+
/**
35+
* @var RuleCollectionFactory
36+
*/
37+
protected $ruleCollectionFactory;
38+
39+
/**
40+
* @var LabelProcessorInterface|null
41+
*/
42+
protected $labelProcessor;
43+
44+
/**
45+
* @var LayoutInterface
46+
*/
47+
protected $layout;
48+
49+
/**
50+
* GetLabels constructor.
51+
* @param StoreManagerInterface $storeManager
52+
* @param \Magefan\ProductLabel\Model\GetProductIdsToRuleIdsMap $getProductIdsToRuleIdsMap
53+
* @param RuleCollectionFactory $ruleCollectionFactory
54+
* @param LayoutInterface $layout
55+
* @param LabelProcessorInterface|null $labelProcessor
56+
*/
57+
public function __construct(
58+
Config $config,
59+
StoreManagerInterface $storeManager,
60+
GetProductIdsToRuleIdsMap $getProductIdsToRuleIdsMap,
61+
RuleCollectionFactory $ruleCollectionFactory,
62+
LayoutInterface $layout,
63+
?LabelProcessorInterface $labelProcessor = null
64+
) {
65+
$this->config = $config;
66+
$this->storeManager = $storeManager;
67+
$this->getProductIdsToRuleIdsMap = $getProductIdsToRuleIdsMap;
68+
$this->ruleCollectionFactory = $ruleCollectionFactory;
69+
$this->labelProcessor = $labelProcessor;
70+
$this->layout = $layout;
71+
}
72+
73+
/**
74+
* @param array $productIds
75+
* @param $idsUseForProductPage
76+
* @return array
77+
*/
78+
public function execute(array $productIds, $productIdsForProductPage = []): array
79+
{
80+
[$ruleIds, $productIdRuleIds] = $this->getProductIdsToRuleIdsMap->execute($productIds);
81+
82+
$rules = $this->ruleCollectionFactory->create()
83+
->addActiveFilter()
84+
->addFieldToFilter('id', ['in' => $ruleIds])
85+
->addStoreFilter($this->storeManager->getStore()->getId())
86+
->setOrder('priority', 'asc');
87+
88+
$replaceMap = [];
89+
90+
foreach ($productIdRuleIds as $productId => $productRuleIds) {
91+
$forProductPage = in_array($productId, $productIdsForProductPage);
92+
93+
$productLabels = $this->getAvailableProductLabels($rules, $productRuleIds, $forProductPage);
94+
95+
$htmlToReplace = $this->layout
96+
->createBlock(\Magefan\ProductLabel\Block\Label::class)
97+
->setProductLabels($productLabels)
98+
->setAdditionalCssClass($forProductPage ? 'mfpl-product-page' : '')
99+
->toHtml();
100+
101+
if ($htmlToReplace) {
102+
$replaceMap[$productId] = $htmlToReplace;
103+
}
104+
}
105+
106+
if (null !== $this->labelProcessor) {
107+
$replaceMap = $this->labelProcessor->execute($replaceMap, $productIds);
108+
}
109+
110+
return $replaceMap;
111+
}
112+
113+
/**
114+
* @param $rules
115+
* @param $productRuleIds
116+
* @param bool $forProductPage
117+
* @return array
118+
*/
119+
public function getAvailableProductLabels($rules, $productRuleIds, $forProductPage = false): array
120+
{
121+
$productLabelsCount = 0;
122+
$productLabels = [];
123+
124+
$discardRulePerPosition = [];
125+
126+
foreach ($rules as $rule) {
127+
if (in_array($rule->getId(), $productRuleIds)) {
128+
$productLabelsCount++;
129+
130+
if ($forProductPage) {
131+
$position = $rule->getPpPosition() ?: $rule->getPosition();
132+
} else {
133+
$position = $rule->getPosition() ?: 'top-left';
134+
}
135+
136+
if (!isset($discardRulePerPosition[$position])) {
137+
$productLabels[$position][] = $rule->getLabelData($forProductPage);
138+
}
139+
140+
if ($rule->getDiscardSubsequentRules()) {
141+
$discardRulePerPosition[$position] = true;
142+
}
143+
}
144+
145+
if ($productLabelsCount >= $this->config->getLabelsPerProduct()) {
146+
break;
147+
}
148+
}
149+
150+
return $productLabels;
151+
}
152+
}

0 commit comments

Comments
 (0)