Skip to content

Commit ff0c129

Browse files
committed
ACP2E-685: Product set to 'Not Visible Individually' still appear in Catalog Advanced Search Results
1 parent 5c3867e commit ff0c129

File tree

8 files changed

+231
-67
lines changed

8 files changed

+231
-67
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ public function __construct(
241241
public function addFieldsToFilter($fields)
242242
{
243243
if ($fields) {
244-
$this->filters = array_merge($this->filters, $fields);
244+
$this->filters = array_replace_recursive($this->filters, $fields);
245245
}
246246
return $this;
247247
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
use Magento\Catalog\Api\Data\ProductAttributeInterface;
9+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Eav\Model\Config;
12+
use Magento\Eav\Setup\EavSetup;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\TestFramework\Helper\Bootstrap;
15+
use Magento\TestFramework\Helper\CacheCleaner;
16+
17+
$objectManager = Bootstrap::getObjectManager();
18+
19+
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);
20+
try {
21+
$attribute = $attributeRepository->get('test_configurable');
22+
} catch (NoSuchEntityException $e) {
23+
$installer = $objectManager->get(EavSetup::class);
24+
25+
$attributeModel = $objectManager->create(ProductAttributeInterface::class);
26+
$attributeModel->setData(
27+
[
28+
'attribute_code' => 'test_configurable',
29+
'entity_type_id' => $installer->getEntityTypeId(Product::ENTITY),
30+
'is_global' => 1,
31+
'is_user_defined' => 1,
32+
'frontend_input' => 'select',
33+
'is_unique' => 0,
34+
'is_required' => 0,
35+
'is_searchable' => 1,
36+
'is_visible_in_advanced_search' => 1,
37+
'is_comparable' => 1,
38+
'is_filterable' => 1,
39+
'is_filterable_in_search' => 1,
40+
'is_used_for_promo_rules' => 0,
41+
'is_html_allowed_on_front' => 1,
42+
'is_visible_on_front' => 1,
43+
'used_in_product_listing' => 1,
44+
'used_for_sort_by' => 1,
45+
'frontend_label' => ['Test Configurable'],
46+
'backend_type' => 'int',
47+
'option' => [
48+
'value' => ['option_0' => ['Option 1'], 'option_1' => ['Option 2']],
49+
'order' => ['option_0' => 1, 'option_1' => 2],
50+
],
51+
'default' => ['option_0']
52+
]
53+
);
54+
$attribute = $attributeRepository->save($attributeModel);
55+
56+
$attributeSetId = $installer->getAttributeSetId(Product::ENTITY, 'Default');
57+
$groupId = $installer->getDefaultAttributeGroupId(Product::ENTITY, $attributeSetId);
58+
$installer->addAttributeToGroup(Product::ENTITY, $attributeSetId, $groupId, $attribute->getId());
59+
60+
CacheCleaner::cleanAll();
61+
$eavConfig = $objectManager->get(Config::class);
62+
$eavConfig->clear();
63+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
9+
use Magento\Eav\Model\Config;
10+
use Magento\Framework\Exception\NoSuchEntityException;
11+
use Magento\Framework\Registry;
12+
use Magento\TestFramework\Helper\Bootstrap;
13+
14+
$objectManager = Bootstrap::getObjectManager();
15+
16+
$registry = $objectManager->get(Registry::class);
17+
$registry->unregister('isSecureArea');
18+
$registry->register('isSecureArea', true);
19+
20+
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);
21+
try {
22+
$attribute = $attributeRepository->get('test_configurable');
23+
$attributeRepository->delete($attribute);
24+
} catch (NoSuchEntityException $e) {
25+
//Attribute already removed
26+
}
27+
$eavConfig = $objectManager->get(Config::class);
28+
$eavConfig->clear();
29+
30+
$registry->unregister('isSecureArea');
31+
$registry->register('isSecureArea', false);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
9+
use Magento\Catalog\Api\ProductRepositoryInterface;
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus;
12+
use Magento\Catalog\Model\Product\Type as ProductType;
13+
use Magento\Catalog\Model\Product\Visibility as ProductVisibility;
14+
use Magento\Indexer\Model\Indexer\Collection as IndexerCollection;
15+
use Magento\Store\Api\WebsiteRepositoryInterface;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
18+
19+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/layered_navigation_attribute.php');
20+
21+
$objectManager = Bootstrap::getObjectManager();
22+
23+
$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class);
24+
$baseWebsite = $websiteRepository->get('base');
25+
26+
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);
27+
$attribute = $attributeRepository->get('test_configurable');
28+
29+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
30+
$product = $objectManager->create(Product::class);
31+
$product->setTypeId(ProductType::TYPE_SIMPLE)
32+
->setAttributeSetId($product->getDefaultAttributeSetId())
33+
->setName('Not visible simple')
34+
->setSku('not_visible_simple')
35+
->setTaxClassId('none')
36+
->setDescription('description')
37+
->setShortDescription('short description')
38+
->setPrice(10)
39+
->setWeight(1)
40+
->setMetaTitle('meta title')
41+
->setMetaKeyword('meta keyword')
42+
->setMetaDescription('meta description')
43+
->setVisibility(ProductVisibility::VISIBILITY_NOT_VISIBLE)
44+
->setStatus(ProductStatus::STATUS_ENABLED)
45+
->setWebsiteIds([$baseWebsite->getId()])
46+
->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1])
47+
->setData($attribute->getAttributeCode(), $attribute->getSource()->getOptionId('Option 1'));
48+
$productRepository->save($product);
49+
50+
$indexerCollection = $objectManager->get(IndexerCollection::class);
51+
foreach ($indexerCollection->getItems() as $indexer) {
52+
$indexer->reindexAll();
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
use Magento\Catalog\Api\ProductRepositoryInterface;
9+
use Magento\Framework\Exception\NoSuchEntityException;
10+
use Magento\TestFramework\Helper\Bootstrap;
11+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
12+
13+
$objectManager = Bootstrap::getObjectManager();
14+
15+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
16+
try {
17+
$product = $productRepository->get('not_visible_simple', false, null, true);
18+
$productRepository->delete($product);
19+
} catch (NoSuchEntityException $e) {
20+
//Product already removed
21+
}
22+
23+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/layered_navigation_attribute_rollback.php');

dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_layered_navigation_attribute.php

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,77 +6,27 @@
66
declare(strict_types=1);
77

88
use Magento\Catalog\Api\Data\CategoryInterfaceFactory;
9-
use Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory;
109
use Magento\Catalog\Api\Data\ProductInterfaceFactory;
11-
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
1210
use Magento\Catalog\Api\ProductRepositoryInterface;
1311
use Magento\Catalog\Model\Product;
1412
use Magento\Catalog\Model\Product\Attribute\Source\Status;
1513
use Magento\Catalog\Model\Product\Type;
1614
use Magento\Catalog\Model\Product\Visibility;
17-
use Magento\Eav\Model\Config;
18-
use Magento\Eav\Setup\EavSetup;
1915
use Magento\Indexer\Model\Indexer;
2016
use Magento\Indexer\Model\Indexer\Collection;
2117
use Magento\Msrp\Model\Product\Attribute\Source\Type as SourceType;
2218
use Magento\Store\Api\WebsiteRepositoryInterface;
2319
use Magento\TestFramework\Helper\Bootstrap;
24-
use Magento\TestFramework\Helper\CacheCleaner;
20+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
2521

26-
$objectManager = Bootstrap::getObjectManager();
27-
28-
/** @var Config $eavConfig */
29-
$eavConfig = $objectManager->get(Config::class);
30-
31-
/** @var ProductAttributeRepositoryInterface $attributeRepository */
32-
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);
33-
/** @var ProductAttributeInterfaceFactory $attributeFactory */
34-
$attributeFactory = $objectManager->get(ProductAttributeInterfaceFactory::class);
22+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/layered_navigation_attribute.php');
3523

