Skip to content

Commit eca4ae5

Browse files
committed
ACP2E-3166: [Cloud] Graphql Product sorting do not work
1 parent 6f4805f commit eca4ae5

File tree

2 files changed

+149
-15
lines changed

2 files changed

+149
-15
lines changed

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

Lines changed: 78 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,85 @@ 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+
if ($request->isPost()) {
92+
$data = $this->jsonSerializer->unserialize($request->getContent());
93+
} elseif ($request->isGet()) {
94+
$data = $request->getParams();
95+
$data['variables'] = isset($data['variables']) ?
96+
$this->jsonSerializer->unserialize($data['variables']) : null;
97+
$data['variables'] = is_array($data['variables']) ?
98+
$data['variables'] : null;
99+
} else {
100+
return [];
101+
}
102+
103+
return $data;
104+
}
105+
56106
/**
57107
* Get sort fields in the original order
58108
*
59109
* @param ResolveInfo $info
60110
* @param array $sortFields
111+
* @param array|null $requestSortFields
61112
* @return array
62113
* @throws \Exception
63114
*/
64-
private function getSortFieldsOrder(ResolveInfo $info, array $sortFields)
115+
private function getSortFieldsOrder(ResolveInfo $info, array $sortFields, ?array $requestSortFields): array
65116
{
66117
$sortFieldsOriginal = [];
67118
Visitor::visit(
68119
$info->operation,
69120
[
70121
'enter' => [
71-
NodeKind::ARGUMENT => function (Node $node) use (&$sortFieldsOriginal, $sortFields) {
122+
NodeKind::ARGUMENT => function (Node $node) use (
123+
&$sortFieldsOriginal,
124+
$sortFields,
125+
$requestSortFields
126+
) {
72127
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];
128+
if (isset($requestSortFields)) {
129+
foreach ($requestSortFields as $fieldName) {
130+
if (isset($sortFields[$fieldName])) {
131+
$sortFieldsOriginal[$fieldName] = $sortFields[$fieldName];
132+
}
133+
}
134+
} else {
135+
Visitor::visit(
136+
$node->value,
137+
[
138+
'enter' => [
139+
NodeKind::OBJECT_FIELD =>
140+
function (Node $node) use (&$sortFieldsOriginal, $sortFields) {
141+
if (isset($sortFields[$node->name->value])) {
142+
$sortFieldsOriginal[$node->name->value] =
143+
$sortFields[$node->name->value];
144+
}
82145
}
83-
}
146+
]
84147
]
85-
]
86-
);
148+
);
149+
}
87150
return Visitor::stop();
88151
}
89152
}

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

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

117+
/**
118+
* Verify that products returned in a correct order
119+
*
120+
* @magentoApiDataFixture Magento/Catalog/_files/products_for_search.php
121+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
122+
*/
123+
public function testSortMultipleFieldsSentInVariables(): void
124+
{
125+
$query = <<<'QUERY'
126+
query GetProductsQuery(
127+
$search: String,
128+
$filter: ProductAttributeFilterInput,
129+
$pageSize: Int,
130+
$currentPage: Int,
131+
$sort: ProductAttributeSortInput
132+
) {
133+
products(
134+
search: $search,
135+
filter: $filter,
136+
pageSize: $pageSize,
137+
currentPage: $currentPage,
138+
sort: $sort
139+
) {
140+
total_count
141+
page_info{total_pages}
142+
items{
143+
__typename
144+
url_key
145+
sku
146+
name
147+
stock_status
148+
price_range {
149+
minimum_price {
150+
final_price {
151+
value
152+
currency
153+
}
154+
}
155+
}
156+
}
157+
}
158+
}
159+
QUERY;
160+
$variables = [
161+
'search' => null,
162+
'filter' => [],
163+
'pageSize' => 24,
164+
'currentPage' => 1,
165+
'sort' => ['price' => 'ASC', 'name' => 'ASC']
166+
];
167+
$response = $this->graphQlQuery($query, $variables);
168+
$this->assertEquals(5, $response['products']['total_count']);
169+
$prod1 = $this->productRepository->get('search_product_1');
170+
$prod2 = $this->productRepository->get('search_product_2');
171+
$prod3 = $this->productRepository->get('search_product_3');
172+
$prod4 = $this->productRepository->get('search_product_4');
173+
$prod5 = $this->productRepository->get('search_product_5');
174+
175+
$filteredProducts = [$prod1, $prod2, $prod3, $prod4, $prod5];
176+
$productItemsInResponse = array_map(null, $response['products']['items'], $filteredProducts);
177+
foreach ($productItemsInResponse as $itemIndex => $itemArray) {
178+
$this->assertNotEmpty($itemArray);
179+
$this->assertResponseFields(
180+
$productItemsInResponse[$itemIndex][0],
181+
[
182+
'name' => $filteredProducts[$itemIndex]->getName(),
183+
]
184+
);
185+
}
186+
}
187+
117188
/**
118189
* Verify that filters for non-existing category are empty
119190
*

0 commit comments

Comments
 (0)