Skip to content

Commit 11da387

Browse files
committed
Merge remote-tracking branch 'sasha19957099/31332_schema_changes_implementation_for_configurable_options_selection' into PWA-1326
# Conflicts: # app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php # app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls # dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartSingleMutationTest.php # dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionMetadataTest.php
2 parents d3f202a + b339166 commit 11da387

File tree

17 files changed

+870
-233
lines changed

17 files changed

+870
-233
lines changed

app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use Magento\Framework\Api\Search\SearchResultInterface;
1919
use Magento\Framework\Api\SearchCriteriaInterface;
2020
use Magento\Framework\Api\SearchResultsInterface;
21+
use Magento\Framework\Exception\LocalizedException;
22+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
2123
use Magento\GraphQl\Model\Query\ContextInterface;
2224

2325
/**
@@ -87,6 +89,7 @@ public function __construct(
8789
* @param array $attributes
8890
* @param ContextInterface|null $context
8991
* @return SearchResultsInterface
92+
* @throws GraphQlNoSuchEntityException
9093
*/
9194
public function getList(
9295
SearchCriteriaInterface $searchCriteria,
@@ -107,6 +110,13 @@ public function getList(
107110
)->apply();
108111

109112
$this->collectionPreProcessor->process($collection, $searchCriteriaForCollection, $attributes, $context);
113+
114+
try {
115+
$collection->addMediaGalleryData();
116+
} catch (LocalizedException $e) {
117+
throw new GraphQlNoSuchEntityException(__('Cannot load media gallery'));
118+
}
119+
110120
$collection->load();
111121
$this->collectionPostProcessor->process($collection, $attributes);
112122

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\ConfigurableProductGraphQl\Model\Formatter;
10+
11+
use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute;
12+
use Magento\Framework\GraphQl\Query\Uid;
13+
14+
/**
15+
* Formatter for configurable product options
16+
*/
17+
class Option
18+
{
19+
/**
20+
* @var Uid
21+
*/
22+
private $idEncoder;
23+
24+
/**
25+
* @var OptionValue
26+
*/
27+
private $valueFormatter;
28+
29+
/**
30+
* @param Uid $idEncoder
31+
* @param OptionValue $valueFormatter
32+
*/
33+
public function __construct(
34+
Uid $idEncoder,
35+
OptionValue $valueFormatter
36+
) {
37+
$this->idEncoder = $idEncoder;
38+
$this->valueFormatter = $valueFormatter;
39+
}
40+
41+
/**
42+
* Format configurable product options according to the GraphQL schema
43+
*
44+
* @param Attribute $attribute
45+
* @param array $optionIds
46+
* @return array|null
47+
*/
48+
public function format(Attribute $attribute, array $optionIds): ?array
49+
{
50+
$optionValues = [];
51+
52+
foreach ($attribute->getOptions() as $option) {
53+
$optionValues[] = $this->valueFormatter->format($option, $attribute, $optionIds);
54+
}
55+
56+
return [
57+
'uid' => $this->idEncoder->encode($attribute->getProductSuperAttributeId()),
58+
'attribute_code' => $attribute->getProductAttribute()->getAttributeCode(),
59+
'label' => $attribute->getLabel(),
60+
'values' => $optionValues,
61+
];
62+
}
63+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\ConfigurableProductGraphQl\Model\Formatter;
10+
11+
use Magento\CatalogInventory\Model\StockRegistry;
12+
use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute;
13+
use Magento\ConfigurableProductGraphQl\Model\Options\SelectionUidFormatter;
14+
use Magento\SwatchesGraphQl\Model\Resolver\Product\Options\DataProvider\SwatchDataProvider;
15+
16+
/**
17+
* Formatter for configurable product option values
18+
*/
19+
class OptionValue
20+
{
21+
/**
22+
* @var SelectionUidFormatter
23+
*/
24+
private $selectionUidFormatter;
25+
26+
/**
27+
* @var SwatchDataProvider
28+
*/
29+
private $swatchDataProvider;
30+
31+
/**
32+
* @var StockRegistry
33+
*/
34+
private $stockRegistry;
35+
36+
/**
37+
* @param SelectionUidFormatter $selectionUidFormatter
38+
* @param SwatchDataProvider $swatchDataProvider
39+
* @param StockRegistry $stockRegistry
40+
*/
41+
public function __construct(
42+
SelectionUidFormatter $selectionUidFormatter,
43+
SwatchDataProvider $swatchDataProvider,
44+
StockRegistry $stockRegistry
45+
) {
46+
$this->selectionUidFormatter = $selectionUidFormatter;
47+
$this->swatchDataProvider = $swatchDataProvider;
48+
$this->stockRegistry = $stockRegistry;
49+
}
50+
51+
/**
52+
* Format configurable product option values according to the GraphQL schema
53+
*
54+
* @param array $optionValue
55+
* @param Attribute $attribute
56+
* @param array $optionIds
57+
* @return array
58+
*/
59+
public function format(array $optionValue, Attribute $attribute, array $optionIds): array
60+
{
61+
$valueIndex = (int)$optionValue['value_index'];
62+
$attributeId = (int)$attribute->getAttributeId();
63+
64+
return [
65+
'uid' => $this->selectionUidFormatter->encode(
66+
$attributeId,
67+
$valueIndex
68+
),
69+
'is_available' => $this->getIsAvailable($optionIds[$valueIndex] ?? []),
70+
'is_use_default' => (bool)$attribute->getIsUseDefault(),
71+
'label' => $optionValue['label'],
72+
'swatch' => $this->swatchDataProvider->getData($optionValue['value_index'])
73+
];
74+
}
75+
76+
/**
77+
* Get is variants available
78+
*
79+
* @param array $variantIds
80+
* @return bool
81+
*/
82+
private function getIsAvailable(array $variantIds): bool
83+
{
84+
foreach ($variantIds as $variantId) {
85+
if ($this->stockRegistry->getProductStockStatus($variantId)) {
86+
return true;
87+
}
88+
}
89+
90+
return false;
91+
}
92+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\ConfigurableProductGraphQl\Model\Formatter;
10+
11+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
12+
13+
/**
14+
* Formatter for configurable product variant
15+
*/
16+
class Variant
17+
{
18+
/**
19+
* Format selected variant of configurable product based on selected options
20+
*
21+
* @param array $options
22+
* @param array $selectedOptions
23+
* @param array $variants
24+
* @return array|null
25+
* @throws GraphQlInputException
26+
*/
27+
public function format(array $options, array $selectedOptions, array $variants): ?array
28+
{
29+
$variant = null;
30+
$productIds = array_keys($variants);
31+
32+
foreach ($selectedOptions as $attributeId => $selectedValue) {
33+
if (!isset($options[$attributeId][$selectedValue])) {
34+
throw new GraphQlInputException(__('configurableOptionValueUids values are incorrect'));
35+
}
36+
37+
$productIds = array_intersect($productIds, $options[$attributeId][$selectedValue]);
38+
}
39+
40+
if (count($productIds) === 1) {
41+
$variantProduct = $variants[array_pop($productIds)];
42+
$variant = $variantProduct->getData();
43+
$variant['url_path'] = $variantProduct->getProductUrl();
44+
$variant['model'] = $variantProduct;
45+
}
46+
47+
return $variant;
48+
}
49+
}

app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use Magento\Catalog\Api\Data\ProductInterface;
1111
use Magento\CatalogInventory\Model\ResourceModel\Stock\StatusFactory;
1212
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
13+
use Magento\Framework\DataObject;
14+
use Magento\Framework\Exception\LocalizedException;
1315

1416
/**
1517
* Retrieve child products
@@ -42,10 +44,10 @@ public function __construct(
4244
* Load available child products by parent
4345
*
4446
* @param ProductInterface $product
45-
* @return ProductInterface[]
46-
* @throws \Magento\Framework\Exception\LocalizedException
47+
* @return DataObject[]
48+
* @throws LocalizedException
4749
*/
48-
public function getSalableVariantsByParent(ProductInterface $product)
50+
public function getSalableVariantsByParent(ProductInterface $product): array
4951
{
5052
$collection = $this->configurableType->getUsedProductCollection($product);
5153
$collection
@@ -62,6 +64,6 @@ public function getSalableVariantsByParent(ProductInterface $product)
6264
}
6365
$collection->clear();
6466

65-
return $collection->getItems();
67+
return $collection->getItems() ?? [];
6668
}
6769
}

0 commit comments

Comments
 (0)