Skip to content

Commit 666cbee

Browse files
author
jekabs
committed
Variants Services
-Added getVariantsExactlyMatch service -Added getVariantsInclude service -Added test cases for these services
1 parent dc336c6 commit 666cbee

File tree

3 files changed

+171
-31
lines changed

3 files changed

+171
-31
lines changed

app/code/Magento/CatalogStorefront/Model/VariantService.php

+66
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,72 @@ public function getVariantsMatch(OptionSelectionRequestInterface $request): Prod
283283
return $response;
284284
}
285285

286+
/**
287+
* Match full variant which matches the merchant selection exactly
288+
*
289+
* @param OptionSelectionRequestInterface $request
290+
* @return ProductVariantResponseInterface
291+
* @throws RuntimeException
292+
* @throws \Throwable
293+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
294+
*/
295+
public function getVariantsExactlyMatch(OptionSelectionRequestInterface $request): ProductVariantResponseInterface
296+
{
297+
$values = $request->getValues();
298+
$store = $request->getStore();
299+
$variantIds = $this->productVariantsDataProvider->fetchVariantIdsByOptionValues($values);
300+
$variantData = count($variantIds) !== 1 ? [] : $this->productVariantsDataProvider->fetchByVariantIds($variantIds);
301+
302+
$validVariants = [];
303+
if (!empty($variantData) && count($variantData) === count($values)) {
304+
\ksort($variantData);
305+
$variants = $this->formatVariants($variantData);
306+
$validVariants = $this->validateVariants($variants, $store);
307+
}
308+
309+
$output = [];
310+
foreach ($validVariants as $variant) {
311+
$output[] = $this->productVariantMapper->setData($variant)->build();
312+
}
313+
314+
$response = new ProductVariantResponse();
315+
$response->setMatchedVariants($output);
316+
return $response;
317+
}
318+
319+
/**
320+
* Get all variants which contain at least one of merchant selections
321+
*
322+
* @param OptionSelectionRequestInterface $request
323+
* @return ProductVariantResponseInterface
324+
* @throws RuntimeException
325+
* @throws \Throwable
326+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
327+
*/
328+
public function getVariantsInclude(OptionSelectionRequestInterface $request): ProductVariantResponseInterface
329+
{
330+
$values = $request->getValues();
331+
$store = $request->getStore();
332+
$variantIds = $this->productVariantsDataProvider->fetchVariantIdsByOptionValues($values, false);
333+
$variantData = empty($variantIds) ? [] : $this->productVariantsDataProvider->fetchByVariantIds($variantIds);
334+
335+
$validVariants = [];
336+
if (!empty($variantData)) {
337+
\ksort($variantData);
338+
$variants = $this->formatVariants($variantData);
339+
$validVariants = $this->validateVariants($variants, $store);
340+
}
341+
342+
$output = [];
343+
foreach ($validVariants as $variant) {
344+
$output[] = $this->productVariantMapper->setData($variant)->build();
345+
}
346+
347+
$response = new ProductVariantResponse();
348+
$response->setMatchedVariants($output);
349+
return $response;
350+
}
351+
286352
/**
287353
* Combine option values into product variants
288354
*

app/code/Magento/CatalogStorefront/Test/Api/ProductVariants/ConfigurableVariantsTest.php

+103-26
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@
2323
*/
2424
class ConfigurableVariantsTest extends StorefrontTestsAbstract
2525
{
26+
/**
27+
* Simple product skus from Magento/ConfigurableProduct/_files/configurable_product_nine_simples.php
28+
*/
29+
private const SIMPLE_SKUS = [
30+
'simple_0',
31+
'simple_1',
32+
'simple_2',
33+
'simple_3',
34+
'simple_4',
35+
'simple_5',
36+
'simple_6',
37+
'simple_7',
38+
'simple_8'
39+
];
40+
2641
/**
2742
* @var VariantService
2843
*/
@@ -78,21 +93,10 @@ public function testConfigurableProductVariants(): void
7893
//This sleep ensures that the elastic index has sufficient time to refresh
7994
//See https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-refresh.html#docs-refresh
8095
sleep(1);
81-
$simpleSkus = [
82-
'simple_0',
83-
'simple_1',
84-
'simple_2',
85-
'simple_3',
86-
'simple_4',
87-
'simple_5',
88-
'simple_6',
89-
'simple_7',
90-
'simple_8'
91-
];
9296
/** @var $configurable Product */
9397
$configurable = $this->productRepository->get('configurable');
9498
$simples = [];
95-
foreach ($simpleSkus as $sku) {
99+
foreach (self::SIMPLE_SKUS as $sku) {
96100
$simples[] = $this->productRepository->get($sku);
97101
}
98102

@@ -132,33 +136,22 @@ public function testProductVariantsDisabledProduct(): void
132136
}
133137

134138
/**
135-
* Validate matching of variants by option values
139+
* Validate matching of variants by option values using getVariantsMatch
136140
*
137141
* @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_product_nine_simples.php
138142
* @magentoDbIsolation disabled
139143
* @throws NoSuchEntityException
140144
* @throws \Throwable
141145
*/
142-
public function testVariantsMatch(): void
146+
public function testGetVariantsMatch(): void
143147
{
144148
//This sleep ensures that the elastic index has sufficient time to refresh
145149
//See https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-refresh.html#docs-refresh
146150
sleep(1);
147-
$simpleSkus = [
148-
'simple_0',
149-
'simple_1',
150-
'simple_2',
151-
'simple_3',
152-
'simple_4',
153-
'simple_5',
154-
'simple_6',
155-
'simple_7',
156-
'simple_8'
157-
];
158151
/** @var $configurable Product */
159152
$configurable = $this->productRepository->get('configurable');
160153
$simples = [];
161-
foreach ($simpleSkus as $sku) {
154+
foreach (self::SIMPLE_SKUS as $sku) {
162155
$simples[] = $this->productRepository->get($sku);
163156
}
164157
$availableVariants = $this->getExpectedProductVariants($configurable, $simples);
@@ -187,6 +180,90 @@ public function testVariantsMatch(): void
187180
$this->compare($expected, $actual);
188181
}
189182

183+
/**
184+
* Validate matching of variants by option values using getVariantsExactlyMatch
185+
*
186+
* @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_product_nine_simples.php
187+
* @magentoDbIsolation disabled
188+
* @throws NoSuchEntityException
189+
* @throws \Throwable
190+
*/
191+
public function testGetVariantsExactlyMatch(): void
192+
{
193+
//This sleep ensures that the elastic index has sufficient time to refresh
194+
//See https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-refresh.html#docs-refresh
195+
sleep(1);
196+
/** @var $configurable Product */
197+
$configurable = $this->productRepository->get('configurable');
198+
$simples = [];
199+
foreach (self::SIMPLE_SKUS as $sku) {
200+
$simples[] = $this->productRepository->get($sku);
201+
}
202+
$availableVariants = $this->getExpectedProductVariants($configurable, $simples);
203+
204+
// Use exact match using two option values. Expect 1 simple product.
205+
$optionValues = $availableVariants[0]['option_values'];
206+
$this->optionSelectionRequestInterface->setStore('default');
207+
$this->optionSelectionRequestInterface->setValues($optionValues);
208+
/** @var $variantServiceItem ProductVariantResponse */
209+
$variantServiceItem = $this->variantService->getVariantsExactlyMatch($this->optionSelectionRequestInterface);
210+
$actual = $this->responseArrayMapper->convertToArray($variantServiceItem)['matched_variants'];
211+
$expected = [$availableVariants[0]];
212+
self::assertCount(1, $actual);
213+
$this->compare($expected, $actual);
214+
215+
// Use exact match using one option value. Expect 0 simple products.
216+
$optionValues = [$availableVariants[0]['option_values'][0]];
217+
$this->optionSelectionRequestInterface->setValues($optionValues);
218+
/** @var $variantServiceItem ProductVariantResponse */
219+
$variantServiceItem = $this->variantService->getVariantsExactlyMatch($this->optionSelectionRequestInterface);
220+
$actual = $this->responseArrayMapper->convertToArray($variantServiceItem)['matched_variants'];
221+
self::assertEmpty($actual);
222+
}
223+
224+
/**
225+
* Validate matching of variants by option values using getVariantsInclude
226+
*
227+
* @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_product_nine_simples.php
228+
* @magentoDbIsolation disabled
229+
* @throws NoSuchEntityException
230+
* @throws \Throwable
231+
*/
232+
public function testGetVariantsInclude(): void
233+
{
234+
//This sleep ensures that the elastic index has sufficient time to refresh
235+
//See https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-refresh.html#docs-refresh
236+
sleep(1);
237+
/** @var $configurable Product */
238+
$configurable = $this->productRepository->get('configurable');
239+
$simples = [];
240+
foreach (self::SIMPLE_SKUS as $sku) {
241+
$simples[] = $this->productRepository->get($sku);
242+
}
243+
$availableVariants = $this->getExpectedProductVariants($configurable, $simples);
244+
245+
// Use include match using two option values. Expect 6 simple products.
246+
$optionValues = [
247+
$availableVariants[0]['option_values'][0],
248+
$availableVariants[1]['option_values'][0]
249+
];
250+
$this->optionSelectionRequestInterface->setStore('default');
251+
$this->optionSelectionRequestInterface->setValues($optionValues);
252+
/** @var $variantServiceItem ProductVariantResponse */
253+
$variantServiceItem = $this->variantService->getVariantsInclude($this->optionSelectionRequestInterface);
254+
$actual = $this->responseArrayMapper->convertToArray($variantServiceItem)['matched_variants'];
255+
$expected = \array_values(\array_filter($availableVariants, function ($variant) use ($optionValues) {
256+
foreach ($optionValues as $optionValue) {
257+
if (\in_array($optionValue, $variant['option_values'])) {
258+
return true;
259+
}
260+
}
261+
return false;
262+
}));
263+
self::assertCount(6, $actual);
264+
$this->compare($expected, $actual);
265+
}
266+
190267
/**
191268
* Get the expected variants for configurable products.
192269
*

magento.proto

+2-5
Original file line numberDiff line numberDiff line change
@@ -460,13 +460,10 @@ service VariantService {
460460
rpc deleteProductVariants (DeleteVariantsRequest) returns (DeleteVariantsResponse) {}
461461
// get all variants that belong to a product
462462
rpc getProductVariants (ProductVariantRequest) returns (ProductVariantResponse) {}
463-
464463
// match the variants which correspond, and do not contradict, the merchant selection (%like operation)
465464
rpc getVariantsMatch (OptionSelectionRequest) returns (ProductVariantResponse) {}
466-
467-
// will be implemented in future
468465
// match the variants which exactly matched with merchant selection (&& operation)
469-
//rpc getVariantsExactlyMatch (OptionSelectionRequest) returns (ProductVariantResponse) {}
466+
rpc getVariantsExactlyMatch (OptionSelectionRequest) returns (ProductVariantResponse) {}
470467
// get all variants which contain at least one of merchant selection (|| operation)
471-
//rpc getVariantsInclude (OptionSelectionRequest) returns (ProductVariantResponse) {}
468+
rpc getVariantsInclude (OptionSelectionRequest) returns (ProductVariantResponse) {}
472469
}

0 commit comments

Comments
 (0)