Skip to content

Commit da99b7b

Browse files
MAGETWO-87251: [Backport 2.3] #12936 out-of-stock options for configurable product visible as sellable #13417
- Merge Pull Request #13417 from Coderimus/magento2:backport/stock-status-filter-fix-for-configurable-products - Merged commits: 1. d9111b0
2 parents 8c705bf + d9111b0 commit da99b7b

File tree

3 files changed

+46
-36
lines changed

3 files changed

+46
-36
lines changed

app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
*/
66
namespace Magento\CatalogInventory\Model\ResourceModel\Stock;
77

8-
use Magento\CatalogInventory\Model\Stock;
98
use Magento\CatalogInventory\Api\StockConfigurationInterface;
9+
use Magento\CatalogInventory\Model\Stock;
1010
use Magento\Framework\App\ObjectManager;
1111

1212
/**
@@ -46,19 +46,23 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
4646
* @param \Magento\Store\Model\WebsiteFactory $websiteFactory
4747
* @param \Magento\Eav\Model\Config $eavConfig
4848
* @param string $connectionName
49+
* @param \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration
4950
*/
5051
public function __construct(
5152
\Magento\Framework\Model\ResourceModel\Db\Context $context,
5253
\Magento\Store\Model\StoreManagerInterface $storeManager,
5354
\Magento\Store\Model\WebsiteFactory $websiteFactory,
5455
\Magento\Eav\Model\Config $eavConfig,
55-
$connectionName = null
56+
$connectionName = null,
57+
$stockConfiguration = null
5658
) {
5759
parent::__construct($context, $connectionName);
5860

5961
$this->_storeManager = $storeManager;
6062
$this->_websiteFactory = $websiteFactory;
6163
$this->eavConfig = $eavConfig;
64+
$this->stockConfiguration = $stockConfiguration ?: ObjectManager::getInstance()
65+
->get(StockConfigurationInterface::class);
6266
}
6367

