diff --git a/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/StockProcessor.php b/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/StockProcessor.php
index 61085c10a73..2cfb96b0fab 100644
--- a/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/StockProcessor.php
+++ b/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/StockProcessor.php
@@ -57,8 +57,10 @@ class StockProcessor implements CollectionProcessorInterface
array $attributeNames,
ContextInterface $context = null
): Collection {
- if (!$this->stockConfig->isShowOutOfStock()) {
- $this->stockStatusResource->addIsInStockFilterToCollection($collection);
+ $stockFlag = 'has_stock_status_filter';
+ if (!$collection->hasFlag($stockFlag)) {
+ $this->stockStatusResource->addStockDataToCollection($collection, !$this->stockConfig->isShowOutOfStock());
+ $collection->setFlag($stockFlag, true);
}
return $collection;
diff --git a/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsCompositeFilter.php b/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsCompositeFilter.php
new file mode 100644
index 00000000000..c6bc7cbd296
--- /dev/null
+++ b/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsCompositeFilter.php
@@ -0,0 +1,51 @@
+configurableOptionsFilters = $configurableOptionsFilters;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function filter(ProductInterface $parentProduct, array $childProducts): array
+ {
+ foreach ($this->configurableOptionsFilters as $configurableOptionsFilter) {
+ $childProducts = $configurableOptionsFilter->filter($parentProduct, $childProducts);
+ }
+ return $childProducts;
+ }
+}
diff --git a/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsFilterInterface.php b/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsFilterInterface.php
new file mode 100644
index 00000000000..cc38764b683
--- /dev/null
+++ b/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsFilterInterface.php
@@ -0,0 +1,25 @@
+configurable = $configurable;
+ $this->configurableOptionsFilter = $configurableOptionsFilter
+ ?? ObjectManager::getInstance()->get(ConfigurableOptionsFilterInterface::class);
}
/**
@@ -39,7 +49,10 @@ class ConfigurableOptionsProvider implements ConfigurableOptionsProviderInterfac
public function getProducts(ProductInterface $product)
{
if (!isset($this->products[$product->getId()])) {
- $this->products[$product->getId()] = $this->configurable->getUsedProducts($product);
+ $this->products[$product->getId()] = $this->configurableOptionsFilter->filter(
+ $product,
+ $this->configurable->getUsedProducts($product)
+ );
}
return $this->products[$product->getId()];
}
diff --git a/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsStatusFilter.php b/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsStatusFilter.php
new file mode 100644
index 00000000000..5394b27ed96
--- /dev/null
+++ b/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsStatusFilter.php
@@ -0,0 +1,29 @@
+getStatus() === Status::STATUS_ENABLED) {
+ $result[] = $childProduct;
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsStockStatusFilter.php b/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsStockStatusFilter.php
new file mode 100644
index 00000000000..fb3d87c9ddb
--- /dev/null
+++ b/vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsStockStatusFilter.php
@@ -0,0 +1,62 @@
+stockConfig = $stockConfig;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function filter(ProductInterface $parentProduct, array $childProducts): array
+ {
+ if ($this->stockConfig->isShowOutOfStock()) {
+ $result = $childProducts;
+ if ($parentProduct->getIsSalable()) {
+ $result = $this->filterInStockProducts($childProducts) ?: $childProducts;
+ }
+ } else {
+ $result = $this->filterInStockProducts($childProducts);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns in-stock products
+ *
+ * @param ProductInterface[] $childProducts
+ * @return ProductInterface[]
+ */
+ private function filterInStockProducts(array $childProducts): array
+ {
+ $result = [];
+ foreach ($childProducts as $childProduct) {
+ if ($childProduct->getIsSalable()) {
+ $result[] = $childProduct;
+ }
+ }
+ return $result;
+ }
+}
diff --git a/vendor/magento/module-configurable-product/etc/di.xml b/vendor/magento/module-configurable-product/etc/di.xml
index 833ee99583b..b3ed7d46a40 100644
--- a/vendor/magento/module-configurable-product/etc/di.xml
+++ b/vendor/magento/module-configurable-product/etc/di.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/vendor/magento/module-configurable-product/etc/frontend/di.xml b/vendor/magento/module-configurable-product/etc/frontend/di.xml
index 3942ec52cbb..d170e6840d7 100644
--- a/vendor/magento/module-configurable-product/etc/frontend/di.xml
+++ b/vendor/magento/module-configurable-product/etc/frontend/di.xml
@@ -14,4 +14,12 @@
+
+
+
+ - Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsStatusFilter
+ - Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsStockStatusFilter
+
+
+
diff --git a/vendor/magento/module-configurable-product-graph-ql/Model/Options/DataProvider/Variant.php b/vendor/magento/module-configurable-product-graph-ql/Model/Options/DataProvider/Variant.php
index 7b5a3fb806a..32b9b2a48a3 100644
--- a/vendor/magento/module-configurable-product-graph-ql/Model/Options/DataProvider/Variant.php
+++ b/vendor/magento/module-configurable-product-graph-ql/Model/Options/DataProvider/Variant.php
@@ -52,8 +52,6 @@ class Variant
$collection
->addAttributeToSelect('*')
->addFilterByRequiredOptions();
- $collection->addMediaGalleryData();
- $collection->addTierPriceData();
$stockFlag = 'has_stock_status_filter';
if (!$collection->hasFlag($stockFlag)) {
@@ -61,7 +59,8 @@ class Variant
$stockStatusResource->addStockDataToCollection($collection, true);
$collection->setFlag($stockFlag, true);
}
- $collection->clear();
+ $collection->addMediaGalleryData();
+ $collection->addTierPriceData();
return $collection->getItems() ?? [];
}
diff --git a/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/Product/Price/Provider.php b/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/Product/Price/Provider.php
index 4dfa09d77ce..2d52c558469 100644
--- a/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/Product/Price/Provider.php
+++ b/vendor/magento/module-configurable-product-graph-ql/Model/Resolver/Product/Price/Provider.php
@@ -9,11 +9,11 @@ namespace Magento\ConfigurableProductGraphQl\Model\Resolver\Product\Price;
use Magento\Catalog\Pricing\Price\FinalPrice;
use Magento\Catalog\Pricing\Price\RegularPrice;
-use Magento\ConfigurableProduct\Pricing\Price\ConfigurableRegularPrice;
use Magento\Framework\Pricing\Amount\AmountInterface;
use Magento\Framework\Pricing\SaleableInterface;
use Magento\CatalogGraphQl\Model\Resolver\Product\Price\ProviderInterface;
use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface;
+use Magento\Framework\Pricing\Amount\BaseFactory;
/**
* Provides product prices for configurable products
@@ -25,23 +25,37 @@ class Provider implements ProviderInterface
*/
private $optionsProvider;
+ /**
+ * @var BaseFactory
+ */
+ private $amountFactory;
+
/**
* @var array
*/
- private $minimumFinalAmounts = [];
+ private $minimalPrice = [
+ FinalPrice::PRICE_CODE => [],
+ RegularPrice::PRICE_CODE => []
+ ];
/**
* @var array
*/
- private $maximumFinalAmounts = [];
+ private $maximalPrice = [
+ FinalPrice::PRICE_CODE => [],
+ RegularPrice::PRICE_CODE => []
+ ];
/**
* @param ConfigurableOptionsProviderInterface $optionsProvider
+ * @param BaseFactory $amountFactory
*/
public function __construct(
- ConfigurableOptionsProviderInterface $optionsProvider
+ ConfigurableOptionsProviderInterface $optionsProvider,
+ BaseFactory $amountFactory
) {
$this->optionsProvider = $optionsProvider;
+ $this->amountFactory = $amountFactory;
}
/**
@@ -49,18 +63,7 @@ class Provider implements ProviderInterface
*/
public function getMinimalFinalPrice(SaleableInterface $product): AmountInterface
{
- if (!isset($this->minimumFinalAmounts[$product->getId()])) {
- $minimumAmount = null;
- foreach ($this->optionsProvider->getProducts($product) as $variant) {
- $variantAmount = $variant->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getAmount();
- if (!$minimumAmount || ($variantAmount->getValue() < $minimumAmount->getValue())) {
- $minimumAmount = $variantAmount;
- $this->minimumFinalAmounts[$product->getId()] = $variantAmount;
- }
- }
- }
-
- return $this->minimumFinalAmounts[$product->getId()];
+ return $this->getMinimalPrice($product, FinalPrice::PRICE_CODE);
}
/**
@@ -68,9 +71,7 @@ class Provider implements ProviderInterface
*/
public function getMinimalRegularPrice(SaleableInterface $product): AmountInterface
{
- /** @var ConfigurableRegularPrice $regularPrice */
- $regularPrice = $product->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE);
- return $regularPrice->getMinRegularAmount();
+ return $this->getMinimalPrice($product, RegularPrice::PRICE_CODE);
}
/**
@@ -78,18 +79,7 @@ class Provider implements ProviderInterface
*/
public function getMaximalFinalPrice(SaleableInterface $product): AmountInterface
{
- if (!isset($this->maximumFinalAmounts[$product->getId()])) {
- $maximumAmount = null;
- foreach ($this->optionsProvider->getProducts($product) as $variant) {
- $variantAmount = $variant->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getAmount();
- if (!$maximumAmount || ($variantAmount->getValue() > $maximumAmount->getValue())) {
- $maximumAmount = $variantAmount;
- $this->maximumFinalAmounts[$product->getId()] = $variantAmount;
- }
- }
- }
-
- return $this->maximumFinalAmounts[$product->getId()];
+ return $this->getMaximalPrice($product, FinalPrice::PRICE_CODE);
}
/**
@@ -97,9 +87,7 @@ class Provider implements ProviderInterface
*/
public function getMaximalRegularPrice(SaleableInterface $product): AmountInterface
{
- /** @var ConfigurableRegularPrice $regularPrice */
- $regularPrice = $product->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE);
- return $regularPrice->getMaxRegularAmount();
+ return $this->getMaximalPrice($product, RegularPrice::PRICE_CODE);
}
/**
@@ -109,4 +97,50 @@ class Provider implements ProviderInterface
{
return $product->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE)->getAmount();
}
+
+ /**
+ * Get minimal price from child products
+ *
+ * @param SaleableInterface $product
+ * @param string $code
+ * @return AmountInterface
+ */
+ private function getMinimalPrice(SaleableInterface $product, string $code): AmountInterface
+ {
+ if (!isset($this->minimalPrice[$code][$product->getId()])) {
+ $minimumAmount = null;
+ foreach ($this->optionsProvider->getProducts($product) as $variant) {
+ $variantAmount = $variant->getPriceInfo()->getPrice($code)->getAmount();
+ if (!$minimumAmount || ($variantAmount->getValue() < $minimumAmount->getValue())) {
+ $minimumAmount = $variantAmount;
+ $this->minimalPrice[$code][$product->getId()] = $variantAmount;
+ }
+ }
+ }
+
+ return $this->minimalPrice[$code][$product->getId()] ?? $this->amountFactory->create(['amount' => null]);
+ }
+
+ /**
+ * Get maximal price from child products
+ *
+ * @param SaleableInterface $product
+ * @param string $code
+ * @return AmountInterface
+ */
+ private function getMaximalPrice(SaleableInterface $product, string $code): AmountInterface
+ {
+ if (!isset($this->maximalPrice[$code][$product->getId()])) {
+ $maximumAmount = null;
+ foreach ($this->optionsProvider->getProducts($product) as $variant) {
+ $variantAmount = $variant->getPriceInfo()->getPrice($code)->getAmount();
+ if (!$maximumAmount || ($variantAmount->getValue() > $maximumAmount->getValue())) {
+ $maximumAmount = $variantAmount;
+ $this->maximalPrice[$code][$product->getId()] = $variantAmount;
+ }
+ }
+ }
+
+ return $this->maximalPrice[$code][$product->getId()] ?? $this->amountFactory->create(['amount' => null]);
+ }
}
diff --git a/vendor/magento/module-configurable-product-graph-ql/Plugin/AddStockStatusToCollection.php b/vendor/magento/module-configurable-product-graph-ql/Plugin/AddStockStatusToCollection.php
new file mode 100644
index 00000000000..c12847d2082
--- /dev/null
+++ b/vendor/magento/module-configurable-product-graph-ql/Plugin/AddStockStatusToCollection.php
@@ -0,0 +1,49 @@
+stockStatusResourceModel = $stockStatusResourceModel;
+ }
+
+ /**
+ * Add stock data to the collection.
+ *
+ * @param Collection $productCollection
+ * @param bool $printQuery
+ * @param bool $logQuery
+ * @return array
+ */
+ public function beforeLoad(Collection $productCollection, $printQuery = false, $logQuery = false): array
+ {
+ $stockFlag = 'has_stock_status_filter';
+ if (!$productCollection->hasFlag($stockFlag)) {
+ $this->stockStatusResourceModel->addStockDataToCollection($productCollection, false);
+ $productCollection->setFlag($stockFlag, true);
+ }
+ return [$printQuery, $logQuery];
+ }
+}
diff --git a/vendor/magento/module-configurable-product-graph-ql/etc/graphql/di.xml b/vendor/magento/module-configurable-product-graph-ql/etc/graphql/di.xml
index 1456068058c..5f6850434ea 100644
--- a/vendor/magento/module-configurable-product-graph-ql/etc/graphql/di.xml
+++ b/vendor/magento/module-configurable-product-graph-ql/etc/graphql/di.xml
@@ -73,4 +73,15 @@
+
+
+
+ - Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsStatusFilter
+ - Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsStockStatusFilter
+
+
+
+
+
+