Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 2.3] #12936 out-of-stock options for configurable product visible as sellable #13417

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*/
namespace Magento\CatalogInventory\Model\ResourceModel\Stock;

use Magento\CatalogInventory\Model\Stock;
use Magento\CatalogInventory\Api\StockConfigurationInterface;
use Magento\CatalogInventory\Model\Stock;
use Magento\Framework\App\ObjectManager;

/**
Expand Down Expand Up @@ -46,19 +46,23 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
* @param \Magento\Store\Model\WebsiteFactory $websiteFactory
* @param \Magento\Eav\Model\Config $eavConfig
* @param string $connectionName
* @param \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration
*/
public function __construct(
\Magento\Framework\Model\ResourceModel\Db\Context $context,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Store\Model\WebsiteFactory $websiteFactory,
\Magento\Eav\Model\Config $eavConfig,
$connectionName = null
$connectionName = null,
$stockConfiguration = null
) {
parent::__construct($context, $connectionName);

$this->_storeManager = $storeManager;
$this->_websiteFactory = $websiteFactory;
$this->eavConfig = $eavConfig;
$this->stockConfiguration = $stockConfiguration ?: ObjectManager::getInstance()
->get(StockConfigurationInterface::class);
}

/**
Expand Down Expand Up @@ -204,7 +208,7 @@ public function getProductCollection($lastEntityId = 0, $limit = 1000)
*/
public function addStockStatusToSelect(\Magento\Framework\DB\Select $select, \Magento\Store\Model\Website $website)
{
$websiteId = $this->getStockConfiguration()->getDefaultScopeId();
$websiteId = $this->getWebsiteId($website->getId());
$select->joinLeft(
['stock_status' => $this->getMainTable()],
'e.entity_id = stock_status.product_id AND stock_status.website_id=' . $websiteId,
Expand All @@ -221,7 +225,7 @@ public function addStockStatusToSelect(\Magento\Framework\DB\Select $select, \Ma
*/
public function addStockDataToCollection($collection, $isFilterInStock)
{
$websiteId = $this->getStockConfiguration()->getDefaultScopeId();
$websiteId = $this->getWebsiteId();
$joinCondition = $this->getConnection()->quoteInto(
'e.entity_id = stock_status_index.product_id' . ' AND stock_status_index.website_id = ?',
$websiteId
Expand Down Expand Up @@ -255,7 +259,7 @@ public function addStockDataToCollection($collection, $isFilterInStock)
*/
public function addIsInStockFilterToCollection($collection)
{
$websiteId = $this->getStockConfiguration()->getDefaultScopeId();
$websiteId = $this->getWebsiteId();
$joinCondition = $this->getConnection()->quoteInto(
'e.entity_id = stock_status_index.product_id' . ' AND stock_status_index.website_id = ?',
$websiteId
Expand All @@ -277,6 +281,19 @@ public function addIsInStockFilterToCollection($collection)
return $this;
}

/**
* @param \Magento\Store\Model\Website $websiteId
* @return int
*/
private function getWebsiteId($websiteId = null)
{
if (null === $websiteId) {
$websiteId = $this->stockConfiguration->getDefaultScopeId();
}

return $websiteId;
}

/**
* Retrieve Product(s) status for store
* Return array where key is a product_id, value - status
Expand Down Expand Up @@ -335,18 +352,4 @@ public function getProductStatus($productIds, $storeId = null)
}
return $statuses;
}

/**
* @return StockConfigurationInterface
*
* @deprecated 100.1.0
*/
private function getStockConfiguration()
{
if ($this->stockConfiguration === null) {
$this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\CatalogInventory\Api\StockConfigurationInterface::class);
}
return $this->stockConfiguration;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\ConfigurableProduct\Model\Product\Type;

use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductInterfaceFactory;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\ConfigurableProduct\Model\Product\Type\Collection\SalableProcessor;
use Magento\Catalog\Model\Config;
use Magento\Catalog\Model\Product\Gallery\ReadHandler as GalleryReadHandler;
use Magento\ConfigurableProduct\Model\Product\Type\Collection\SalableProcessor;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Catalog\Model\Product\Gallery\ReadHandler as GalleryReadHandler;

/**
* Configurable product type implementation
Expand Down Expand Up @@ -266,7 +267,6 @@ public function __construct(
$productRepository,
$serializer
);

}

/**
Expand Down Expand Up @@ -682,7 +682,7 @@ private function saveConfigurableOptions(ProductInterface $product)
->setProductId($product->getData($metadata->getLinkField()))
->save();
}
/** @var $configurableAttributesCollection \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection */
/** @var $configurableAttributesCollection \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection */
$configurableAttributesCollection = $this->_attributeCollectionFactory->create();
$configurableAttributesCollection->setProductFilter($product);
$configurableAttributesCollection->addFieldToFilter(
Expand Down Expand Up @@ -1276,6 +1276,8 @@ public function getSalableUsedProducts(\Magento\Catalog\Model\Product $product,
* Load collection on sub-products for specified configurable product
*
* Load collection of sub-products, apply result to specified configurable product and store result to cache
* Please note $salableOnly parameter is used for backwards compatibility because of deprecated method
* getSalableUsedProducts
* Number of loaded sub-products depends on $salableOnly parameter
* $salableOnly = true - result array contains only salable sub-products
* $salableOnly = false - result array contains all sub-products
Expand All @@ -1292,7 +1294,7 @@ private function loadUsedProducts(\Magento\Catalog\Model\Product $product, $cach
if (!$product->hasData($dataFieldName)) {
$usedProducts = $this->readUsedProductsCacheData($cacheKey);
if ($usedProducts === null) {
$collection = $this->getConfiguredUsedProductCollection($product);
$collection = $this->getConfiguredUsedProductCollection($product, false);
if ($salableOnly) {
$collection = $this->salableProcessor->process($collection);
}
Expand Down Expand Up @@ -1386,13 +1388,18 @@ private function getUsedProductsCacheKey($keyParts)
* Retrieve related products collection with additional configuration
*
* @param \Magento\Catalog\Model\Product $product
* @param bool $skipStockFilter
* @return \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection
*/
private function getConfiguredUsedProductCollection(\Magento\Catalog\Model\Product $product)
{
private function getConfiguredUsedProductCollection(
\Magento\Catalog\Model\Product $product,
$skipStockFilter = true
) {
$collection = $this->getUsedProductCollection($product);
if ($skipStockFilter) {
$collection->setFlag('has_stock_status_filter', true);
}
$collection
->setFlag('has_stock_status_filter', true)
->addAttributeToSelect($this->getCatalogConfig()->getProductAttributes())
->addFilterByRequiredOptions()
->setStoreId($product->getStoreId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@
use Magento\Catalog\Api\Data\ProductExtensionInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Config;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
use Magento\Framework\EntityManager\EntityMetadata;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Customer\Model\Session;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\CollectionFactory;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection;
use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface;
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
use Magento\ConfigurableProduct\Model\Product\Type\Collection\SalableProcessor;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable\AttributeFactory;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\CollectionFactory;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection as ProductCollection;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\ConfigurableFactory;
use Magento\Customer\Model\Session;
use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection as ProductCollection;
use Magento\ConfigurableProduct\Model\Product\Type\Collection\SalableProcessor;
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
use Magento\Framework\EntityManager\EntityMetadata;
use Magento\Framework\EntityManager\MetadataPool;

/**
* @SuppressWarnings(PHPMD.LongVariable)
Expand Down