Skip to content

Commit 4225cf4

Browse files
[Magento Community Engineering] Community Contributions - 2.4-develop
- merged latest code from mainline branch
2 parents 3a56f01 + 97191ce commit 4225cf4

File tree

8 files changed

+218
-25
lines changed

8 files changed

+218
-25
lines changed

app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,30 @@
66

77
namespace Magento\CatalogSearch\Model\ResourceModel\Advanced;
88

9+
use Magento\Catalog\Model\Category;
910
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory;
12+
use Magento\CatalogSearch\Model\ResourceModel\Advanced;
1013
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyChecker;
1114
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyCheckerInterface;
15+
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverFactory;
1216
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverInterface;
17+
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierFactory;
1318
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierInterface;
14-
use Magento\Framework\Search\EngineResolverInterface;
15-
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverInterface;
1619
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverFactory;
20+
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverInterface;
21+
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
1722
use Magento\Framework\Api\FilterBuilder;
18-
use Magento\Framework\DB\Select;
1923
use Magento\Framework\Api\Search\SearchCriteriaBuilder;
2024
use Magento\Framework\Api\Search\SearchResultFactory;
25+
use Magento\Framework\Api\Search\SearchResultInterface;
26+
use Magento\Framework\App\ObjectManager;
27+
use Magento\Framework\DB\Select;
2128
use Magento\Framework\EntityManager\MetadataPool;
2229
use Magento\Framework\Exception\LocalizedException;
30+
use Magento\Framework\Search\EngineResolverInterface;
2331
use Magento\Framework\Search\Request\EmptyRequestDataException;
2432
use Magento\Framework\Search\Request\NonExistingRequestNameException;
25-
use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory;
26-
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverFactory;
27-
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierFactory;
28-
use Magento\Framework\App\ObjectManager;
29-
use Magento\Framework\Api\Search\SearchResultInterface;
3033

3134
/**
3235
* Advanced search collection
@@ -106,6 +109,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection
106109
*/
107110
private $defaultFilterStrategyApplyChecker;
108111

