Skip to content

Commit 9c02116

Browse files
author
Vasilii Burlacu
committed
Display category filter item in layered navigation based on the system configuration from admin area
1 parent 5a9fcab commit 9c02116

File tree

5 files changed

+196
-5
lines changed

5 files changed

+196
-5
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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\Catalog\Model\Config;
9+
10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Store\Model\ScopeInterface;
13+
use Magento\Store\Model\StoreManagerInterface;
14+
15+
/**
16+
* Config for category in the layered navigation
17+
*/
18+
class LayerCategoryConfig
19+
{
20+
private const XML_PATH_CATALOG_LAYERED_NAVIGATION_DISPLAY_CATEGORY = 'catalog/layered_navigation/display_category';
21+
22+
/**
23+
* @var ScopeConfigInterface
24+
*/
25+
private $scopeConfig;
26+
27+
/**
28+
* @var StoreManagerInterface
29+
*/
30+
private $storeManager;
31+
32+
/**
33+
* LayerCategoryConfig constructor
34+
*
35+
* @param ScopeConfigInterface $scopeConfig
36+
* @param StoreManagerInterface $storeManager
37+
*/
38+
public function __construct(
39+
ScopeConfigInterface $scopeConfig,
40+
StoreManagerInterface $storeManager
41+
) {
42+
$this->scopeConfig = $scopeConfig;
43+
$this->storeManager = $storeManager;
44+
}
45+
46+
/**
47+
* Check if category filter item should be added in the layered navigation
48+
*
49+
* @param string $scopeType
50+
* @param null|int|string $scopeCode
51+
*
52+
* @return bool
53+
*/
54+
public function isCategoryFilterVisibleInLayerNavigation(
55+
$scopeType = ScopeInterface::SCOPE_STORES,
56+
$scopeCode = null
57+
): bool {
58+
if (!$scopeCode) {
59+
$scopeCode = $this->getStoreId();
60+
}
61+
62+
return $this->scopeConfig->isSetFlag(
63+
static::XML_PATH_CATALOG_LAYERED_NAVIGATION_DISPLAY_CATEGORY,
64+
$scopeType,
65+
$scopeCode
66+
);
67+
}
68+
69+
/**
70+
* Get the current store ID
71+
*
72+
* @return int|null
73+
*/
74+
protected function getStoreId(): ?int
75+
{
76+
try {
77+
return (int) $this->storeManager->getStore()->getId();
78+
} catch (NoSuchEntityException $e) {
79+
return null;
80+
}
81+
}
82+
}

app/code/Magento/Catalog/Model/Layer/FilterList.php

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

88
namespace Magento\Catalog\Model\Layer;
99

10+
use Magento\Catalog\Model\Config\LayerCategoryConfig;
11+
use Magento\Framework\App\ObjectManager;
12+
1013
/**
1114
* Layer navigation filters
1215
*/
@@ -44,18 +47,27 @@ class FilterList
4447
*/
4548
protected $filters = [];
4649

