Skip to content

Commit 76a0d7c

Browse files
author
Prabhu Ram
committed
Merge remote-tracking branch 'mainline/2.3.3-develop' into MC-19115
2 parents 09ec671 + d525030 commit 76a0d7c

File tree

12 files changed

+341
-100
lines changed

12 files changed

+341
-100
lines changed

app/code/Magento/Catalog/Controller/Product/Compare/Add.php

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,72 @@
66
*/
77
namespace Magento\Catalog\Controller\Product\Compare;
88

9-
use Magento\Catalog\Model\Product\Attribute\Source\Status;
9+
use Magento\Catalog\Api\ProductRepositoryInterface;
10+
use Magento\Catalog\ViewModel\Product\Checker\AddToCompareAvailability;
1011
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
12+
use Magento\Framework\Data\Form\FormKey\Validator;
1113
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Framework\View\Result\PageFactory;
1215

1316
/**
1417
* Add item to compare list action.
18+
*
19+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1520
*/
1621
class Add extends \Magento\Catalog\Controller\Product\Compare implements HttpPostActionInterface
1722
{
23+
/**
24+
* @var AddToCompareAvailability
25+
*/
26+
private $compareAvailability;
27+
28+
/**
29+
* @param \Magento\Framework\App\Action\Context $context
30+
* @param \Magento\Catalog\Model\Product\Compare\ItemFactory $compareItemFactory
31+
* @param \Magento\Catalog\Model\ResourceModel\Product\Compare\Item\CollectionFactory $itemCollectionFactory
32+
* @param \Magento\Customer\Model\Session $customerSession
33+
* @param \Magento\Customer\Model\Visitor $customerVisitor
34+
* @param \Magento\Catalog\Model\Product\Compare\ListCompare $catalogProductCompareList
35+
* @param \Magento\Catalog\Model\Session $catalogSession
36+
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
37+
* @param Validator $formKeyValidator
38+
* @param PageFactory $resultPageFactory
39+
* @param ProductRepositoryInterface $productRepository
40+
* @param AddToCompareAvailability|null $compareAvailability
41+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
42+
*/
43+
public function __construct(
44+
\Magento\Framework\App\Action\Context $context,
45+
\Magento\Catalog\Model\Product\Compare\ItemFactory $compareItemFactory,
46+
\Magento\Catalog\Model\ResourceModel\Product\Compare\Item\CollectionFactory $itemCollectionFactory,
47+
\Magento\Customer\Model\Session $customerSession,
48+
\Magento\Customer\Model\Visitor $customerVisitor,
49+
\Magento\Catalog\Model\Product\Compare\ListCompare $catalogProductCompareList,
50+
\Magento\Catalog\Model\Session $catalogSession,
51+
\Magento\Store\Model\StoreManagerInterface $storeManager,
52+
Validator $formKeyValidator,
53+
PageFactory $resultPageFactory,
54+
ProductRepositoryInterface $productRepository,
55+
AddToCompareAvailability $compareAvailability = null
56+
) {
57+
parent::__construct(
58+
$context,
59+
$compareItemFactory,
60+
$itemCollectionFactory,
61+
$customerSession,
62+
$customerVisitor,
63+
$catalogProductCompareList,
64+
$catalogSession,
65+
$storeManager,
66+
$formKeyValidator,
67+
$resultPageFactory,
68+
$productRepository
69+
);
70+
71+
$this->compareAvailability = $compareAvailability
72+
?: $this->_objectManager->get(AddToCompareAvailability::class);
73+
}
74+
1875
/**
1976
* Add item to compare list.
2077
*
@@ -37,7 +94,7 @@ public function execute()
3794
$product = null;
3895
}
3996

40-
if ($product && (int)$product->getStatus() !== Status::STATUS_DISABLED) {
97+
if ($product && $this->compareAvailability->isAvailableForCompare($product)) {
4198
$this->_catalogProductCompareList->addProduct($product);
4299
$productName = $this->_objectManager->get(
43100
\Magento\Framework\Escaper::class

app/code/Magento/Catalog/Controller/Product/Compare/Remove.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
namespace Magento\Catalog\Controller\Product\Compare;
88

9+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
910
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
1011
use Magento\Framework\Exception\NoSuchEntityException;
1112

@@ -17,12 +18,13 @@ class Remove extends \Magento\Catalog\Controller\Product\Compare implements Http
1718
/**
1819
* Remove item from compare list.
1920
*
21+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
2022
* @return \Magento\Framework\Controller\ResultInterface
2123
*/
2224
public function execute()
2325
{
2426
$productId = (int)$this->getRequest()->getParam('product');
25-
if ($productId) {
27+
if ($this->_formKeyValidator->validate($this->getRequest()) && $productId) {
2628
$storeId = $this->_storeManager->getStore()->getId();
2729
try {
2830
/** @var \Magento\Catalog\Model\Product $product */
@@ -31,7 +33,7 @@ public function execute()
3133
$product = null;
3234
}
3335

34-
if ($product && $product->isSalable()) {
36+
if ($product && (int)$product->getStatus() !== Status::STATUS_DISABLED) {
3537
/** @var $item \Magento\Catalog\Model\Product\Compare\Item */
3638
$item = $this->_compareItemFactory->create();
3739
if ($this->_customerSession->isLoggedIn()) {

app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,45 +18,43 @@
1818
<testCaseId value="MAGETWO-98644"/>
1919
<useCaseId value="MAGETWO-98522"/>
2020
<group value="Catalog"/>
21-
<skip>
22-
<issueId value="MC-15930"/>
23-
</skip>
2421
</annotations>
2522
<before>
2623
<actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/>
27-
<magentoCLI command="config:set cataloginventory/options/show_out_of_stock 0" stepKey="displayOutOfStockNo"/>
24+
<magentoCLI command="config:set {{CatalogInventoryOptionsShowOutOfStockDisable.path}} {{CatalogInventoryOptionsShowOutOfStockDisable.value}}" stepKey="setConfigShowOutOfStockFalse"/>
2825
<magentoCLI command="cache:flush" stepKey="flushCache"/>
2926
<createData entity="SimpleSubCategory" stepKey="category"/>
3027
<createData entity="SimpleProduct4" stepKey="product">
3128
<requiredEntity createDataKey="category"/>
3229
</createData>
3330
</before>
3431
<after>
35-
<magentoCLI command="config:set cataloginventory/options/show_out_of_stock 0" stepKey="displayOutOfStockNo2"/>
32+
<magentoCLI command="config:set {{CatalogInventoryOptionsShowOutOfStockDisable.path}} {{CatalogInventoryOptionsShowOutOfStockDisable.value}}" stepKey="setConfigShowOutOfStockFalse"/>
3633
<magentoCLI command="cache:flush" stepKey="flushCache"/>
3734
<deleteData createDataKey="product" stepKey="deleteProduct"/>
3835
<deleteData createDataKey="category" stepKey="deleteCategory"/>
3936
<actionGroup ref="logout" stepKey="logout"/>
4037
</after>
4138
<!--Open product page-->
4239
<comment userInput="Open product page" stepKey="openProdPage"/>
43-
<amOnPage url="{{StorefrontProductPage.url($$product.name$$)}}" stepKey="goToSimpleProductPage"/>
40+
<amOnPage url="{{StorefrontProductPage.url($$product.custom_attributes[url_key]$$)}}" stepKey="goToSimpleProductPage"/>
4441
<waitForPageLoad stepKey="waitForSimpleProductPage"/>
4542
<!--'Add to compare' link is not available-->
4643
<comment userInput="'Add to compare' link is not available" stepKey="addToCompareLinkAvailability"/>
4744
<dontSeeElement selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="dontSeeAddToCompareLink"/>
4845
<!--Turn on 'out on stock' config-->
4946
<comment userInput="Turn on 'out of stock' config" stepKey="onOutOfStockConfig"/>
50-
<magentoCLI command="config:set cataloginventory/options/show_out_of_stock 1" stepKey="displayOutOfStockYes"/>
47+
<magentoCLI command="config:set {{CatalogInventoryOptionsShowOutOfStockEnable.path}} {{CatalogInventoryOptionsShowOutOfStockEnable.value}}" stepKey="setConfigShowOutOfStockTrue"/>
5148
<!--Clear cache and reindex-->
5249
<comment userInput="Clear cache and reindex" stepKey="cleanCache"/>
5350
<magentoCLI command="indexer:reindex" stepKey="reindex"/>
5451
<magentoCLI command="cache:flush" stepKey="flushCache"/>
5552
<!--Open product page-->
5653
<comment userInput="Open product page" stepKey="openProductPage"/>
57-
<amOnPage url="{{StorefrontProductPage.url($$product.name$$)}}" stepKey="goToSimpleProductPage2"/>
54+
<amOnPage url="{{StorefrontProductPage.url($$product.custom_attributes[url_key]$$)}}" stepKey="goToSimpleProductPage2"/>
5855
<waitForPageLoad stepKey="waitForSimpleProductPage2"/>
5956
<!--Click on 'Add to Compare' link-->
57+
<waitForElementVisible selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="seeAddToCompareLink"/>
6058
<comment userInput="Click on 'Add to Compare' link" stepKey="clickOnAddToCompareLink"/>
6159
<click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickOnAddToCompare"/>
6260
<waitForPageLoad stepKey="waitForProdAddToCmpList"/>

app/code/Magento/Catalog/ViewModel/Product/Checker/AddToCompareAvailability.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Framework\View\Element\Block\ArgumentInterface;
1111
use Magento\Catalog\Api\Data\ProductInterface;
1212
use Magento\CatalogInventory\Api\StockConfigurationInterface;
13+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
1314

1415
/**
1516
* Check is available add to compare.
@@ -37,7 +38,11 @@ public function __construct(StockConfigurationInterface $stockConfiguration)
3738
*/
3839
public function isAvailableForCompare(ProductInterface $product): bool
3940
{
40-
return $this->isInStock($product) || $this->stockConfiguration->isShowOutOfStock();
41+
if ((int)$product->getStatus() !== Status::STATUS_DISABLED) {
42+
return $this->isInStock($product) || $this->stockConfiguration->isShowOutOfStock();
43+
}
44+
45+
return false;
4146
}
4247

4348
/**
@@ -53,6 +58,6 @@ private function isInStock(ProductInterface $product): bool
5358
return $product->isSalable();
5459
}
5560

56-
return isset($quantityAndStockStatus['is_in_stock']) && $quantityAndStockStatus['is_in_stock'];
61+
return $quantityAndStockStatus['is_in_stock'] ?? false;
5762
}
5863
}

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+
}

0 commit comments

Comments
 (0)