-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
…ldren are out of stock and even if Display Out of Stock Products is set to "yes" - allow "out of stock" items to be used for price determination of configurable product ONLY in case all child products are "out of stock".
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
This comment has been minimized.
Sorry, something went wrong.
swnsma
|
||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
namespace Magento\ConfigurableProduct\Model\ResourceModel\Product; | ||
|
||
use Magento\Framework\DB\Select; | ||
|
||
/** | ||
* Interface BaseSelectProcessorInterface | ||
* @api | ||
*/ | ||
interface BaseSelectProcessorInterface | ||
{ | ||
/** | ||
* Product table alias | ||
*/ | ||
const PRODUCT_TABLE_ALIAS = 'child'; | ||
|
||
/** | ||
* @param Select $select | ||
* @param int $productId | ||
* @return Select | ||
*/ | ||
public function process(Select $select, $productId); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,6 @@ | |
*/ | ||
This comment has been minimized.
Sorry, something went wrong.
swnsma
|
||
namespace Magento\ConfigurableProduct\Model\ResourceModel\Product; | ||
|
||
use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; | ||
use Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderInterface; | ||
|
||
/** | ||
|
@@ -46,7 +45,7 @@ public function build($productId) | |
$selects = $this->linkedProductSelectBuilder->build($productId); | ||
|
||
foreach ($selects as $select) { | ||
$this->baseSelectProcessor->process($select); | ||
$this->baseSelectProcessor->process($select, $productId); | ||
} | ||
|
||
return $selects; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,13 +3,14 @@ | |
* Copyright © Magento, Inc. All rights reserved. | ||
This comment has been minimized.
Sorry, something went wrong.
swnsma
|
||
* See COPYING.txt for license details. | ||
*/ | ||
|
||
namespace Magento\ConfigurableProduct\Model\ResourceModel\Product; | ||
|
||
use Magento\Framework\DB\Select; | ||
use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; | ||
use Magento\CatalogInventory\Api\StockConfigurationInterface; | ||
use Magento\CatalogInventory\Model\Stock\Status as StockStatus; | ||
use Magento\CatalogInventory\Model\ResourceModel\Stock\Status as StockStatusResource; | ||
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\StockStatusInterface as StockStatusConfigurableInterface; | ||
|
||
/** | ||
* A Select object processor. | ||
|
@@ -28,24 +29,35 @@ class StockStatusBaseSelectProcessor implements BaseSelectProcessorInterface | |
*/ | ||
private $stockStatusResource; | ||
|
||
/** | ||
* @var StockStatusConfigurableInterface | ||
*/ | ||
private $stockStatusConfigurableResource; | ||
|
||
/** | ||
* @param StockConfigurationInterface $stockConfig | ||
* @param StockStatusResource $stockStatusResource | ||
* @param StockStatusConfigurableInterface $stockStatusConfigurableResource | ||
*/ | ||
public function __construct( | ||
StockConfigurationInterface $stockConfig, | ||
StockStatusResource $stockStatusResource | ||
) { | ||
StockStatusResource $stockStatusResource, | ||
StockStatusConfigurableInterface $stockStatusConfigurableResource | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
{ | ||
$this->stockConfig = $stockConfig; | ||
$this->stockStatusResource = $stockStatusResource; | ||
$this->stockStatusConfigurableResource = $stockStatusConfigurableResource; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function process(Select $select) | ||
public function process(Select $select, $productId) | ||
{ | ||
if ($this->stockConfig->isShowOutOfStock()) { | ||
if ($this->stockConfig->isShowOutOfStock() && | ||
!$this->isAllChildOutOfStock($productId) | ||
) { | ||
$select->joinInner( | ||
['stock' => $this->stockStatusResource->getMainTable()], | ||
sprintf( | ||
|
@@ -61,4 +73,14 @@ public function process(Select $select) | |
|
||
return $select; | ||
} | ||
|
||
/** | ||
* @param int $productId | ||
* @return bool | ||
* @throws \Exception | ||
*/ | ||
protected function isAllChildOutOfStock($productId) | ||
{ | ||
return $this->stockStatusConfigurableResource->isAllChildOutOfStock($productId); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
<?php | ||
This comment has been minimized.
Sorry, something went wrong.
swnsma
|
||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
namespace Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable; | ||
|
||
use Magento\Framework\EntityManager\MetadataPool; | ||
use Magento\Framework\App\ResourceConnection; | ||
use Magento\Catalog\Api\Data\ProductInterface; | ||
use Magento\CatalogInventory\Api\Data\StockStatusInterface as CatalogInventoryStockStatusInterface; | ||
|
||
class StockStatus implements StockStatusInterface | ||
{ | ||
/** | ||
* @var ResourceConnection | ||
*/ | ||
private $resource; | ||
|
||
/** | ||
* @var MetadataPool | ||
*/ | ||
private $metadataPool; | ||
|
||
/** | ||
* StockStatus constructor. | ||
* @param ResourceConnection $resource | ||
* @param MetadataPool $metadataPool | ||
*/ | ||
public function __construct(ResourceConnection $resource, MetadataPool $metadataPool) | ||
{ | ||
$this->resource = $resource; | ||
$this->metadataPool = $metadataPool; | ||
} | ||
|
||
/** | ||
* @var array | ||
*/ | ||
private $allChildOutOfStockInfo = []; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function isAllChildOutOfStock($productId) | ||
{ | ||
if (isset($this->allChildOutOfStockInfo[$productId])) { | ||
return $this->allChildOutOfStockInfo[$productId]; | ||
} | ||
|
||
$statuses = $this->getAllChildStockInfo($productId); | ||
$isAllChildOutOfStock = true; | ||
foreach ($statuses as $status) { | ||
if ($status == CatalogInventoryStockStatusInterface::STATUS_IN_STOCK) { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
$isAllChildOutOfStock = false; | ||
break; | ||
} | ||
} | ||
|
||
$this->allChildOutOfStockInfo[$productId] = $isAllChildOutOfStock; | ||
return $this->allChildOutOfStockInfo[$productId]; | ||
} | ||
|
||
/** | ||
* @return \Magento\Framework\DB\Adapter\AdapterInterface | ||
*/ | ||
protected function getConnection() | ||
{ | ||
return $this->resource->getConnection(ResourceConnection::DEFAULT_CONNECTION); | ||
This comment has been minimized.
Sorry, something went wrong.
swnsma
|
||
} | ||
|
||
/** | ||
* @param int $productId | ||
* @return array | ||
* @throws \Exception | ||
*/ | ||
protected function getAllChildStockInfo($productId) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
{ | ||
$linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); | ||
$productTable = $this->resource->getTableName('catalog_product_entity'); | ||
$productRelationTable = $this->resource->getTableName('catalog_product_relation'); | ||
|
||
$select = $this->getConnection()->select() | ||
->from(['parent' => $productTable], '', []) | ||
->joinInner( | ||
['link' => $productRelationTable], | ||
"link.parent_id = parent.$linkField", | ||
['id' => 'child_id'] | ||
)->joinInner( | ||
['stock' => $this->resource->getTableName('cataloginventory_stock_status')], | ||
'stock.product_id = link.child_id', | ||
['stock_status'] | ||
)->where(sprintf('parent.%s = ?', $linkField), $productId); | ||
|
||
return $this->getConnection()->fetchPairs($select); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
This comment has been minimized.
Sorry, something went wrong.
swnsma
|
||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
namespace Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable; | ||
|
||
/** | ||
* Interface StockStatusInterface | ||
* @api | ||
*/ | ||
interface StockStatusInterface | ||
{ | ||
/** | ||
* @param int $productId | ||
* @return bool | ||
* @throws \Exception | ||
*/ | ||
public function isAllChildOutOfStock($productId); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
use Magento\Framework\Pricing\Render\RendererPool; | ||
This comment has been minimized.
Sorry, something went wrong.
swnsma
|
||
use Magento\Framework\Pricing\SaleableInterface; | ||
use Magento\Framework\View\Element\Template\Context; | ||
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\StockStatus; | ||
|
||
class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox | ||
{ | ||
|
@@ -24,6 +25,11 @@ class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox | |
*/ | ||
private $lowestPriceOptionsProvider; | ||
|
||
/** | ||
* @var StockStatus | ||
*/ | ||
private $stockStatus; | ||
|
||
/** | ||
* @param Context $context | ||
* @param SaleableInterface $saleableItem | ||
|
@@ -34,6 +40,7 @@ class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox | |
* @param LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider | ||
* @param SalableResolverInterface|null $salableResolver | ||
* @param MinimalPriceCalculatorInterface|null $minimalPriceCalculator | ||
* @param StockStatus $stockStatus | ||
* @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||
*/ | ||
public function __construct( | ||
|
@@ -45,7 +52,8 @@ public function __construct( | |
array $data = [], | ||
LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null, | ||
SalableResolverInterface $salableResolver = null, | ||
MinimalPriceCalculatorInterface $minimalPriceCalculator = null | ||
MinimalPriceCalculatorInterface $minimalPriceCalculator = null, | ||
StockStatus $stockStatus = null | ||
) { | ||
parent::__construct( | ||
$context, | ||
|
@@ -58,6 +66,7 @@ public function __construct( | |
); | ||
$this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?: | ||
ObjectManager::getInstance()->get(LowestPriceOptionsProviderInterface::class); | ||
$this->stockStatus = $stockStatus ?: ObjectManager::getInstance()->get(StockStatus::class); | ||
} | ||
|
||
/** | ||
|
@@ -77,4 +86,12 @@ public function hasSpecialPrice() | |
} | ||
return false; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
protected function isApplySalableCheck(SaleableInterface $salableItem) | ||
{ | ||
return !$this->stockStatus->isAllChildOutOfStock($salableItem->getId()); | ||
} | ||
} |
1 comment
on commit 80f6a36
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed and fixed
declare(strict_types=1); is missed.