36-
/** @var $installer EavSetup */
37-
$installer = $objectManager->get(EavSetup::class);
38-
$attributeSetId = $installer->getAttributeSetId(Product::ENTITY, 'Default');
39-
$groupId = $installer->getDefaultAttributeGroupId(Product::ENTITY, $attributeSetId);
24+
$objectManager = Bootstrap::getObjectManager();
4025

4126
/** @var WebsiteRepositoryInterface $websiteRepository */
4227
$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class);
4328
$baseWebsite = $websiteRepository->get('base');
4429

45-
$attributeModel = $attributeFactory->create();
46-
$attributeModel->setData(
47-
[
48-
'attribute_code' => 'test_configurable',
49-
'entity_type_id' => $installer->getEntityTypeId(Product::ENTITY),
50-
'is_global' => 1,
51-
'is_user_defined' => 1,
52-
'frontend_input' => 'select',
53-
'is_unique' => 0,
54-
'is_required' => 0,
55-
'is_searchable' => 1,
56-
'is_visible_in_advanced_search' => 1,
57-
'is_comparable' => 1,
58-
'is_filterable' => 1,
59-
'is_filterable_in_search' => 1,
60-
'is_used_for_promo_rules' => 0,
61-
'is_html_allowed_on_front' => 1,
62-
'is_visible_on_front' => 1,
63-
'used_in_product_listing' => 1,
64-
'used_for_sort_by' => 1,
65-
'frontend_label' => ['Test Configurable'],
66-
'backend_type' => 'int',
67-
'option' => [
68-
'value' => ['option_0' => ['Option 1'], 'option_1' => ['Option 2']],
69-
'order' => ['option_0' => 1, 'option_1' => 2],
70-
],
71-
'default' => ['option_0']
72-
]
73-
);
74-
$attribute = $attributeRepository->save($attributeModel);
75-
76-
$installer->addAttributeToGroup(Product::ENTITY, $attributeSetId, $groupId, $attribute->getId());
77-
CacheCleaner::cleanAll();
78-
$eavConfig->clear();
79-
8030
/** @var ProductRepositoryInterface $productRepository */
8131
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
8232
/** @var ProductInterfaceFactory $productInterfaceFactory */

dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_layered_navigation_attribute_rollback.php

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
declare(strict_types=1);
77

88
use Magento\Catalog\Api\CategoryRepositoryInterface;
9-
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
109
use Magento\Catalog\Api\ProductRepositoryInterface;
11-
use Magento\Eav\Model\Config;
1210
use Magento\Framework\Exception\NoSuchEntityException;
1311
use Magento\Framework\Registry;
1412
use Magento\TestFramework\Catalog\Model\GetCategoryByName;
1513
use Magento\TestFramework\Helper\Bootstrap;
14+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
1615

1716
$objectManager = Bootstrap::getObjectManager();
1817
/** @var Registry $registry */
@@ -45,17 +44,7 @@
4544
//Category already removed
4645
}
4746

48-
$eavConfig = $objectManager->get(Config::class);
49-
/** @var ProductAttributeRepositoryInterface $attributeRepository */
50-
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);
51-
52-
try {
53-
$attribute = $attributeRepository->get('test_configurable');
54-
$attributeRepository->delete($attribute);
55-
} catch (NoSuchEntityException $exception) {
56-
//Attribute already removed
57-
}
58-
$eavConfig->clear();
47+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/layered_navigation_attribute_rollback.php');
5948

6049
$registry->unregister('isSecureArea');
6150
$registry->register('isSecureArea', false);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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;
9+
10+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
11+
use Magento\Catalog\Model\Product;
12+
use Magento\Framework\Search\Request\Config as RequestConfig;
13+
use Magento\Framework\Search\Request\Config\FilesystemReader as RequestConfigReader;
14+
use Magento\TestFramework\Helper\Bootstrap;
15+
use PHPUnit\Framework\TestCase;
16+
17+
class AdvancedTest extends TestCase
18+
{
19+
/**
20+
* @var Advanced
21+
*/
22+
private $model;
23+
24+
protected function setUp(): void
25+
{
26+
$requestConfigReader = Bootstrap::getObjectManager()->get(RequestConfigReader::class);
27+
$requestConfig = Bootstrap::getObjectManager()->get(RequestConfig::class);
28+
$requestConfig->merge($requestConfigReader->read());
29+
30+
$this->model = Bootstrap::getObjectManager()->create(Advanced::class);
31+
}
32+
33+
/**
34+
* @magentoDbIsolation disabled
35+
* @magentoDataFixture Magento/Catalog/_files/products_with_not_empty_layered_navigation_attribute.php
36+
* @magentoDataFixture Magento/Catalog/_files/not_visible_product_with_layered_navigation_attribute.php
37+
*/
38+
public function testAddFilters(): void
39+
{
40+
$attributeCode = 'test_configurable';
41+
$attributeRepository = Bootstrap::getObjectManager()->get(ProductAttributeRepositoryInterface::class);
42+
$attribute = $attributeRepository->get($attributeCode);
43+
$option = $attribute->getOptions()[1];
44+
self::assertEquals('Option 1', $option->getLabel());
45+
46+
$filters = [$attribute->getAttributeCode() => $option->getValue()];
47+
$this->model->addFilters($filters);
48+
$productCollection = $this->model->getProductCollection();
49+
$products = $productCollection->getItems();
50+
self::assertCount(1, $products);
51+
/** @var Product $product */
52+
$product = array_shift($products);
53+
self::assertEquals('Option 1', $product->getAttributeText($attributeCode));
54+
}
55+
}

0 commit comments

Comments
 (0)