Skip to content

Commit 52f9fd4

Browse files
authored
Merge pull request #4799 from magento-trigger/MC-16650
- fixed Product Attribute Type Price Not Displaying
2 parents 3ee05a4 + bdfc864 commit 52f9fd4

File tree

17 files changed

+344
-15
lines changed

17 files changed

+344
-15
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Catalog\Model\Layer;
89

10+
/**
11+
* Layer navigation filters
12+
*/
913
class FilterList
1014
{
1115
const CATEGORY_FILTER = 'category';
@@ -106,9 +110,9 @@ protected function getAttributeFilterClass(\Magento\Catalog\Model\ResourceModel\
106110
{
107111
$filterClassName = $this->filterTypes[self::ATTRIBUTE_FILTER];
108112

109-
if ($attribute->getAttributeCode() == 'price') {
113+
if ($attribute->getFrontendInput() === 'price') {
110114
$filterClassName = $this->filterTypes[self::PRICE_FILTER];
111-
} elseif ($attribute->getBackendType() == 'decimal') {
115+
} elseif ($attribute->getBackendType() === 'decimal') {
112116
$filterClassName = $this->filterTypes[self::DECIMAL_FILTER];
113117
}
114118

app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,28 @@
278278
<data key="used_for_sort_by">false</data>
279279
<requiredEntity type="FrontendLabel">ProductAttributeFrontendLabel</requiredEntity>
280280
</entity>
281+
<entity name="productAttributeTypeOfPrice" type="ProductAttribute">
282+
<data key="attribute_code" unique="suffix">attribute</data>
283+
<data key="frontend_input">price</data>
284+
<data key="scope">global</data>
285+
<data key="is_required">false</data>
286+
<data key="is_unique">false</data>
287+
<data key="is_searchable">false</data>
288+
<data key="is_visible">true</data>
289+
<data key="is_wysiwyg_enabled">false</data>
290+
<data key="is_visible_in_advanced_search">false</data>
291+
<data key="is_visible_on_front">true</data>
292+
<data key="is_filterable">true</data>
293+
<data key="is_filterable_in_search">false</data>
294+
<data key="used_in_product_listing">false</data>
295+
<data key="is_used_for_promo_rules">false</data>
296+
<data key="is_comparable">true</data>
297+
<data key="is_used_in_grid">false</data>
298+
<data key="is_visible_in_grid">false</data>
299+
<data key="is_filterable_in_grid">false</data>
300+
<data key="used_for_sort_by">false</data>
301+
<requiredEntity type="FrontendLabel">ProductAttributeFrontendLabel</requiredEntity>
302+
</entity>
281303
<entity name="textProductAttribute" extends="productAttributeWysiwyg" type="ProductAttribute">
282304
<data key="frontend_input">text</data>
283305
<data key="default_value" unique="suffix">defaultValue</data>

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@
215215
<element name="textAttributeByName" type="text" selector="//div[@data-index='attributes']//fieldset[contains(@class, 'admin__field') and .//*[contains(.,'{{var}}')]]//input" parameterized="true"/>
216216
<element name="dropDownAttribute" type="select" selector="//select[@name='product[{{arg}}]']" parameterized="true" timeout="30"/>
217217
<element name="attributeSection" type="block" selector="//div[@data-index='attributes']/div[contains(@class, 'admin__collapsible-content _show')]" timeout="30"/>
218+
<element name="customAttribute" type="text" selector="product[{{attributecode}}]" timeout="30" parameterized="true"/>
218219
<element name="attributeGroupByName" type="button" selector="//div[@class='fieldset-wrapper-title']//span[text()='{{group}}']" parameterized="true"/>
219220
<element name="attributeByGroupAndName" type="text" selector="//div[@class='fieldset-wrapper-title']//span[text()='{{group}}']/../../following-sibling::div//span[contains(text(),'attribute')]" parameterized="true"/>
220221
</section>

app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryFilterSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
<section name="StorefrontCategoryFilterSection">
1212
<element name="CategoryFilter" type="button" selector="//main//div[@class='filter-options']//div[contains(text(), 'Category')]"/>
1313
<element name="CategoryByName" type="button" selector="//main//div[@class='filter-options']//li[@class='item']//a[contains(text(), '{{var1}}')]" parameterized="true"/>
14+
<element name="CustomPriceAttribute" type="button" selector="div.filter-options-title"/>
1415
</section>
1516
</sections>

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Catalog\Test\Unit\Model\Layer;
89

@@ -72,9 +73,13 @@ public function testGetFilters($method, $value, $expectedClass)
7273

7374
$this->objectManagerMock->expects($this->at(1))
7475
->method('create')
75-
->with($expectedClass, [
76-
'data' => ['attribute_model' => $this->attributeMock],
77-
'layer' => $this->layerMock])
76+
->with(
77+
$expectedClass,
78+
[
79+
'data' => ['attribute_model' => $this->attributeMock],
80+
'layer' => $this->layerMock
81+
]
82+
)
7883
->will($this->returnValue('filter'));
7984

8085
$this->attributeMock->expects($this->once())
@@ -95,8 +100,8 @@ public function getFiltersDataProvider()
95100
{
96101
return [
97102
[
98-
'method' => 'getAttributeCode',
99-
'value' => FilterList::PRICE_FILTER,
103+
'method' => 'getFrontendInput',
104+
'value' => 'price',
100105
'expectedClass' => 'PriceFilterClass',
101106
],
102107
[
@@ -105,8 +110,8 @@ public function getFiltersDataProvider()
105110
'expectedClass' => 'DecimalFilterClass',
106111
],
107112
[
108-
'method' => 'getAttributeCode',
109-
'value' => null,
113+
'method' => 'getFrontendInput',
114+
'value' => 'text',
110115
'expectedClass' => 'AttributeFilterClass',
111116
]
112117
];

app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\CatalogSearch\Model\Layer\Filter;
79

810
use Magento\Catalog\Model\Layer\Filter\AbstractFilter;
@@ -12,6 +14,9 @@
1214
*/
1315
class Decimal extends AbstractFilter
1416
{
17+
/** Decimal delta for filter */
18+
private const DECIMAL_DELTA = 0.001;
19+
1520
/**
1621
* @var \Magento\Framework\Pricing\PriceCurrencyInterface
1722
*/
@@ -70,11 +75,17 @@ public function apply(\Magento\Framework\App\RequestInterface $request)
7075

7176
list($from, $to) = explode('-', $filter);
7277

78+
// When the range is 10-20 we only need to get products that are in the 10-19.99 range.
79+
$toValue = $to;
80+
if (!empty($toValue) && $from !== $toValue) {
81+
$toValue -= self::DECIMAL_DELTA;
82+
}
83+
7384
$this->getLayer()
7485
->getProductCollection()
7586
->addFieldToFilter(
7687
$this->getAttributeModel()->getAttributeCode(),
77-
['from' => $from, 'to' => $to]
88+
['from' => $from, 'to' => $toValue]
7889
);
7990

8091
$this->getLayer()->getState()->addFilter(
@@ -111,7 +122,7 @@ protected function _getItemsData()
111122
$from = '';
112123
}
113124
if ($to == '*') {
114-
$to = null;
125+
$to = '';
115126
}
116127
$label = $this->renderRangeLabel(empty($from) ? 0 : $from, $to);
117128
$value = $from . '-' . $to;
@@ -138,7 +149,7 @@ protected function _getItemsData()
138149
protected function renderRangeLabel($fromPrice, $toPrice)
139150
{
140151
$formattedFromPrice = $this->priceCurrency->format($fromPrice);
141-
if ($toPrice === null) {
152+
if ($toPrice === '') {
142153
return __('%1 and above', $formattedFromPrice);
143154
} else {
144155
if ($fromPrice != $toPrice) {

app/code/Magento/CatalogSearch/Model/Layer/Filter/Price.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\CatalogSearch\Model\Layer\Filter;
79

810
use Magento\Catalog\Model\Layer\Filter\AbstractFilter;
@@ -11,6 +13,7 @@
1113
* Layer price filter based on Search API
1214
*
1315
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
16+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
1417
*/
1518
class Price extends AbstractFilter
1619
{
@@ -138,7 +141,7 @@ public function apply(\Magento\Framework\App\RequestInterface $request)
138141
list($from, $to) = $filter;
139142

140143
$this->getLayer()->getProductCollection()->addFieldToFilter(
141-
'price',
144+
$this->getAttributeModel()->getAttributeCode(),
142145
['from' => $from, 'to' => empty($to) || $from == $to ? $to : $to - self::PRICE_DELTA]
143146
);
144147

app/code/Magento/CatalogSearch/Model/Search/RequestGenerator.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\CatalogSearch\Model\Search;
79

810
use Magento\Catalog\Api\Data\EavAttributeInterface;
@@ -78,6 +80,7 @@ private function generateRequest($attributeType, $container, $useFulltext)
7880
{
7981
$request = [];
8082
foreach ($this->getSearchableAttributes() as $attribute) {
83+
/** @var $attribute Attribute */
8184
if ($attribute->getData($attributeType)) {
8285
if (!in_array($attribute->getAttributeCode(), ['price', 'category_ids'], true)) {
8386
$queryName = $attribute->getAttributeCode() . '_query';
@@ -97,12 +100,14 @@ private function generateRequest($attributeType, $container, $useFulltext)
97100
],
98101
];
99102
$bucketName = $attribute->getAttributeCode() . self::BUCKET_SUFFIX;
100-
$generator = $this->generatorResolver->getGeneratorForType($attribute->getBackendType());
103+
$generatorType = $attribute->getFrontendInput() === 'price'
104+
? $attribute->getFrontendInput()
105+
: $attribute->getBackendType();
106+
$generator = $this->generatorResolver->getGeneratorForType($generatorType);
101107
$request['filters'][$filterName] = $generator->getFilterData($attribute, $filterName);
102108
$request['aggregations'][$bucketName] = $generator->getAggregationData($attribute, $bucketName);
103109
}
104110
}
105-
/** @var $attribute Attribute */
106111
if (!$attribute->getIsSearchable() || in_array($attribute->getAttributeCode(), ['price'], true)) {
107112
// Some fields have their own specific handlers
108113
continue;

app/code/Magento/CatalogSearch/Model/Search/RequestGenerator/Decimal.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\CatalogSearch\Model\Search\RequestGenerator;
89

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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\Search\RequestGenerator;
9+
10+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
11+
use Magento\Framework\Search\Request\BucketInterface;
12+
use Magento\Framework\Search\Request\FilterInterface;
13+
14+
/**
15+
* Catalog search range request generator.
16+
*/
17+
class Price implements GeneratorInterface
18+
{
19+
/**
20+
* @inheritdoc
21+
*/
22+
public function getFilterData(Attribute $attribute, $filterName): array
23+
{
24+
return [
25+
'type' => FilterInterface::TYPE_RANGE,
26+
'name' => $filterName,
27+
'field' => $attribute->getAttributeCode(),
28+
'from' => '$' . $attribute->getAttributeCode() . '.from$',
29+
'to' => '$' . $attribute->getAttributeCode() . '.to$',
30+
];
31+
}
32+
33+
/**
34+
* @inheritdoc
35+
*/
36+
public function getAggregationData(Attribute $attribute, $bucketName): array
37+
{
38+
return [
39+
'type' => BucketInterface::TYPE_DYNAMIC,
40+
'name' => $bucketName,
41+
'field' => $attribute->getAttributeCode(),
42+
'method' => '$price_dynamic_algorithm$',
43+
'metric' => [['type' => 'count']],
44+
];
45+
}
46+
}

0 commit comments

Comments
 (0)