6468
/**
@@ -204,7 +208,7 @@ public function getProductCollection($lastEntityId = 0, $limit = 1000)
204208
*/
205209
public function addStockStatusToSelect(\Magento\Framework\DB\Select $select, \Magento\Store\Model\Website $website)
206210
{
207-
$websiteId = $this->getStockConfiguration()->getDefaultScopeId();
211+
$websiteId = $this->getWebsiteId($website->getId());
208212
$select->joinLeft(
209213
['stock_status' => $this->getMainTable()],
210214
'e.entity_id = stock_status.product_id AND stock_status.website_id=' . $websiteId,
@@ -221,7 +225,7 @@ public function addStockStatusToSelect(\Magento\Framework\DB\Select $select, \Ma
221225
*/
222226
public function addStockDataToCollection($collection, $isFilterInStock)
223227
{
224-
$websiteId = $this->getStockConfiguration()->getDefaultScopeId();
228+
$websiteId = $this->getWebsiteId();
225229
$joinCondition = $this->getConnection()->quoteInto(
226230
'e.entity_id = stock_status_index.product_id' . ' AND stock_status_index.website_id = ?',
227231
$websiteId
@@ -255,7 +259,7 @@ public function addStockDataToCollection($collection, $isFilterInStock)
255259
*/
256260
public function addIsInStockFilterToCollection($collection)
257261
{
258-
$websiteId = $this->getStockConfiguration()->getDefaultScopeId();
262+
$websiteId = $this->getWebsiteId();
259263
$joinCondition = $this->getConnection()->quoteInto(
260264
'e.entity_id = stock_status_index.product_id' . ' AND stock_status_index.website_id = ?',
261265
$websiteId
@@ -277,6 +281,19 @@ public function addIsInStockFilterToCollection($collection)
277281
return $this;
278282
}
279283

284+
/**
285+
* @param \Magento\Store\Model\Website $websiteId
286+
* @return int
287+
*/
288+
private function getWebsiteId($websiteId = null)
289+
{
290+
if (null === $websiteId) {
291+
$websiteId = $this->stockConfiguration->getDefaultScopeId();
292+
}
293+
294+
return $websiteId;
295+
}
296+
280297
/**
281298
* Retrieve Product(s) status for store
282299
* Return array where key is a product_id, value - status
@@ -335,18 +352,4 @@ public function getProductStatus($productIds, $storeId = null)
335352
}
336353
return $statuses;
337354
}
338-
339-
/**
340-
* @return StockConfigurationInterface
341-
*
342-
* @deprecated 100.1.0
343-
*/
344-
private function getStockConfiguration()
345-
{
346-
if ($this->stockConfiguration === null) {
347-
$this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance()
348-
->get(\Magento\CatalogInventory\Api\StockConfigurationInterface::class);
349-
}
350-
return $this->stockConfiguration;
351-
}
352355
}

app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
namespace Magento\ConfigurableProduct\Model\Product\Type;
78

89
use Magento\Catalog\Api\Data\ProductAttributeInterface;
910
use Magento\Catalog\Api\Data\ProductInterface;
1011
use Magento\Catalog\Api\Data\ProductInterfaceFactory;
1112
use Magento\Catalog\Api\ProductRepositoryInterface;
12-
use Magento\ConfigurableProduct\Model\Product\Type\Collection\SalableProcessor;
1313
use Magento\Catalog\Model\Config;
14+
use Magento\Catalog\Model\Product\Gallery\ReadHandler as GalleryReadHandler;
15+
use Magento\ConfigurableProduct\Model\Product\Type\Collection\SalableProcessor;
1416
use Magento\Framework\App\ObjectManager;
1517
use Magento\Framework\EntityManager\MetadataPool;
16-
use Magento\Catalog\Model\Product\Gallery\ReadHandler as GalleryReadHandler;
1718

1819
/**
1920
* Configurable product type implementation
@@ -266,7 +267,6 @@ public function __construct(
266267
$productRepository,
267268
$serializer
268269
);
269-
270270
}
271271

272272
/**
@@ -682,7 +682,7 @@ private function saveConfigurableOptions(ProductInterface $product)
682682
->setProductId($product->getData($metadata->getLinkField()))
683683
->save();
684684
}
685-
/** @var $configurableAttributesCollection \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection */
685+
/** @var $configurableAttributesCollection \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection */
686686
$configurableAttributesCollection = $this->_attributeCollectionFactory->create();
687687
$configurableAttributesCollection->setProductFilter($product);
688688
$configurableAttributesCollection->addFieldToFilter(
@@ -1276,6 +1276,8 @@ public function getSalableUsedProducts(\Magento\Catalog\Model\Product $product,
12761276
* Load collection on sub-products for specified configurable product
12771277
*
12781278
* Load collection of sub-products, apply result to specified configurable product and store result to cache
1279+
* Please note $salableOnly parameter is used for backwards compatibility because of deprecated method
1280+
* getSalableUsedProducts
12791281
* Number of loaded sub-products depends on $salableOnly parameter
12801282
* $salableOnly = true - result array contains only salable sub-products
12811283
* $salableOnly = false - result array contains all sub-products
@@ -1292,7 +1294,7 @@ private function loadUsedProducts(\Magento\Catalog\Model\Product $product, $cach
12921294
if (!$product->hasData($dataFieldName)) {
12931295
$usedProducts = $this->readUsedProductsCacheData($cacheKey);
12941296
if ($usedProducts === null) {
1295-
$collection = $this->getConfiguredUsedProductCollection($product);
1297+
$collection = $this->getConfiguredUsedProductCollection($product, false);
12961298
if ($salableOnly) {
12971299
$collection = $this->salableProcessor->process($collection);
12981300
}
@@ -1386,13 +1388,18 @@ private function getUsedProductsCacheKey($keyParts)
13861388
* Retrieve related products collection with additional configuration
13871389
*
13881390
* @param \Magento\Catalog\Model\Product $product
1391+
* @param bool $skipStockFilter
13891392
* @return \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection
13901393
*/
1391-
private function getConfiguredUsedProductCollection(\Magento\Catalog\Model\Product $product)
1392-
{
1394+
private function getConfiguredUsedProductCollection(
1395+
\Magento\Catalog\Model\Product $product,
1396+
$skipStockFilter = true
1397+
) {
13931398
$collection = $this->getUsedProductCollection($product);
1399+
if ($skipStockFilter) {
1400+
$collection->setFlag('has_stock_status_filter', true);
1401+
}
13941402
$collection
1395-
->setFlag('has_stock_status_filter', true)
13961403
->addAttributeToSelect($this->getCatalogConfig()->getProductAttributes())
13971404
->addFilterByRequiredOptions()
13981405
->setStoreId($product->getStoreId());

app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@
88
use Magento\Catalog\Api\Data\ProductExtensionInterface;
99
use Magento\Catalog\Api\Data\ProductInterface;
1010
use Magento\Catalog\Model\Config;
11-
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
12-
use Magento\Framework\EntityManager\EntityMetadata;
13-
use Magento\Framework\EntityManager\MetadataPool;
14-
use Magento\Customer\Model\Session;
15-
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\CollectionFactory;
16-
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection;
1711
use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface;
18-
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
12+
use Magento\ConfigurableProduct\Model\Product\Type\Collection\SalableProcessor;
13+
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
1914
use Magento\ConfigurableProduct\Model\Product\Type\Configurable\AttributeFactory;
15+
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection;
16+
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\CollectionFactory;
17+
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection as ProductCollection;
2018
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\ConfigurableFactory;
19+
use Magento\Customer\Model\Session;
2120
use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend;
2221
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
23-
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection as ProductCollection;
24-
use Magento\ConfigurableProduct\Model\Product\Type\Collection\SalableProcessor;
22+
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
23+
use Magento\Framework\EntityManager\EntityMetadata;
24+
use Magento\Framework\EntityManager\MetadataPool;
2525

2626
/**
2727
* @SuppressWarnings(PHPMD.LongVariable)

0 commit comments

Comments
 (0)