Skip to content

Commit 66b65d2

Browse files
[Magento Community Engineering] Community Contributions - 2.4-develop
- merged latest code from mainline branch
2 parents 7d3594e + 0bcb278 commit 66b65d2

File tree

9 files changed

+364
-62
lines changed

9 files changed

+364
-62
lines changed

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/AttributeOptionProvider.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation;
99

1010
use Magento\Framework\App\ResourceConnection;
11+
use Magento\Store\Model\Store;
1112

1213
/**
1314
* Fetch product attribute option data including attribute info
@@ -41,16 +42,18 @@ public function __construct(ResourceConnection $resourceConnection)
4142
* Get option data. Return list of attributes with option data
4243
*
4344
* @param array $optionIds
45+
* @param int|null $storeId
4446
* @param array $attributeCodes
4547
* @return array
4648
* @throws \Zend_Db_Statement_Exception
4749
*/
48-
public function getOptions(array $optionIds, array $attributeCodes = []): array
50+
public function getOptions(array $optionIds, ?int $storeId, array $attributeCodes = []): array
4951
{
5052
if (!$optionIds) {
5153
return [];
5254
}
5355

56+
$storeId = $storeId ?: Store::DEFAULT_STORE_ID;
5457
$connection = $this->resourceConnection->getConnection();
5558
$select = $connection->select()
5659
->from(
@@ -70,9 +73,21 @@ public function getOptions(array $optionIds, array $attributeCodes = []): array
7073
['option_value' => $this->resourceConnection->getTableName('eav_attribute_option_value')],
7174
'options.option_id = option_value.option_id',
7275
[
73-
'option_label' => 'option_value.value',
7476
'option_id' => 'option_value.option_id',
7577
]
78+
)->joinLeft(
79+
['option_value_store' => $this->resourceConnection->getTableName('eav_attribute_option_value')],
80+
"options.option_id = option_value_store.option_id AND option_value_store.store_id = {$storeId}",
81+
[
82+
'option_label' => $connection->getCheckSql(
83+
'option_value_store.value_id > 0',
84+
'option_value_store.value',
85+
'option_value.value'
86+
)
87+
]
88+
)->where(
89+
'a.attribute_id = options.attribute_id AND option_value.store_id = ?',
90+
Store::DEFAULT_STORE_ID
7691
);
7792

7893
$select->where('option_value.option_id IN (?)', $optionIds);

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Builder/Attribute.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function __construct(
7171
*/
7272
public function build(AggregationInterface $aggregation, ?int $storeId): array
7373
{
74-
$attributeOptions = $this->getAttributeOptions($aggregation);
74+
$attributeOptions = $this->getAttributeOptions($aggregation, $storeId);
7575

7676
// build layer per attribute
7777
$result = [];
@@ -133,10 +133,11 @@ private function isBucketEmpty(?BucketInterface $bucket): bool
133133
* Get list of attributes with options
134134
*
135135
* @param AggregationInterface $aggregation
136+
* @param int|null $storeId
136137
* @return array
137138
* @throws \Zend_Db_Statement_Exception
138139
*/
139-
private function getAttributeOptions(AggregationInterface $aggregation): array
140+
private function getAttributeOptions(AggregationInterface $aggregation, ?int $storeId): array
140141
{
141142
$attributeOptionIds = [];
142143
$attributes = [];
@@ -154,6 +155,6 @@ function (AggregationValueInterface $value) {
154155
return [];
155156
}
156157

157-
return $this->attributeOptionProvider->getOptions(\array_merge(...$attributeOptionIds), $attributes);
158+
return $this->attributeOptionProvider->getOptions(\array_merge(...$attributeOptionIds), $storeId, $attributes);
158159
}
159160
}

app/code/Magento/GraphQl/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
"require": {
66
"php": "~7.3.0||~7.4.0",
77
"magento/module-eav": "*",
8-
"magento/framework": "*"
8+
"magento/framework": "*",
9+
"magento/module-webapi": "*"
910
},
1011
"suggest": {
11-
"magento/module-webapi": "*",
1212
"magento/module-graph-ql-cache": "*"
1313
},
1414
"license": [

app/code/Magento/QuoteGraphQl/Model/Resolver/CustomerCart.php

Lines changed: 15 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,66 +7,32 @@
77

88
namespace Magento\QuoteGraphQl\Model\Resolver;
99

10-
use Magento\Framework\Exception\NoSuchEntityException;
1110
use Magento\Framework\GraphQl\Config\Element\Field;
1211
use Magento\Framework\GraphQl\Query\ResolverInterface;
1312
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
14-
use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForCustomer;
1513
use Magento\GraphQl\Model\Query\ContextInterface;
1614
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
17-
use Magento\Quote\Api\CartManagementInterface;
18-
use Magento\Quote\Model\QuoteIdMaskFactory;
19-
use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
20-
use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResourceModel;
15+
use Magento\Quote\Model\Cart\CustomerCartResolver;
2116

2217
/**
2318
* Get cart for the customer
2419
*/
2520
class CustomerCart implements ResolverInterface
2621
{
2722
/**
28-
* @var CreateEmptyCartForCustomer
23+
* @var CustomerCartResolver
2924
*/
30-
private $createEmptyCartForCustomer;
25+
private $customerCartResolver;
3126

3227
/**
33-
* @var CartManagementInterface
34-
*/
35-
private $cartManagement;
36-
37-
/**
38-
* @var QuoteIdMaskFactory
39-
*/
40-
private $quoteIdMaskFactory;
41-
42-
/**
43-
* @var QuoteIdMaskResourceModel
44-
*/
45-
private $quoteIdMaskResourceModel;
46-
/**
47-
* @var QuoteIdToMaskedQuoteIdInterface
48-
*/
49-
private $quoteIdToMaskedQuoteId;
50-
51-
/**
52-
* @param CreateEmptyCartForCustomer $createEmptyCartForCustomer
53-
* @param CartManagementInterface $cartManagement
54-
* @param QuoteIdMaskFactory $quoteIdMaskFactory
55-
* @param QuoteIdMaskResourceModel $quoteIdMaskResourceModel
56-
* @param QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId
28+
* CustomerCart constructor.
29+
*
30+
* @param CustomerCartResolver $customerCartResolver
5731
*/
5832
public function __construct(
59-
CreateEmptyCartForCustomer $createEmptyCartForCustomer,
60-
CartManagementInterface $cartManagement,
61-
QuoteIdMaskFactory $quoteIdMaskFactory,
62-
QuoteIdMaskResourceModel $quoteIdMaskResourceModel,
63-
QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId
33+
CustomerCartResolver $customerCartResolver
6434
) {
65-
$this->createEmptyCartForCustomer = $createEmptyCartForCustomer;
66-
$this->cartManagement = $cartManagement;
67-
$this->quoteIdMaskFactory = $quoteIdMaskFactory;
68-
$this->quoteIdMaskResourceModel = $quoteIdMaskResourceModel;
69-
$this->quoteIdToMaskedQuoteId = $quoteIdToMaskedQuoteId;
35+
$this->customerCartResolver = $customerCartResolver;
7036
}
7137

7238
/**
@@ -76,22 +42,17 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
7642
{
7743
$currentUserId = $context->getUserId();
7844

79-
/** @var ContextInterface $context */
45+
/**
46+
* @var ContextInterface $context
47+
*/
8048
if (false === $context->getExtensionAttributes()->getIsCustomer()) {
8149
throw new GraphQlAuthorizationException(__('The request is allowed for logged in customer'));
8250
}
83-
try {
84-
$cart = $this->cartManagement->getCartForCustomer($currentUserId);
85-
} catch (NoSuchEntityException $e) {
86-
$this->createEmptyCartForCustomer->execute($currentUserId, null);
87-
$cart = $this->cartManagement->getCartForCustomer($currentUserId);
88-
}
8951

90-
$maskedId = $this->quoteIdToMaskedQuoteId->execute((int) $cart->getId());
91-
if (empty($maskedId)) {
92-
$quoteIdMask = $this->quoteIdMaskFactory->create();
93-
$quoteIdMask->setQuoteId((int) $cart->getId());
94-
$this->quoteIdMaskResourceModel->save($quoteIdMask);
52+
try {
53+
$cart = $this->customerCartResolver->resolve($currentUserId);
54+
} catch (\Exception $e) {
55+
$cart = null;
9556
}
9657

9758
return [

composer.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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\GraphQl\Catalog;
9+
10+
use Exception;
11+
use Magento\Eav\Api\Data\AttributeOptionInterface;
12+
use Magento\Eav\Model\Config;
13+
use Magento\Framework\Exception\LocalizedException;
14+
use Magento\TestFramework\Helper\Bootstrap;
15+
use Magento\TestFramework\TestCase\GraphQlAbstract;
16+
17+
class ProductAttributeStoreOptionsTest extends GraphQlAbstract
18+
{
19+
/**
20+
* Test that custom attribute option labels are returned respecting store
21+
*
22+
* @magentoApiDataFixture Magento/Store/_files/store.php
23+
* @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute_store_options.php
24+
* @throws LocalizedException
25+
*/
26+
public function testAttributeStoreLabels(): void
27+
{
28+
$this->attributeLabelTest('Option Default Store');
29+
$this->attributeLabelTest('Option Test Store', ['Store' => 'test']);
30+
}
31+
32+
/**
33+
* @param $expectedLabel
34+
* @param array $headers
35+
* @throws LocalizedException
36+
* @throws Exception
37+
*/
38+
private function attributeLabelTest($expectedLabel, array $headers = []): void
39+
{
40+
/** @var Config $eavConfig */
41+
$eavConfig = Bootstrap::getObjectManager()->get(Config::class);
42+
$attributeCode = 'test_configurable';
43+
$attribute = $eavConfig->getAttribute('catalog_product', $attributeCode);
44+
45+
/** @var AttributeOptionInterface[] $options */
46+
$options = $attribute->getOptions();
47+
array_shift($options);
48+
$optionValues = [];
49+
50+
foreach ($options as $option) {
51+
$optionValues[] = [
52+
'value' => $option->getValue(),
53+
];
54+
}
55+
56+
$expectedOptions = [
57+
[
58+
'label' => $expectedLabel,
59+
'value' => $optionValues[0]['value']
60+
]
61+
];
62+
63+
$query = <<<QUERY
64+
{
65+
products(search:"Simple",
66+
pageSize: 3
67+
currentPage: 1
68+
)
69+
{
70+
aggregations
71+
{
72+
attribute_code
73+
options
74+
{
75+
label
76+
value
77+
}
78+
}
79+
}
80+
}
81+
QUERY;
82+
$response = $this->graphQlQuery($query, [], '', $headers);
83+
$this->assertNotEmpty($response['products']['aggregations']);
84+
$actualAttributes = $response['products']['aggregations'];
85+
$actualAttributeOptions = [];
86+
87+
foreach ($actualAttributes as $actualAttribute) {
88+
if ($actualAttribute['attribute_code'] === $attributeCode) {
89+
$actualAttributeOptions = $actualAttribute['options'];
90+
}
91+
}
92+
93+
$this->assertNotEmpty($actualAttributeOptions);
94+
95+
foreach ($actualAttributeOptions as $key => $actualAttributeOption) {
96+
if ($actualAttributeOption['value'] === $expectedOptions[$key]['value']) {
97+
$this->assertEquals($actualAttributeOption['label'], $expectedOptions[$key]['label']);
98+
}
99+
}
100+
}
101+
}

0 commit comments

Comments
 (0)