Skip to content

Commit e6531f1

Browse files
committed
MC-42666: GraphQL request returns configurable variants from ALL storeviews
1 parent 2697216 commit e6531f1

File tree

9 files changed

+208
-416
lines changed

9 files changed

+208
-416
lines changed

app/code/Magento/ConfigurableProduct/Model/AttributeOptionProvider.php

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,13 @@
88

99
use Magento\ConfigurableProduct\Model\ResourceModel\Attribute\OptionSelectBuilderInterface;
1010
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
11-
use Magento\Framework\App\ScopeResolverInterface;
1211
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute;
13-
use Magento\Framework\DB\Select;
1412

1513
/**
1614
* Provider for retrieving configurable options.
1715
*/
1816
class AttributeOptionProvider implements AttributeOptionProviderInterface
1917
{
20-
/**
21-
* @var ScopeResolverInterface
22-
*/
23-
private $scopeResolver;
24-
2518
/**
2619
* @var Attribute
2720
*/
@@ -34,16 +27,13 @@ class AttributeOptionProvider implements AttributeOptionProviderInterface
3427

3528
/**
3629
* @param Attribute $attributeResource
37-
* @param ScopeResolverInterface $scopeResolver,
3830
* @param OptionSelectBuilderInterface $optionSelectBuilder
3931
*/
4032
public function __construct(
4133
Attribute $attributeResource,
42-
ScopeResolverInterface $scopeResolver,
4334
OptionSelectBuilderInterface $optionSelectBuilder
4435
) {
4536
$this->attributeResource = $attributeResource;
46-
$this->scopeResolver = $scopeResolver;
4737
$this->optionSelectBuilder = $optionSelectBuilder;
4838
}
4939

@@ -52,8 +42,7 @@ public function __construct(
5242
*/
5343
public function getAttributeOptions(AbstractAttribute $superAttribute, $productId)
5444
{
55-
$scope = $this->scopeResolver->getScope();
56-
$select = $this->optionSelectBuilder->getSelect($superAttribute, $productId, $scope);
45+
$select = $this->optionSelectBuilder->getSelect($superAttribute, (int) $productId);
5746
$data = $this->attributeResource->getConnection()->fetchAll($select);
5847

5948
if ($superAttribute->getSourceModel()) {

app/code/Magento/ConfigurableProduct/Model/ResourceModel/Attribute/OptionSelectBuilder.php

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,47 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\ConfigurableProduct\Model\ResourceModel\Attribute;
79

10+
use Magento\Catalog\Api\Data\ProductInterface;
811
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute;
912
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
10-
use Magento\Framework\App\ScopeInterface;
13+
use Magento\Framework\EntityManager\MetadataPool;
14+
use Magento\Store\Model\Store;
1115

1216
/**
1317
* Build select object for retrieving configurable options.
1418
*/
1519
class OptionSelectBuilder implements OptionSelectBuilderInterface
1620
{
1721
/**
18-
* Configurable Attribute Resource Model.
19-
*
2022
* @var Attribute
2123
*/
2224
private $attributeResource;
2325

2426
/**
25-
* Option Provider.
26-
*
27-
* @var OptionProvider
27+
* @var MetadataPool
2828
*/
29-
private $attributeOptionProvider;
29+
private $metadataPool;
3030

3131
/**
3232
* @param Attribute $attributeResource
33-
* @param OptionProvider $attributeOptionProvider
33+
* @param MetadataPool $metadataPool
3434
*/
35-
public function __construct(Attribute $attributeResource, OptionProvider $attributeOptionProvider)
35+
public function __construct(Attribute $attributeResource, MetadataPool $metadataPool)
3636
{
3737
$this->attributeResource = $attributeResource;
38-
$this->attributeOptionProvider = $attributeOptionProvider;
38+
$this->metadataPool = $metadataPool;
3939
}
4040

4141
/**
4242
* @inheritdoc
4343
*/
44-
public function getSelect(AbstractAttribute $superAttribute, int $productId, ScopeInterface $scope)
44+
public function getSelect(AbstractAttribute $superAttribute, int $productId)
4545
{
46-
$productLinkField = $this->attributeOptionProvider->getProductEntityLinkField();
46+
$productLinkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
4747
$select = $this->attributeResource->getConnection()->select()->from(
4848
['super_attribute' => $this->attributeResource->getTable('catalog_product_super_attribute')],
4949
[
@@ -55,7 +55,7 @@ public function getSelect(AbstractAttribute $superAttribute, int $productId, Sco
5555
]
5656
)->joinInner(
5757
['product_entity' => $this->attributeResource->getTable('catalog_product_entity')],
58-
"product_entity.{$this->attributeOptionProvider->getProductEntityLinkField()} = super_attribute.product_id",
58+
"product_entity.$productLinkField = super_attribute.product_id",
5959
[]
6060
)->joinInner(
6161
['product_link' => $this->attributeResource->getTable('catalog_product_super_link')],
@@ -80,23 +80,13 @@ public function getSelect(AbstractAttribute $superAttribute, int $productId, Sco
8080
]
8181
),
8282
[]
83-
)->joinInner(
84-
['entity_website' => $this->attributeResource->getTable('catalog_product_website')],
85-
implode(
86-
' AND ',
87-
[
88-
"entity_website.product_id = entity.$productLinkField",
89-
"entity_website.website_id = {$scope->getWebsiteId()}",
90-
]
91-
),
92-
[]
9383
)->joinLeft(
9484
['attribute_label' => $this->attributeResource->getTable('catalog_product_super_attribute_label')],
9585
implode(
9686
' AND ',
9787
[
9888
'super_attribute.product_super_attribute_id = attribute_label.product_super_attribute_id',
99-
'attribute_label.store_id = ' . \Magento\Store\Model\Store::DEFAULT_STORE_ID,
89+
'attribute_label.store_id = ' . Store::DEFAULT_STORE_ID,
10090
]
10191
),
10292
[]
@@ -115,34 +105,19 @@ public function getSelect(AbstractAttribute $superAttribute, int $productId, Sco
115105
);
116106

117107
if (!$superAttribute->getSourceModel()) {
118-
$select->columns(
119-
[
120-
'option_title' => $this->attributeResource->getConnection()->getIfNullSql(
121-
'option_value.value',
122-
'default_option_value.value'
123-
),
124-
'default_title' => 'default_option_value.value',
125-
]
126-
)->joinLeft(
108+
$select->joinLeft(
127109
['option_value' => $this->attributeResource->getTable('eav_attribute_option_value')],
128110
implode(
129111
' AND ',
130112
[
131113
'option_value.option_id = entity_value.value',
132-
'option_value.store_id = ' . $scope->getId(),
133-
]
134-
),
135-
[]
136-
)->joinLeft(
137-
['default_option_value' => $this->attributeResource->getTable('eav_attribute_option_value')],
138-
implode(
139-
' AND ',
140-
[
141-
'default_option_value.option_id = entity_value.value',
142-
'default_option_value.store_id = ' . \Magento\Store\Model\Store::DEFAULT_STORE_ID,
114+
'option_value.store_id = ' . Store::DEFAULT_STORE_ID,
143115
]
144116
),
145-
[]
117+
[
118+
'option_title' => 'option_value.value',
119+
'default_title' => 'option_value.value',
120+
]
146121
);
147122
}
148123

app/code/Magento/ConfigurableProduct/Model/ResourceModel/Attribute/OptionSelectBuilderInterface.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
namespace Magento\ConfigurableProduct\Model\ResourceModel\Attribute;
77

88
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
9-
use Magento\Framework\App\ScopeInterface;
109
use Magento\Framework\DB\Select;
1110

1211
/**
@@ -19,8 +18,7 @@ interface OptionSelectBuilderInterface
1918
*
2019
* @param AbstractAttribute $superAttribute
2120
* @param int $productId
22-
* @param ScopeInterface $scope
2321
* @return Select
2422
*/
25-
public function getSelect(AbstractAttribute $superAttribute, int $productId, ScopeInterface $scope);
23+
public function getSelect(AbstractAttribute $superAttribute, int $productId);
2624
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\ConfigurableProduct\Model\ResourceModel\Attribute;
9+
10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
12+
use Magento\CatalogInventory\Model\Stock\Status as StockStatus;
13+
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute;
14+
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
15+
use Magento\Framework\EntityManager\MetadataPool;
16+
use Magento\Store\Model\Store;
17+
use Magento\Store\Model\StoreManagerInterface;
18+
19+
/**
20+
* Build select object for retrieving configurable options considering scope.
21+
*/
22+
class ScopedOptionSelectBuilder implements OptionSelectBuilderInterface
23+
{
24+
/**
25+
* @var Attribute
26+
*/
27+
private $attributeResource;
28+
29+
/**
30+
* @var MetadataPool
31+
*/
32+
private $metadataPool;
33+
34+
/**
35+
* @var StoreManagerInterface
36+
*/
37+
private $storeManager;
38+
39+
/**
40+
* @var StockConfigurationInterface
41+
*/
42+
private $stockConfig;
43+
44+
/**
45+
* @param Attribute $attributeResource
46+
* @param MetadataPool $metadataPool
47+
* @param StoreManagerInterface $storeManager
48+
* @param StockConfigurationInterface $stockConfig
49+
*/
50+
public function __construct(
51+
Attribute $attributeResource,
52+
MetadataPool $metadataPool,
53+
StoreManagerInterface $storeManager,
54+
StockConfigurationInterface $stockConfig
55+
) {
56+
$this->attributeResource = $attributeResource;
57+
$this->metadataPool = $metadataPool;
58+
$this->storeManager = $storeManager;
59+
$this->stockConfig = $stockConfig;
60+
}
61+
62+
/**
63+
* @inheritdoc
64+
*/
65+
public function getSelect(AbstractAttribute $superAttribute, int $productId)
66+
{
67+
$store = $this->storeManager->getStore();
68+
$productLinkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
69+
$select = $this->attributeResource->getConnection()->select()->from(
70+
['super_attribute' => $this->attributeResource->getTable('catalog_product_super_attribute')],
71+
[
72+
'sku' => 'entity.sku',
73+
'product_id' => 'product_entity.entity_id',
74+
'attribute_code' => 'attribute.attribute_code',
75+
'value_index' => 'entity_value.value',
76+
'super_attribute_label' => 'attribute_label.value',
77+
]
78+
)->joinInner(
79+
['product_entity' => $this->attributeResource->getTable('catalog_product_entity')],
80+
"product_entity.$productLinkField = super_attribute.product_id",
81+
[]
82+
)->joinInner(
83+
['product_link' => $this->attributeResource->getTable('catalog_product_super_link')],
84+
'product_link.parent_id = super_attribute.product_id',
85+
[]
86+
)->joinInner(
87+
['attribute' => $this->attributeResource->getTable('eav_attribute')],
88+
'attribute.attribute_id = super_attribute.attribute_id',
89+
[]
90+
)->joinInner(
91+
['entity' => $this->attributeResource->getTable('catalog_product_entity')],
92+
'entity.entity_id = product_link.product_id',
93+
[]
94+
)->joinInner(
95+
['entity_value' => $superAttribute->getBackendTable()],
96+
implode(
97+
' AND ',
98+
[
99+
'entity_value.attribute_id = super_attribute.attribute_id',
100+
'entity_value.store_id = 0',
101+
"entity_value.$productLinkField = entity.$productLinkField",
102+
]
103+
),
104+
[]
105+
)->joinInner(
106+
['entity_website' => $this->attributeResource->getTable('catalog_product_website')],
107+
implode(
108+
' AND ',
109+
[
110+
"entity_website.product_id = entity.$productLinkField",
111+
"entity_website.website_id = {$store->getWebsiteId()}",
112+
]
113+
),
114+
[]
115+
)->joinLeft(
116+
['attribute_label' => $this->attributeResource->getTable('catalog_product_super_attribute_label')],
117+
implode(
118+
' AND ',
119+
[
120+
'super_attribute.product_super_attribute_id = attribute_label.product_super_attribute_id',
121+
'attribute_label.store_id = ' . Store::DEFAULT_STORE_ID,
122+
]
123+
),
124+
[]
125+
)->joinLeft(
126+
['attribute_option' => $this->attributeResource->getTable('eav_attribute_option')],
127+
'attribute_option.option_id = entity_value.value',
128+
[]
129+
)->order(
130+
'attribute_option.sort_order ASC'
131+
)->where(
132+
'super_attribute.product_id = ?',
133+
$productId
134+
)->where(
135+
'attribute.attribute_id = ?',
136+
$superAttribute->getAttributeId()
137+
);
138+
139+
if (!$this->stockConfig->isShowOutOfStock()) {
140+
$select->joinInner(
141+
['stock' => $this->attributeResource->getTable('cataloginventory_stock_status')],
142+
'stock.product_id = entity.entity_id',
143+
[]
144+
)->where(
145+
'stock.stock_status = ?',
146+
StockStatus::STATUS_IN_STOCK
147+
);
148+
}
149+
150+
if (!$superAttribute->getSourceModel()) {
151+
$select->columns(
152+
[
153+
'option_title' => $this->attributeResource->getConnection()->getIfNullSql(
154+
'option_value.value',
155+
'default_option_value.value'
156+
),
157+
'default_title' => 'default_option_value.value',
158+
]
159+
)->joinLeft(
160+
['option_value' => $this->attributeResource->getTable('eav_attribute_option_value')],
161+
implode(
162+
' AND ',
163+
[
164+
'option_value.option_id = entity_value.value',
165+
'option_value.store_id = ' . $store->getId(),
166+
]
167+
),
168+
[]
169+
)->joinLeft(
170+
['default_option_value' => $this->attributeResource->getTable('eav_attribute_option_value')],
171+
implode(
172+
' AND ',
173+
[
174+
'default_option_value.option_id = entity_value.value',
175+
'default_option_value.store_id = ' . Store::DEFAULT_STORE_ID,
176+
]
177+
),
178+
[]
179+
);
180+
}
181+
182+
return $select;
183+
}
184+
}

0 commit comments

Comments
 (0)