112+
/**
113+
* @var Advanced
114+
*/
115+
private $advancedSearchResource;
116+
109117
/**
110118
* Collection constructor
111119
*
@@ -141,6 +149,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection
141149
* @param TotalRecordsResolverFactory|null $totalRecordsResolverFactory
142150
* @param EngineResolverInterface|null $engineResolver
143151
* @param DefaultFilterStrategyApplyCheckerInterface|null $defaultFilterStrategyApplyChecker
152+
* @param Advanced|null $advancedSearchResource
144153
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
145154
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
146155
*/
@@ -176,7 +185,8 @@ public function __construct(
176185
SearchResultApplierFactory $searchResultApplierFactory = null,
177186
TotalRecordsResolverFactory $totalRecordsResolverFactory = null,
178187
EngineResolverInterface $engineResolver = null,
179-
DefaultFilterStrategyApplyCheckerInterface $defaultFilterStrategyApplyChecker = null
188+
DefaultFilterStrategyApplyCheckerInterface $defaultFilterStrategyApplyChecker = null,
189+
Advanced $advancedSearchResource = null
180190
) {
181191
$this->searchRequestName = $searchRequestName;
182192
if ($searchResultFactory === null) {
@@ -193,6 +203,8 @@ public function __construct(
193203
->get(EngineResolverInterface::class);
194204
$this->defaultFilterStrategyApplyChecker = $defaultFilterStrategyApplyChecker ?: ObjectManager::getInstance()
195205
->get(DefaultFilterStrategyApplyChecker::class);
206+
$this->advancedSearchResource = $advancedSearchResource ?: ObjectManager::getInstance()
207+
->get(Advanced::class);
196208
parent::__construct(
197209
$entityFactory,
198210
$logger,
@@ -258,14 +270,14 @@ public function setOrder($attribute, $dir = Select::SQL_DESC)
258270
*/
259271
public function addCategoryFilter(\Magento\Catalog\Model\Category $category)
260272
{
273+
$this->setAttributeFilterData(Category::ENTITY, 'category_ids', $category->getId());
261274
/**
262275
* This changes need in backward compatible reasons for support dynamic improved algorithm
263276
* for price aggregation process.
264277
*/
265278
if ($this->defaultFilterStrategyApplyChecker->isApplicable()) {
266279
parent::addCategoryFilter($category);
267280
} else {
268-
$this->addFieldToFilter('category_ids', $category->getId());
269281
$this->_productLimitationPrice();
270282
}
271283

@@ -278,14 +290,13 @@ public function addCategoryFilter(\Magento\Catalog\Model\Category $category)
278290
*/
279291
public function setVisibility($visibility)
280292
{
293+
$this->setAttributeFilterData(Product::ENTITY, 'visibility', $visibility);
281294
/**
282295
* This changes need in backward compatible reasons for support dynamic improved algorithm
283296
* for price aggregation process.
284297
*/
285298
if ($this->defaultFilterStrategyApplyChecker->isApplicable()) {
286299
parent::setVisibility($visibility);
287-
} else {
288-
$this->addFieldToFilter('visibility', $visibility);
289300
}
290301

291302
return $this;
@@ -306,6 +317,25 @@ private function setSearchOrder($field, $direction)
306317
$this->searchOrders[$field] = $direction;
307318
}
308319

320+
/**
321+
* Prepare attribute data to filter.
322+
*
323+
* @param string $entityType
324+
* @param string $attributeCode
325+
* @param mixed $condition
326+
* @return $this
327+
*/
328+
private function setAttributeFilterData(string $entityType, string $attributeCode, $condition): self
329+
{
330+
/** @var AbstractAttribute $attribute */
331+
$attribute = $this->_eavConfig->getAttribute($entityType, $attributeCode);
332+
$table = $attribute->getBackend()->getTable();
333+
$condition = $this->advancedSearchResource->prepareCondition($attribute, $condition);
334+
$this->addFieldsToFilter([$table => [$attributeCode => $condition]]);
335+
336+
return $this;
337+
}
338+
309339
/**
310340
* @inheritdoc
311341
*/
@@ -377,7 +407,7 @@ public function _loadEntities($printQuery = false, $logQuery = false)
377407
$query = $this->getSelect();
378408
$rows = $this->_fetchAll($query);
379409
} catch (\Exception $e) {
380-
$this->printLogQuery(false, true, $query);
410+
$this->printLogQuery(false, true, $query ?? null);
381411
throw $e;
382412
}
383413

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
<queryReference clause="should" ref="sku_query"/>
6767
<queryReference clause="should" ref="price_query"/>
6868
<queryReference clause="should" ref="category_query"/>
69+
<queryReference clause="must" ref="visibility_query"/>
6970
</query>
7071
<query name="sku_query" xsi:type="filteredQuery">
7172
<filterReference clause="must" ref="sku_query_filter"/>
@@ -76,11 +77,15 @@
7677
<query name="category_query" xsi:type="filteredQuery">
7778
<filterReference clause="must" ref="category_filter"/>
7879
</query>
80+
<query name="visibility_query" xsi:type="filteredQuery">
81+
<filterReference clause="must" ref="visibility_filter"/>
82+
</query>
7983
</queries>
8084
<filters>
8185
<filter xsi:type="wildcardFilter" name="sku_query_filter" field="sku" value="$sku$"/>
8286
<filter xsi:type="rangeFilter" name="price_query_filter" field="price" from="$price.from$" to="$price.to$"/>
8387
<filter xsi:type="termFilter" name="category_filter" field="category_ids" value="$category_ids$"/>
88+
<filter xsi:type="termFilter" name="visibility_filter" field="visibility" value="$visibility$"/>
8489
</filters>
8590
<from>0</from>
8691
<size>10000</size>

app/code/Magento/Elasticsearch/Model/Advanced/ProductCollectionPrepareStrategy.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
*/
66
namespace Magento\Elasticsearch\Model\Advanced;
77

8-
use Magento\Catalog\Model\ResourceModel\Product\Collection;
98
use Magento\Catalog\Model\Config;
9+
use Magento\Catalog\Model\Product\Visibility;
10+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
1011
use Magento\CatalogSearch\Model\Advanced\ProductCollectionPrepareStrategyInterface;
12+
use Magento\Framework\App\ObjectManager;
1113

1214
/**
1315
* Strategy interface for preparing product collection.
@@ -19,13 +21,22 @@ class ProductCollectionPrepareStrategy implements ProductCollectionPrepareStrate
1921
*/
2022
private $catalogConfig;
2123

24+
/**
25+
* @var Visibility
26+
*/
27+
private $catalogProductVisibility;
28+
2229
/**
2330
* @param Config $catalogConfig
31+
* @param Visibility|null $catalogProductVisibility
2432
*/
2533
public function __construct(
26-
Config $catalogConfig
34+
Config $catalogConfig,
35+
Visibility $catalogProductVisibility = null
2736
) {
2837
$this->catalogConfig = $catalogConfig;
38+
$this->catalogProductVisibility = $catalogProductVisibility
39+
?? ObjectManager::getInstance()->get(Visibility::class);
2940
}
3041

3142
/**
@@ -36,6 +47,7 @@ public function prepare(Collection $collection)
3647
$collection
3748
->addAttributeToSelect($this->catalogConfig->getProductAttributes())
3849
->addMinimalPrice()
39-
->addTaxPercents();
50+
->addTaxPercents()
51+
->setVisibility($this->catalogProductVisibility->getVisibleInSearchIds());
4052
}
4153
}

app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ protected function configure()
7474
*/
7575
protected function execute(InputInterface $input, OutputInterface $output)
7676
{
77-
$returnValue = Cli::RETURN_FAILURE;
77+
$returnValue = Cli::RETURN_SUCCESS;
7878
foreach ($this->getIndexers($input) as $indexer) {
7979
try {
8080
$this->validateIndexerStatus($indexer);
@@ -97,14 +97,15 @@ protected function execute(InputInterface $input, OutputInterface $output)
9797
$output->writeln(
9898
__('has been rebuilt successfully in %time', ['time' => gmdate('H:i:s', $resultTime)])
9999
);
100-
$returnValue = Cli::RETURN_SUCCESS;
101100
} catch (LocalizedException $e) {
102101
$output->writeln(__('exception: %message', ['message' => $e->getMessage()]));
102+
$returnValue = Cli::RETURN_FAILURE;
103103
} catch (\Exception $e) {
104104
$output->writeln('process unknown error:');
105105
$output->writeln($e->getMessage());
106106

107107
$output->writeln($e->getTraceAsString(), OutputInterface::VERBOSITY_DEBUG);
108+
$returnValue = Cli::RETURN_FAILURE;
108109
}
109110
}
110111

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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\Elasticsearch\Model\CatalogSearch;
9+
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\CatalogSearch\Model\Advanced;
12+
use Magento\Catalog\Model\Product\Visibility;
13+
use Magento\Catalog\Api\Data\ProductInterface;
14+
use Magento\Framework\ObjectManagerInterface;
15+
use Magento\Framework\Registry;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* Check catalog Advanced Search process with Elasticsearch enabled.
21+
*/
22+
class AdvancedTest extends TestCase
23+
{
24+
/**
25+
* @var ObjectManagerInterface
26+
*/
27+
private $objectManager;
28+
29+
/**
30+
* @var Registry
31+
*/
32+
private $registry;
33+
34+
/**
35+
* @var Visibility
36+
*/
37+
private $productVisibility;
38+
39+
/**
40+
* @var ProductRepositoryInterface
41+
*/
42+
private $productRepository;
43+
44+
/**
45+
* @inheritDoc
46+
*/
47+
protected function setUp(): void
48+
{
49+
parent::setUp();
50+
51+
$this->objectManager = Bootstrap::getObjectManager();
52+
$this->registry = $this->objectManager->get(Registry::class);
53+
$this->productVisibility = $this->objectManager->get(Visibility::class);
54+
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
55+
}
56+
57+
/**
58+
* Check that Advanced Search does NOT return products that do NOT have search visibility.
59+
*
60+
* @magentoDbIsolation disabled
61+
* @magentoConfigFixture default/catalog/search/engine elasticsearch7
62+
* @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_child_products.php
63+
* @return void
64+
*/
65+
public function testAddFilters(): void
66+
{
67+
$this->assertResultsAfterRequest(1);
68+
69+
/** @var ProductInterface $configurableProductOption */
70+
$configurableProductOption = $this->productRepository->get('Simple option 1');
71+
$configurableProductOption->setVisibility(Visibility::VISIBILITY_IN_SEARCH);
72+
$this->productRepository->save($configurableProductOption);
73+
74+
$this->registry->unregister('advanced_search_conditions');
75+
$this->assertResultsAfterRequest(2);
76+
}
77+
78+
/**
79+
* Do Elasticsearch query and assert results.
80+
*
81+
* @param int $count
82+
* @return void
83+
*/
84+
private function assertResultsAfterRequest(int $count): void
85+
{
86+
/** @var Advanced $advancedSearch */
87+
$advancedSearch = $this->objectManager->create(Advanced::class);
88+
$advancedSearch->addFilters(['name' => 'Configurable']);
89+
90+
/** @var ProductInterface[] $itemsResult */
91+
$itemsResult = $advancedSearch->getProductCollection()
92+
->addAttributeToSelect(ProductInterface::VISIBILITY)
93+
->getItems();
94+
95+
$this->assertCount($count, $itemsResult);
96+
foreach ($itemsResult as $product) {
97+
$this->assertStringContainsString('Configurable', $product->getName());
98+
$this->assertContains((int)$product->getVisibility(), $this->productVisibility->getVisibleInSearchIds());
99+
}
100+
}
101+
}

dev/tests/integration/testsuite/Magento/Indexer/Console/Command/IndexerReindexCommandTest.php

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
namespace Magento\Indexer\Console\Command;
99

10+
use Magento\Framework\Console\Cli;
1011
use Magento\Framework\ObjectManagerInterface;
1112
use Magento\TestFramework\Helper\Bootstrap;
1213
use PHPUnit\Framework\MockObject\MockObject as Mock;
14+
use PHPUnit\Framework\TestCase;
1315
use Symfony\Component\Console\Input\InputInterface;
1416
use Symfony\Component\Console\Output\OutputInterface;
1517

@@ -19,7 +21,7 @@
1921
* @magentoDbIsolation disabled
2022
* @magentoAppIsolation enabled
2123
*/
22-
class IndexerReindexCommandTest extends \PHPUnit\Framework\TestCase
24+
class IndexerReindexCommandTest extends TestCase
2325
{
2426
/**
2527
* @var ObjectManagerInterface
@@ -56,14 +58,23 @@ protected function setUp(): void
5658

5759
/**
5860
* @magentoDataFixture Magento/Store/_files/second_store_group_with_second_website.php
61+
* @return void
5962
*/
60-
public function testReindexAll()
63+
public function testReindexAll(): void
6164
{
6265
$status = $this->command->run($this->inputMock, $this->outputMock);
63-
$this->assertEquals(
64-
\Magento\Framework\Console\Cli::RETURN_SUCCESS,
65-
$status,
66-
'Index wasn\'t success'
67-
);
66+
$this->assertEquals(Cli::RETURN_SUCCESS, $status, 'Index wasn\'t success');
67+
}
68+
69+
/**
70+
* Check that 'indexer:reindex' command return right code.
71+
*
72+
* @magentoDataFixture Magento/Indexer/_files/wrong_config_data.php
73+
* @return void
74+
*/
75+
public function testReindexAllWhenSomethingIsWrong(): void
76+
{
77+
$status = $this->command->run($this->inputMock, $this->outputMock);
78+
$this->assertEquals(Cli::RETURN_FAILURE, $status, 'Index didn\'t return failure code');
6879
}
6980
}

0 commit comments

Comments
 (0)