Skip to content

Commit e89b753

Browse files
committed
MC-21694: Boolean attributes show "_bucket" in graphql search aggregations
1 parent ab19a3d commit e89b753

File tree

7 files changed

+192
-6
lines changed

7 files changed

+192
-6
lines changed

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/AttributeOptionProvider.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ public function __construct(ResourceConnection $resourceConnection)
4141
* Get option data. Return list of attributes with option data
4242
*
4343
* @param array $optionIds
44+
* @param array $attributeCodes
4445
* @return array
4546
* @throws \Zend_Db_Statement_Exception
4647
*/
47-
public function getOptions(array $optionIds): array
48+
public function getOptions(array $optionIds, array $attributeCodes = []): array
4849
{
4950
if (!$optionIds) {
5051
return [];
@@ -60,20 +61,28 @@ public function getOptions(array $optionIds): array
6061
'attribute_label' => 'a.frontend_label',
6162
]
6263
)
63-
->joinInner(
64+
->joinLeft(
6465
['options' => $this->resourceConnection->getTableName('eav_attribute_option')],
6566
'a.attribute_id = options.attribute_id',
6667
[]
6768
)
68-
->joinInner(
69+
->joinLeft(
6970
['option_value' => $this->resourceConnection->getTableName('eav_attribute_option_value')],
7071
'options.option_id = option_value.option_id',
7172
[
7273
'option_label' => 'option_value.value',
7374
'option_id' => 'option_value.option_id',
7475
]
75-
)
76-
->where('option_value.option_id IN (?)', $optionIds);
76+
);
77+
78+
$select->where('option_value.option_id IN (?)', $optionIds);
79+
80+
if (!empty($attributeCodes)) {
81+
$select->orWhere(
82+
'a.attribute_code in (?) AND a.frontend_input = \'boolean\'',
83+
$attributeCodes
84+
);
85+
}
7786

7887
return $this->formatResult($select);
7988
}

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Builder/Attribute.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ private function isBucketEmpty(?BucketInterface $bucket): bool
139139
private function getAttributeOptions(AggregationInterface $aggregation): array
140140
{
141141
$attributeOptionIds = [];
142+
$attributes = [];
142143
foreach ($this->getAttributeBuckets($aggregation) as $bucket) {
144+
$attributes[] = \preg_replace('~_bucket$~', '', $bucket->getName());
143145
$attributeOptionIds[] = \array_map(
144146
function (AggregationValueInterface $value) {
145147
return $value->getValue();
@@ -152,6 +154,6 @@ function (AggregationValueInterface $value) {
152154
return [];
153155
}
154156

155-
return $this->attributeOptionProvider->getOptions(\array_merge(...$attributeOptionIds));
157+
return $this->attributeOptionProvider->getOptions(\array_merge(...$attributeOptionIds), $attributes);
156158
}
157159
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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\GraphQl\Catalog;
9+
10+
use Magento\TestFramework\TestCase\GraphQlAbstract;
11+
12+
class ProductSearchAggregationsTest extends GraphQlAbstract
13+
{
14+
/**
15+
* @magentoApiDataFixture Magento/Catalog/_files/products_with_boolean_attribute.php
16+
*/
17+
public function testAggregationBooleanAttribute()
18+
{
19+
$skus= '"search_product_1", "search_product_2", "search_product_3", "search_product_4" ,"search_product_5"';
20+
$query = <<<QUERY
21+
{
22+
products(filter: {sku: {in: [{$skus}]}}){
23+
items{
24+
id
25+
sku
26+
name
27+
}
28+
aggregations{
29+
label
30+
attribute_code
31+
count
32+
options{
33+
label
34+
value
35+
count
36+
}
37+
}
38+
}
39+
}
40+
QUERY;
41+
42+
$result = $this->graphQlQuery($query);
43+
44+
$this->assertArrayNotHasKey('errors', $result);
45+
$this->assertArrayHasKey('items', $result['products']);
46+
$this->assertCount(5, $result['products']['items']);
47+
$this->assertArrayHasKey('aggregations', $result['products']);
48+
49+
$booleanAggregation = array_filter(
50+
$result['products']['aggregations'],
51+
function ($a) {
52+
return $a['attribute_code'] == 'boolean_attribute';
53+
}
54+
);
55+
$this->assertNotEmpty($booleanAggregation);
56+
$booleanAggregation = reset($booleanAggregation);
57+
$this->assertEquals('Boolean Attribute', $booleanAggregation['label']);
58+
$this->assertEquals('boolean_attribute', $booleanAggregation['attribute_code']);
59+
$this->assertEquals(2, $booleanAggregation['count']);
60+
$this->assertCount(2, $booleanAggregation['options']);
61+
$this->assertContains(['label' => '0', 'value'=> '0', 'count' => '2'], $booleanAggregation['options']);
62+
$this->assertContains(['label' => '1', 'value'=> '1', 'count' => '3'], $booleanAggregation['options']);
63+
}
64+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\Catalog\Setup\CategorySetup;
8+
use Magento\Eav\Api\AttributeRepositoryInterface;
9+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
10+
use Magento\TestFramework\Helper\Bootstrap;
11+
12+
$objectManager = Bootstrap::getObjectManager();
13+
/** @var AttributeRepositoryInterface $attributeRepository */
14+
$attributeRepository = $objectManager->get(AttributeRepositoryInterface::class);
15+
/** @var Attribute $attribute */
16+
$attribute = $objectManager->create(Attribute::class);
17+
/** @var $installer \Magento\Catalog\Setup\CategorySetup */
18+
$installer = $objectManager->create(CategorySetup::class);
19+
20+
$attribute->setData(
21+
[
22+
'attribute_code' => 'boolean_attribute',
23+
'entity_type_id' => CategorySetup::CATALOG_PRODUCT_ENTITY_TYPE_ID,
24+
'is_global' => 0,
25+
'is_user_defined' => 1,
26+
'frontend_input' => 'boolean',
27+
'is_unique' => 0,
28+
'is_required' => 0,
29+
'is_searchable' => 1,
30+
'is_visible_in_advanced_search' => 1,
31+
'is_comparable' => 0,
32+
'is_filterable' => 1,
33+
'is_filterable_in_search' => 1,
34+
'is_used_for_promo_rules' => 0,
35+
'is_html_allowed_on_front' => 1,
36+
'is_visible_on_front' => 1,
37+
'used_in_product_listing' => 1,
38+
'used_for_sort_by' => 0,
39+
'frontend_label' => ['Boolean Attribute'],
40+
'backend_type' => 'int'
41+
]
42+
);
43+
44+
$attributeRepository->save($attribute);
45+
46+
/* Assign attribute to attribute set */
47+
$installer->addAttributeToGroup('catalog_product', 'Default', 'Attributes', $attribute->getId());
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\Framework\Registry;
8+
use Magento\TestFramework\Helper\Bootstrap;
9+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
10+
11+
$objectManager = Bootstrap::getObjectManager();
12+
13+
$registry = $objectManager->get(Registry::class);
14+
$registry->unregister('isSecureArea');
15+
$registry->register('isSecureArea', true);
16+
/** @var Attribute $attribute */
17+
$attribute = $objectManager->create(Attribute::class);
18+
$attribute->load('boolean_attribute', 'attribute_code');
19+
$attribute->delete();
20+
$registry->unregister('isSecureArea');
21+
$registry->register('isSecureArea', false);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\Catalog\Api\ProductRepositoryInterface;
8+
use Magento\TestFramework\Helper\CacheCleaner;
9+
10+
require_once __DIR__ . '/products_for_search.php';
11+
require_once __DIR__ . '/product_boolean_attribute.php';
12+
13+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
14+
15+
$yesIds = [101, 102, 104];
16+
$noIds = [103, 105];
17+
18+
foreach ($yesIds as $id) {
19+
$product = $productRepository->getById($id);
20+
$product->setBooleanAttribute(1);
21+
$productRepository->save($product);
22+
}
23+
foreach ($noIds as $id) {
24+
$product = $productRepository->getById($id);
25+
$product->setBooleanAttribute(0);
26+
$productRepository->save($product);
27+
}
28+
CacheCleaner::cleanAll();
29+
/** @var \Magento\Indexer\Model\Indexer\Collection $indexerCollection */
30+
$indexerCollection = $objectManager->get(\Magento\Indexer\Model\Indexer\Collection::class);
31+
$indexerCollection->load();
32+
/** @var \Magento\Indexer\Model\Indexer $indexer */
33+
foreach ($indexerCollection->getItems() as $indexer) {
34+
$indexer->reindexAll();
35+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
require_once __DIR__ . '/products_for_search_rollback.php';
8+
require_once __DIR__ . '/product_boolean_attribute_rollback.php';

0 commit comments

Comments
 (0)