Skip to content

Commit 3e37588

Browse files
Merge pull request #4616 from magento-engcom/MSI-2471
[EngCom] Fix Elasticsearch support for MSI
2 parents bdd4b68 + fa628ed commit 3e37588

File tree

4 files changed

+216
-81
lines changed

4 files changed

+216
-81
lines changed

app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/DataProvider.php

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,9 @@
77

88
use Magento\Catalog\Api\Data\ProductInterface;
99
use Magento\Catalog\Model\Product\Attribute\Source\Status;
10-
use Magento\CatalogInventory\Api\Data\StockStatusInterface;
11-
use Magento\CatalogInventory\Api\StockConfigurationInterface;
12-
use Magento\CatalogInventory\Api\StockStatusCriteriaInterface;
13-
use Magento\CatalogInventory\Api\StockStatusRepositoryInterface;
1410
use Magento\Framework\App\ResourceConnection;
1511
use Magento\Framework\DB\Select;
1612
use Magento\Store\Model\Store;
17-
use Magento\Framework\App\ObjectManager;
1813

1914
/**
2015
* Catalog search full test search data provider.
@@ -129,16 +124,6 @@ class DataProvider
129124
*/
130125
private $antiGapMultiplier;
131126

132-
/**
133-
* @var StockConfigurationInterface
134-
*/
135-
private $stockConfiguration;
136-
137-
/**
138-
* @var StockStatusRepositoryInterface
139-
*/
140-
private $stockStatusRepository;
141-
142127
/**
143128
* @param ResourceConnection $resource
144129
* @param \Magento\Catalog\Model\Product\Type $catalogProductType
@@ -563,8 +548,6 @@ public function prepareProductIndex($indexData, $productData, $storeId)
563548
{
564549
$index = [];
565550

566-
$indexData = $this->filterOutOfStockProducts($indexData, $storeId);
567-
568551
foreach ($this->getSearchableAttributes('static') as $attribute) {
569552
$attributeCode = $attribute->getAttributeCode();
570553

@@ -689,68 +672,4 @@ private function filterAttributeValue($value)
689672
{
690673
return preg_replace('/\s+/iu', ' ', trim(strip_tags($value)));
691674
}
692-
693-
/**
694-
* Filter out of stock products for products.
695-
*
696-
* @param array $indexData
697-
* @param int $storeId
698-
* @return array
699-
*/
700-
private function filterOutOfStockProducts($indexData, $storeId): array
701-
{
702-
if (!$this->getStockConfiguration()->isShowOutOfStock($storeId)) {
703-
$productIds = array_keys($indexData);
704-
$stockStatusCriteria = $this->createStockStatusCriteria();
705-
$stockStatusCriteria->setProductsFilter($productIds);
706-
$stockStatusCollection = $this->getStockStatusRepository()->getList($stockStatusCriteria);
707-
$stockStatuses = $stockStatusCollection->getItems();
708-
$stockStatuses = array_filter(
709-
$stockStatuses,
710-
function (StockStatusInterface $stockStatus) {
711-
return StockStatusInterface::STATUS_IN_STOCK == $stockStatus->getStockStatus();
712-
}
713-
);
714-
$indexData = array_intersect_key($indexData, $stockStatuses);
715-
}
716-
return $indexData;
717-
}
718-
719-
/**
720-
* Get stock configuration.
721-
*
722-
* @return StockConfigurationInterface
723-
*/
724-
private function getStockConfiguration()
725-
{
726-
if (null === $this->stockConfiguration) {
727-
$this->stockConfiguration = ObjectManager::getInstance()->get(StockConfigurationInterface::class);
728-
}
729-
return $this->stockConfiguration;
730-
}
731-
732-
/**
733-
* Create stock status criteria.
734-
*
735-
* Substitution of autogenerated factory in backward compatibility reasons.
736-
*
737-
* @return StockStatusCriteriaInterface
738-
*/
739-
private function createStockStatusCriteria()
740-
{
741-
return ObjectManager::getInstance()->create(StockStatusCriteriaInterface::class);
742-
}
743-
744-
/**
745-
* Get stock status repository.
746-
*
747-
* @return StockStatusRepositoryInterface
748-
*/
749-
private function getStockStatusRepository()
750-
{
751-
if (null === $this->stockStatusRepository) {
752-
$this->stockStatusRepository = ObjectManager::getInstance()->get(StockStatusRepositoryInterface::class);
753-
}
754-
return $this->stockStatusRepository;
755-
}
756675
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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\CatalogSearch\Model\Indexer\Plugin;
9+
10+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
11+
use Magento\CatalogInventory\Api\StockStatusRepositoryInterface;
12+
use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory;
13+
use Magento\CatalogInventory\Api\Data\StockStatusInterface;
14+
use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider;
15+
16+
/**
17+
* Plugin for filtering child products that are out of stock for preventing their saving to catalog search index.
18+
*
19+
* This plugin reverts changes introduced in commit 9ab466d8569ea556cb01393989579c3aac53d9a3 which break extensions
20+
* relying on stocks. Plugin location is changed for consistency purposes.
21+
*/
22+
class StockedProductsFilterPlugin
23+
{
24+
/**
25+
* @var StockConfigurationInterface
26+
*/
27+
private $stockConfiguration;
28+
29+
/**
30+
* @var StockStatusRepositoryInterface
31+
*/
32+
private $stockStatusRepository;
33+
34+
/**
35+
* @var StockStatusCriteriaInterfaceFactory
36+
*/
37+
private $stockStatusCriteriaFactory;
38+
39+
/**
40+
* @param StockConfigurationInterface $stockConfiguration
41+
* @param StockStatusRepositoryInterface $stockStatusRepository
42+
* @param StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory
43+
*/
44+
public function __construct(
45+
StockConfigurationInterface $stockConfiguration,
46+
StockStatusRepositoryInterface $stockStatusRepository,
47+
StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory
48+
) {
49+
$this->stockConfiguration = $stockConfiguration;
50+
$this->stockStatusRepository = $stockStatusRepository;
51+
$this->stockStatusCriteriaFactory = $stockStatusCriteriaFactory;
52+
}
53+
54+
/**
55+
* Filter out of stock options for configurable product.
56+
*
57+
* @param DataProvider $dataProvider
58+
* @param array $indexData
59+
* @param array $productData
60+
* @param int $storeId
61+
* @return array
62+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
63+
*/
64+
public function beforePrepareProductIndex(
65+
DataProvider $dataProvider,
66+
array $indexData,
67+
array $productData,
68+
int $storeId
69+
): array {
70+
if (!$this->stockConfiguration->isShowOutOfStock($storeId)) {
71+
$productIds = array_keys($indexData);
72+
$stockStatusCriteria = $this->stockStatusCriteriaFactory->create();
73+
$stockStatusCriteria->setProductsFilter($productIds);
74+
$stockStatusCollection = $this->stockStatusRepository->getList($stockStatusCriteria);
75+
$stockStatuses = $stockStatusCollection->getItems();
76+
$stockStatuses = array_filter(
77+
$stockStatuses,
78+
function (StockStatusInterface $stockStatus) {
79+
return StockStatusInterface::STATUS_IN_STOCK == $stockStatus->getStockStatus();
80+
}
81+
);
82+
$indexData = array_intersect_key($indexData, $stockStatuses);
83+
}
84+
85+
return [
86+
$indexData,
87+
$productData,
88+
$storeId,
89+
];
90+
}
91+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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\CatalogSearch\Test\Unit\Model\Indexer\Plugin;
9+
10+
use Magento\CatalogSearch\Model\Indexer\Plugin\StockedProductsFilterPlugin;
11+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
12+
use Magento\CatalogInventory\Api\StockStatusRepositoryInterface;
13+
use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory;
14+
use Magento\CatalogInventory\Api\StockStatusCriteriaInterface;
15+
use Magento\CatalogInventory\Api\Data\StockStatusCollectionInterface;
16+
use Magento\CatalogInventory\Api\Data\StockStatusInterface;
17+
use Magento\CatalogInventory\Model\Stock;
18+
use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider;
19+
20+
/**
21+
* Test for Magento\CatalogSearch\Model\Indexer\Plugin\StockedProductsFilterPlugin class.
22+
*
23+
* This plugin reverts changes introduced in commit 9ab466d8569ea556cb01393989579c3aac53d9a3 which break extensions
24+
* relying on stocks. Plugin location is changed for consistency purposes.
25+
*/
26+
class StockedProductsFilterPluginTest extends \PHPUnit\Framework\TestCase
27+
{
28+
/**
29+
* @var StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject
30+
*/
31+
private $stockConfigurationMock;
32+
33+
/**
34+
* @var StockStatusRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
35+
*/
36+
private $stockStatusRepositoryMock;
37+
38+
/**
39+
* @var StockStatusCriteriaInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
40+
*/
41+
private $stockStatusCriteriaFactoryMock;
42+
43+
/**
44+
* @var StockedProductsFilterPlugin
45+
*/
46+
private $plugin;
47+
48+
/**
49+
* {@inheritdoc}
50+
*/
51+
protected function setUp()
52+
{
53+
$this->stockConfigurationMock = $this->getMockBuilder(StockConfigurationInterface::class)
54+
->disableOriginalConstructor()
55+
->getMock();
56+
$this->stockStatusRepositoryMock = $this->getMockBuilder(StockStatusRepositoryInterface::class)
57+
->disableOriginalConstructor()
58+
->getMock();
59+
$this->stockStatusCriteriaFactoryMock = $this->getMockBuilder(StockStatusCriteriaInterfaceFactory::class)
60+
->disableOriginalConstructor()
61+
->getMock();
62+
63+
$this->plugin = new StockedProductsFilterPlugin(
64+
$this->stockConfigurationMock,
65+
$this->stockStatusRepositoryMock,
66+
$this->stockStatusCriteriaFactoryMock
67+
);
68+
}
69+
70+
/**
71+
* @return void
72+
*/
73+
public function testBeforePrepareProductIndex(): void
74+
{
75+
/** @var DataProvider|\PHPUnit_Framework_MockObject_MockObject $dataProviderMock */
76+
$dataProviderMock = $this->getMockBuilder(DataProvider::class)->disableOriginalConstructor()->getMock();
77+
$indexData = [
78+
1 => [],
79+
2 => [],
80+
];
81+
$productData = [];
82+
$storeId = 1;
83+
84+
$this->stockConfigurationMock
85+
->expects($this->once())
86+
->method('isShowOutOfStock')
87+
->willReturn(false);
88+
89+
$stockStatusCriteriaMock = $this->getMockBuilder(StockStatusCriteriaInterface::class)->getMock();
90+
$stockStatusCriteriaMock
91+
->expects($this->once())
92+
->method('setProductsFilter')
93+
->willReturn(true);
94+
$this->stockStatusCriteriaFactoryMock
95+
->expects($this->once())
96+
->method('create')
97+
->willReturn($stockStatusCriteriaMock);
98+
99+
$stockStatusMock = $this->getMockBuilder(StockStatusInterface::class)->getMock();
100+
$stockStatusMock->expects($this->atLeastOnce())
101+
->method('getStockStatus')
102+
->willReturnOnConsecutiveCalls(Stock::STOCK_IN_STOCK, Stock::STOCK_OUT_OF_STOCK);
103+
$stockStatusCollectionMock = $this->getMockBuilder(StockStatusCollectionInterface::class)->getMock();
104+
$stockStatusCollectionMock
105+
->expects($this->once())
106+
->method('getItems')
107+
->willReturn([1 => $stockStatusMock, 2 => $stockStatusMock]);
108+
$this->stockStatusRepositoryMock
109+
->expects($this->once())
110+
->method('getList')
111+
->willReturn($stockStatusCollectionMock);
112+
113+
list ($indexData, $productData, $storeId) = $this->plugin->beforePrepareProductIndex(
114+
$dataProviderMock,
115+
$indexData,
116+
$productData,
117+
$storeId
118+
);
119+
120+
$this->assertEquals([1], array_keys($indexData));
121+
}
122+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,4 +373,7 @@
373373
</argument>
374374
</arguments>
375375
</type>
376+
<type name="Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider">
377+
<plugin name="stockedProductsFilterPlugin" type="Magento\CatalogSearch\Model\Indexer\Plugin\StockedProductsFilterPlugin"/>
378+
</type>
376379
</config>

0 commit comments

Comments
 (0)