50+
/**
51+
* @var LayerCategoryConfig|null
52+
*/
53+
private $layerCategoryConfig;
54+
4755
/**
4856
* @param \Magento\Framework\ObjectManagerInterface $objectManager
4957
* @param FilterableAttributeListInterface $filterableAttributes
5058
* @param array $filters
59+
* @param LayerCategoryConfig|null $layerCategoryConfig
5160
*/
5261
public function __construct(
5362
\Magento\Framework\ObjectManagerInterface $objectManager,
5463
FilterableAttributeListInterface $filterableAttributes,
55-
array $filters = []
64+
array $filters = [],
65+
LayerCategoryConfig $layerCategoryConfig = null
5666
) {
5767
$this->objectManager = $objectManager;
5868
$this->filterableAttributes = $filterableAttributes;
69+
$this->layerCategoryConfig = $layerCategoryConfig ?:
70+
ObjectManager::getInstance()->get(LayerCategoryConfig::class);
5971

6072
/** Override default filter type models */
6173
$this->filterTypes = array_merge($this->filterTypes, $filters);
@@ -70,9 +82,11 @@ public function __construct(
7082
public function getFilters(\Magento\Catalog\Model\Layer $layer)
7183
{
7284
if (!count($this->filters)) {
73-
$this->filters = [
74-
$this->objectManager->create($this->filterTypes[self::CATEGORY_FILTER], ['layer' => $layer]),
75-
];
85+
if ($this->layerCategoryConfig->isCategoryFilterVisibleInLayerNavigation()) {
86+
$this->filters = [
87+
$this->objectManager->create($this->filterTypes[self::CATEGORY_FILTER], ['layer' => $layer]),
88+
];
89+
}
7690
foreach ($this->filterableAttributes->getList() as $attribute) {
7791
$this->filters[] = $this->createAttributeFilter($attribute, $layer);
7892
}

app/code/Magento/Catalog/Test/Unit/Model/Layer/FilterListTest.php

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@
77

88
namespace Magento\Catalog\Test\Unit\Model\Layer;
99

10+
use Magento\Catalog\Model\Config\LayerCategoryConfig;
1011
use \Magento\Catalog\Model\Layer\FilterList;
12+
use PHPUnit\Framework\MockObject\MockObject;
1113

14+
/**
15+
* Filter List Test
16+
*/
1217
class FilterListTest extends \PHPUnit\Framework\TestCase
1318
{
1419
/**
@@ -36,6 +41,14 @@ class FilterListTest extends \PHPUnit\Framework\TestCase
3641
*/
3742
protected $model;
3843

44+
/**
45+
* @var LayerCategoryConfig|MockObject
46+
*/
47+
private $layerCategoryConfigMock;
48+
49+
/**
50+
* Set Up
51+
*/
3952
protected function setUp()
4053
{
4154
$this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class);
@@ -51,8 +64,14 @@ protected function setUp()
5164

5265
];
5366
$this->layerMock = $this->createMock(\Magento\Catalog\Model\Layer::class);
67+
$this->layerCategoryConfigMock = $this->createMock(LayerCategoryConfig::class);
5468

55-
$this->model = new FilterList($this->objectManagerMock, $this->attributeListMock, $filters);
69+
$this->model = new FilterList(
70+
$this->objectManagerMock,
71+
$this->attributeListMock,
72+
$filters,
73+
$this->layerCategoryConfigMock
74+
);
5675
}
5776

5877
/**
@@ -90,9 +109,57 @@ public function testGetFilters($method, $value, $expectedClass)
90109
->method('getList')
91110
->will($this->returnValue([$this->attributeMock]));
92111

112+
$this->layerCategoryConfigMock->expects($this->once())
113+
->method('isCategoryVisibleInLayer')
114+
->willReturn(true);
115+
93116
$this->assertEquals(['filter', 'filter'], $this->model->getFilters($this->layerMock));
94117
}
95118

119+
/**
120+
* Test filters list result when category should not be included
121+
*
122+
* @param string $method
123+
* @param string $value
124+
* @param string $expectedClass
125+
* @param array $expectedResult
126+
*
127+
* @dataProvider getFiltersWithoutCategoryDataProvider
128+
*
129+
* @return void
130+
*/
131+
public function testGetFiltersWithoutCategoryFilter(
132+
string $method,
133+
string $value,
134+
string $expectedClass,
135+
array $expectedResult
136+
): void {
137+
$this->objectManagerMock->expects($this->at(0))
138+
->method('create')
139+
->with(
140+
$expectedClass,
141+
[
142+
'data' => ['attribute_model' => $this->attributeMock],
143+
'layer' => $this->layerMock
144+
]
145+
)
146+
->will($this->returnValue('filter'));
147+
148+
$this->attributeMock->expects($this->once())
149+
->method($method)
150+
->will($this->returnValue($value));
151+
152+
$this->attributeListMock->expects($this->once())
153+
->method('getList')
154+
->will($this->returnValue([$this->attributeMock]));
155+
156+
$this->layerCategoryConfigMock->expects($this->once())
157+
->method('isCategoryVisibleInLayer')
158+
->willReturn(false);
159+
160+
$this->assertEquals($expectedResult, $this->model->getFilters($this->layerMock));
161+
}
162+
96163
/**
97164
* @return array
98165
*/
@@ -116,4 +183,23 @@ public function getFiltersDataProvider()
116183
]
117184
];
118185
}
186+
187+
/**
188+
* Provides attribute filters without category item
189+
*
190+
* @return array
191+
*/
192+
public function getFiltersWithoutCategoryDataProvider(): array
193+
{
194+
return [
195+
'Filters contains only price attribute' => [
196+
'method' => 'getFrontendInput',
197+
'value' => 'price',
198+
'expectedClass' => 'PriceFilterClass',
199+
'expectedResult' => [
200+
'filter'
201+
]
202+
]
203+
];
204+
}
119205
}

app/code/Magento/Catalog/etc/adminhtml/system.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@
138138
<hide_in_single_store_mode>1</hide_in_single_store_mode>
139139
</field>
140140
</group>
141+
<group id="layered_navigation">
142+
<field id="display_category" translate="label" type="select" sortOrder="15" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
143+
<label>Display Category</label>
144+
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
145+
</field>
146+
</group>
141147
<group id="navigation" translate="label" type="text" sortOrder="500" showInDefault="1" showInWebsite="1" showInStore="1">
142148
<label>Category Top Navigation</label>
143149
<field id="max_depth" translate="label" type="text" sortOrder="1" showInDefault="1" canRestore="1">

app/code/Magento/Catalog/etc/config.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454
<time_format>12h</time_format>
5555
<forbidden_extensions>php,exe</forbidden_extensions>
5656
</custom_options>
57+
<layered_navigation>
58+
<display_category>1</display_category>
59+
</layered_navigation>
5760
</catalog>
5861
<indexer>
5962
<catalog_product_price>

0 commit comments

Comments
 (0)