Skip to content

Commit f54feef

Browse files
committed
Merge remote-tracking branch 'mpi/MC-33626' into MPI-2020-09-14
2 parents 1e8a50d + 4254a9a commit f54feef

File tree

8 files changed

+212
-66
lines changed

8 files changed

+212
-66
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogInventory\Model\ResourceModel;
9+
10+
use Magento\CatalogInventory\Api\Data\StockStatusInterface;
11+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
12+
use Magento\CatalogInventory\Model\Stock;
13+
use Magento\Framework\App\ResourceConnection;
14+
use Magento\Framework\DB\Select;
15+
16+
/**
17+
* Generic in-stock status filter
18+
*/
19+
class StockStatusFilter implements StockStatusFilterInterface
20+
{
21+
private const TABLE_NAME = 'cataloginventory_stock_status';
22+
/**
23+
* @var ResourceConnection
24+
*/
25+
private $resource;
26+
27+
/**
28+
* @var StockConfigurationInterface
29+
*/
30+
private $stockConfiguration;
31+
32+
/**
33+
* @param ResourceConnection $resource
34+
* @param StockConfigurationInterface $stockConfiguration
35+
*/
36+
public function __construct(
37+
ResourceConnection $resource,
38+
StockConfigurationInterface $stockConfiguration
39+
) {
40+
$this->resource = $resource;
41+
$this->stockConfiguration = $stockConfiguration;
42+
}
43+
44+
/**
45+
* @inheritDoc
46+
*/
47+
public function execute(
48+
Select $select,
49+
string $productTableAlias,
50+
string $stockStatusTableAlias = self::TABLE_ALIAS,
51+
?int $websiteId = null
52+
): Select {
53+
$stockStatusTable = $this->resource->getTableName(self::TABLE_NAME);
54+
$joinCondition = [
55+
"{$stockStatusTableAlias}.product_id = {$productTableAlias}.entity_id",
56+
$select->getConnection()->quoteInto(
57+
"{$stockStatusTableAlias}.website_id = ?",
58+
$this->stockConfiguration->getDefaultScopeId()
59+
),
60+
$select->getConnection()->quoteInto(
61+
"{$stockStatusTableAlias}.stock_id = ?",
62+
Stock::DEFAULT_STOCK_ID
63+
)
64+
];
65+
$select->join(
66+
[$stockStatusTableAlias => $stockStatusTable],
67+
implode(' AND ', $joinCondition),
68+
[]
69+
);
70+
$select->where("{$stockStatusTableAlias}.stock_status = ?", StockStatusInterface::STATUS_IN_STOCK);
71+
72+
return $select;
73+
}
74+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogInventory\Model\ResourceModel;
9+
10+
use Magento\Framework\DB\Select;
11+
12+
/**
13+
* In stock status filter interface.
14+
*/
15+
interface StockStatusFilterInterface
16+
{
17+
public const TABLE_ALIAS = 'stock_status';
18+
19+
/**
20+
* Add in-stock status constraint to the select.
21+
*
22+
* @param Select $select
23+
* @param string $productTableAliasAlias
24+
* @param string $stockStatusTableAlias
25+
* @param int|null $websiteId
26+
* @return Select
27+
*/
28+
public function execute(
29+
Select $select,
30+
string $productTableAliasAlias,
31+
string $stockStatusTableAlias = self::TABLE_ALIAS,
32+
?int $websiteId = null
33+
): Select;
34+
}

app/code/Magento/CatalogInventory/etc/di.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<preference for="Magento\CatalogInventory\Model\Spi\StockStateProviderInterface" type="Magento\CatalogInventory\Model\StockStateProvider" />
3333

3434
<preference for="Magento\CatalogInventory\Model\ResourceModel\QtyCounterInterface" type="Magento\CatalogInventory\Model\ResourceModel\Stock" />
35+
<preference for="Magento\CatalogInventory\Model\ResourceModel\StockStatusFilterInterface" type="Magento\CatalogInventory\Model\ResourceModel\StockStatusFilter" />
3536
<type name="Magento\Catalog\Model\Product\Attribute\Repository">
3637
<plugin name="filterCustomAttribute" type="Magento\CatalogInventory\Model\Plugin\FilterCustomAttribute" />
3738
</type>

app/code/Magento/Wishlist/Model/ResourceModel/Item/Collection.php

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use Magento\Catalog\Api\Data\ProductInterface;
99
use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer;
10-
use Magento\CatalogInventory\Model\Stock;
10+
use Magento\CatalogInventory\Model\ResourceModel\StockStatusFilterInterface;
1111
use Magento\Framework\App\ObjectManager;
1212
use Magento\Framework\EntityManager\MetadataPool;
1313
use Magento\Sales\Model\ConfigInterface;
@@ -162,6 +162,17 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab
162162
* @var CollectionBuilderInterface
163163
*/
164164
private $productCollectionBuilder;
165+
/**
166+
* @var StockStatusFilterInterface
167+
*/
168+
private $stockStatusFilter;
169+
170+
/**
171+
* Whether product table is joined in select
172+
*
173+
* @var bool
174+
*/
175+
private $isProductTableJoined = false;
165176

166177
/**
167178
* @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
@@ -181,10 +192,11 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab
181192
* @param \Magento\Catalog\Model\Entity\AttributeFactory $catalogAttrFactory
182193
* @param \Magento\Wishlist\Model\ResourceModel\Item $resource
183194
* @param \Magento\Framework\App\State $appState
184-
* @param \Magento\Framework\DB\Adapter\AdapterInterface $connection
195+
* @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection
185196
* @param TableMaintainer|null $tableMaintainer
186197
* @param ConfigInterface|null $salesConfig
187198
* @param CollectionBuilderInterface|null $productCollectionBuilder
199+
* @param StockStatusFilterInterface|null $stockStatusFilter
188200
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
189201
*/
190202
public function __construct(
@@ -208,7 +220,8 @@ public function __construct(
208220
\Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
209221
TableMaintainer $tableMaintainer = null,
210222
ConfigInterface $salesConfig = null,
211-
?CollectionBuilderInterface $productCollectionBuilder = null
223+
?CollectionBuilderInterface $productCollectionBuilder = null,
224+
?StockStatusFilterInterface $stockStatusFilter = null
212225
) {
213226
$this->stockConfiguration = $stockConfiguration;
214227
$this->_adminhtmlSales = $adminhtmlSales;
@@ -227,6 +240,8 @@ public function __construct(
227240
$this->salesConfig = $salesConfig ?: ObjectManager::getInstance()->get(ConfigInterface::class);
228241
$this->productCollectionBuilder = $productCollectionBuilder
229242
?: ObjectManager::getInstance()->get(CollectionBuilderInterface::class);
243+
$this->stockStatusFilter = $stockStatusFilter
244+
?: ObjectManager::getInstance()->get(StockStatusFilterInterface::class);
230245
}
231246

232247
/**
@@ -368,15 +383,8 @@ protected function _renderFiltersBefore()
368383
$connection = $this->getConnection();
369384

370385
if ($this->_productInStock && !$this->stockConfiguration->isShowOutOfStock()) {
371-
$inStockConditions = [
372-
"stockItem.product_id = {$mainTableName}.product_id",
373-
$connection->quoteInto('stockItem.stock_status = ?', Stock::STOCK_IN_STOCK),
374-
];
375-
$this->getSelect()->join(
376-
['stockItem' => $this->getTable('cataloginventory_stock_status')],
377-
join(' AND ', $inStockConditions),
378-
[]
379-
);
386+
$this->joinProductTable();
387+
$this->stockStatusFilter->execute($this->getSelect(), 'product_entity', 'stockItem');
380388
}
381389

382390
if ($this->_productVisible) {
@@ -587,12 +595,9 @@ protected function _joinProductNameTable()
587595

588596
$entityMetadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
589597
$linkField = $entityMetadata->getLinkField();
598+
$this->joinProductTable();
590599

591600
$this->getSelect()->join(
592-
['product_entity' => $this->getTable('catalog_product_entity')],
593-
'product_entity.entity_id = main_table.product_id',
594-
[]
595-
)->join(
596601
['product_name_table' => $attribute->getBackendTable()],
597602
'product_name_table.' . $linkField . ' = product_entity.' . $linkField .
598603
' AND product_name_table.store_id = ' .
@@ -677,4 +682,21 @@ protected function _afterLoadData()
677682

678683
return $this;
679684
}
685+
686+
/**
687+
* Join product table to select if not already joined
688+
*
689+
* @return void
690+
*/
691+
private function joinProductTable(): void
692+
{
693+
if (!$this->isProductTableJoined) {
694+
$this->getSelect()->join(
695+
['product_entity' => $this->getTable('catalog_product_entity')],
696+
'product_entity.entity_id = main_table.product_id',
697+
[]
698+
);
699+
$this->isProductTableJoined = true;
700+
}
701+
}
680702
}

app/code/Magento/Wishlist/Model/Wishlist.php

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
use Magento\Catalog\Api\ProductRepositoryInterface;
1313
use Magento\Catalog\Model\Product;
1414
use Magento\Catalog\Model\ProductFactory;
15-
use Magento\CatalogInventory\Api\Data\StockItemInterface;
15+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
1616
use Magento\CatalogInventory\Api\StockRegistryInterface;
17-
use Magento\CatalogInventory\Model\Configuration;
1817
use Magento\Framework\App\Config\ScopeConfigInterface;
1918
use Magento\Framework\App\ObjectManager;
2019
use Magento\Framework\DataObject;
@@ -27,7 +26,6 @@
2726
use Magento\Framework\Registry;
2827
use Magento\Framework\Serialize\Serializer\Json;
2928
use Magento\Framework\Stdlib\DateTime;
30-
use Magento\Store\Model\ScopeInterface;
3129
use Magento\Store\Model\Store;
3230
use Magento\Store\Model\StoreManagerInterface;
3331
use Magento\Wishlist\Helper\Data;
@@ -150,14 +148,9 @@ class Wishlist extends AbstractModel implements IdentityInterface
150148
private $serializer;
151149

152150
/**
153-
* @var ScopeConfigInterface
151+
* @var StockConfigurationInterface
154152
*/
155-
private $scopeConfig;
156-
157-
/**
158-
* @var StockRegistryInterface|null
159-
*/
160-
private $stockRegistry;
153+
private $stockConfiguration;
161154

162155
/**
163156
* Constructor
@@ -181,8 +174,9 @@ class Wishlist extends AbstractModel implements IdentityInterface
181174
* @param Json|null $serializer
182175
* @param StockRegistryInterface|null $stockRegistry
183176
* @param ScopeConfigInterface|null $scopeConfig
184-
*
177+
* @param StockConfigurationInterface|null $stockConfiguration
185178
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
179+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
186180
*/
187181
public function __construct(
188182
Context $context,
@@ -203,7 +197,8 @@ public function __construct(
203197
array $data = [],
204198
Json $serializer = null,
205199
StockRegistryInterface $stockRegistry = null,
206-
ScopeConfigInterface $scopeConfig = null
200+
ScopeConfigInterface $scopeConfig = null,
201+
?StockConfigurationInterface $stockConfiguration = null
207202
) {
208203
$this->_useCurrentWebsite = $useCurrentWebsite;
209204
$this->_catalogProduct = $catalogProduct;
@@ -218,8 +213,8 @@ public function __construct(
218213
$this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
219214
parent::__construct($context, $registry, $resource, $resourceCollection, $data);
220215
$this->productRepository = $productRepository;
221-
$this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class);
222-
$this->stockRegistry = $stockRegistry ?: ObjectManager::getInstance()->get(StockRegistryInterface::class);
216+
$this->stockConfiguration = $stockConfiguration
217+
?: ObjectManager::getInstance()->get(StockConfigurationInterface::class);
223218
}
224219

225220
/**
@@ -467,7 +462,7 @@ public function addNewItem($product, $buyRequest = null, $forciblySetQty = false
467462
throw new LocalizedException(__('Cannot specify product.'));
468463
}
469464

470-
if ($this->isInStock($productId)) {
465+
if (!$this->stockConfiguration->isShowOutOfStock($storeId) && !$product->getIsSalable()) {
471466
throw new LocalizedException(__('Cannot add product without stock to wishlist.'));
472467
}
473468

@@ -672,25 +667,6 @@ public function isSalable()
672667
return false;
673668
}
674669

675-
/**
676-
* Retrieve if product has stock or config is set for showing out of stock products
677-
*
678-
* @param int $productId
679-
*
680-
* @return bool
681-
*/
682-
private function isInStock($productId)
683-
{
684-
/** @var StockItemInterface $stockItem */
685-
$stockItem = $this->stockRegistry->getStockItem($productId);
686-
$showOutOfStock = $this->scopeConfig->isSetFlag(
687-
Configuration::XML_PATH_SHOW_OUT_OF_STOCK,
688-
ScopeInterface::SCOPE_STORE
689-
);
690-
$isInStock = $stockItem ? $stockItem->getIsInStock() : false;
691-
return !$isInStock && !$showOutOfStock;
692-
}
693-
694670
/**
695671
* Check customer is owner this wishlist
696672
*

0 commit comments

Comments
 (0)