Skip to content

Commit f473ebf

Browse files
committed
Merge remote-tracking branch 'adobe-commerce-tier-4/ACP2E-3166' into Tier4-Kings-PR-08-23-2024
2 parents 01a6ea4 + dfaddd0 commit f473ebf

File tree

2 files changed

+166
-15
lines changed

2 files changed

+166
-15
lines changed

app/code/Magento/CatalogGraphQl/Plugin/ProductAttributeSortInput.php

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,30 @@
2323
use GraphQL\Language\Visitor;
2424
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
2525
use Magento\GraphQl\Model\Query\ContextInterface;
26+
use Magento\Framework\App\RequestInterface;
27+
use Magento\Framework\Serialize\SerializerInterface;
2628

2729
class ProductAttributeSortInput
2830
{
31+
/**
32+
* @var RequestInterface
33+
*/
34+
private $request;
35+
36+
/**
37+
* @var SerializerInterface
38+
*/
39+
private $jsonSerializer;
40+
41+
/**
42+
* @param RequestInterface $request
43+
* @param SerializerInterface $jsonSerializer
44+
*/
45+
public function __construct(RequestInterface $request, SerializerInterface $jsonSerializer)
46+
{
47+
$this->request = $request;
48+
$this->jsonSerializer = $jsonSerializer;
49+
}
2950
/**
3051
* Plugin to preserve the original order of sort fields
3152
*
@@ -47,43 +68,83 @@ public function beforeResolve(
4768
array $value = null,
4869
array $args = null
4970
): array {
71+
72+
$data = $this->getDataFromRequest($this->request);
5073
if (isset($args['sort'])) {
51-
$args['sort'] = $this->getSortFieldsOrder($info, $args['sort']);
74+
$args['sort'] = $this->getSortFieldsOrder(
75+
$info,
76+
$args['sort'],
77+
isset($data['variables']['sort']) ? array_keys($data['variables']['sort']) : null
78+
);
5279
}
5380
return [$field, $context, $info, $value, $args];
5481
}
5582

83+
/**
84+
* Get data from request body or query string
85+
*
86+
* @param RequestInterface $request
87+
* @return array
88+
*/
89+
private function getDataFromRequest(RequestInterface $request): array
90+
{
91+
$data = [];
92+
if ($request->isPost()) {
93+
$data = $this->jsonSerializer->unserialize($request->getContent());
94+
} elseif ($request->isGet()) {
95+
$data = $request->getParams();
96+
$data['variables'] = isset($data['variables']) ?
97+
$this->jsonSerializer->unserialize($data['variables']) : null;
98+
$data['variables'] = is_array($data['variables']) ?
99+
$data['variables'] : null;
100+
}
101+
return $data;
102+
}
103+
56104
/**
57105
* Get sort fields in the original order
58106
*
59107
* @param ResolveInfo $info
60108
* @param array $sortFields
109+
* @param array|null $requestSortFields
61110
* @return array
62111
* @throws \Exception
63112
*/
64-
private function getSortFieldsOrder(ResolveInfo $info, array $sortFields)
113+
private function getSortFieldsOrder(ResolveInfo $info, array $sortFields, ?array $requestSortFields): array
65114
{
66115
$sortFieldsOriginal = [];
67116
Visitor::visit(
68117
$info->operation,
69118
[
70119
'enter' => [
71-
NodeKind::ARGUMENT => function (Node $node) use (&$sortFieldsOriginal, $sortFields) {
120+
NodeKind::ARGUMENT => function (Node $node) use (
121+
&$sortFieldsOriginal,
122+
$sortFields,
123+
$requestSortFields
124+
) {
72125
if ($node->name->value === 'sort') {
73-
Visitor::visit(
74-
$node->value,
75-
[
76-
'enter' => [
77-
NodeKind::OBJECT_FIELD =>
78-
function (Node $node) use (&$sortFieldsOriginal, $sortFields) {
79-
if (isset($sortFields[$node->name->value])) {
80-
$sortFieldsOriginal[$node->name->value] =
81-
$sortFields[$node->name->value];
126+
if (isset($requestSortFields)) {
127+
foreach ($requestSortFields as $fieldName) {
128+
if (isset($sortFields[$fieldName])) {
129+
$sortFieldsOriginal[$fieldName] = $sortFields[$fieldName];
130+
}
131+
}
132+
} else {
133+
Visitor::visit(
134+
$node->value,
135+
[
136+
'enter' => [
137+
NodeKind::OBJECT_FIELD =>
138+
function (Node $node) use (&$sortFieldsOriginal, $sortFields) {
139+
if (isset($sortFields[$node->name->value])) {
140+
$sortFieldsOriginal[$node->name->value] =
141+
$sortFields[$node->name->value];
142+
}
82143
}
83-
}
144+
]
84145
]
85-
]
86-
);
146+
);
147+
}
87148
return Visitor::stop();
88149
}
89150
}

dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,96 @@ protected function setUp(): void
114114
$this->fixture = DataFixtureStorageManager::getStorage();
115115
}
116116

117+
/**
118+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
119+
* @dataProvider sortByPriceAndNameDataProvider
120+
*/
121+
#[
122+
DataFixture(ProductFixture::class, ['price' => 10, 'name' => 'search product 1'], 'prod1'),
123+
DataFixture(ProductFixture::class, ['price' => 10, 'name' => 'search product 2'], 'prod2'),
124+
DataFixture(ProductFixture::class, ['price' => 20, 'name' => 'search product 3'], 'prod3'),
125+
DataFixture(ProductFixture::class, ['price' => 30, 'name' => 'search product 4'], 'prod4'),
126+
DataFixture(ProductFixture::class, ['price' => 40, 'name' => 'search product 5'], 'prod5'),
127+
]
128+
public function testSortMultipleFieldsSentInVariables($sort, $expectedOrder): void
129+
{
130+
$expectedOrderSku = [];
131+
foreach ($expectedOrder as $productName) {
132+
$expectedOrderSku[] = $this->fixture->get($productName)->getSku();
133+
}
134+
$query = <<<'QUERY'
135+
query GetProductsQuery(
136+
$search: String,
137+
$filter: ProductAttributeFilterInput,
138+
$pageSize: Int,
139+
$currentPage: Int,
140+
$sort: ProductAttributeSortInput
141+
) {
142+
products(
143+
search: $search,
144+
filter: $filter,
145+
pageSize: $pageSize,
146+
currentPage: $currentPage,
147+
sort: $sort
148+
) {
149+
total_count
150+
page_info{total_pages}
151+
items{
152+
__typename
153+
url_key
154+
sku
155+
name
156+
stock_status
157+
price_range {
158+
minimum_price {
159+
final_price {
160+
value
161+
currency
162+
}
163+
}
164+
}
165+
}
166+
}
167+
}
168+
QUERY;
169+
$variables = [
170+
'search' => null,
171+
'filter' => [],
172+
'pageSize' => 24,
173+
'currentPage' => 1,
174+
'sort' => $sort
175+
];
176+
177+
$response = $this->graphQlQuery($query, $variables);
178+
$this->assertArrayNotHasKey('errors', $response);
179+
$this->assertEquals($expectedOrderSku, array_column($response['products']['items'], 'sku'));
180+
}
181+
182+
/**
183+
* @return array
184+
*/
185+
public function sortByPriceAndNameDataProvider(): array
186+
{
187+
return [
188+
[
189+
['price' => 'ASC', 'name' => 'ASC'],
190+
['prod1', 'prod2', 'prod3', 'prod4', 'prod5']
191+
],
192+
[
193+
['price' => 'DESC', 'name' => 'ASC'],
194+
['prod5', 'prod4', 'prod3', 'prod1', 'prod2']
195+
],
196+
[
197+
['price' => 'ASC', 'name' => 'DESC'],
198+
['prod2', 'prod1', 'prod3', 'prod4', 'prod5']
199+
],
200+
[
201+
['price' => 'DESC', 'name' => 'DESC'],
202+
['prod5', 'prod4', 'prod3', 'prod2', 'prod1']
203+
],
204+
];
205+
}
206+
117207
/**
118208
* Verify that filters for non-existing category are empty
119209
*

0 commit comments

Comments
 (0)