Skip to content

Commit

Permalink
Merge remote-tracking branch 'local/ACP2E-2201' into PR_06_SEP_2023
Browse files Browse the repository at this point in the history
  • Loading branch information
o-dubovyk committed Oct 13, 2023
2 parents 7e8f730 + 412997e commit ac6941c
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 50 deletions.
25 changes: 14 additions & 11 deletions app/code/Magento/Catalog/Test/Fixture/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace Magento\Catalog\Test\Fixture;

use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Catalog\Api\ProductAttributeManagementInterface;
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
use Magento\Catalog\Model\Product;
Expand Down Expand Up @@ -96,6 +95,11 @@ class Attribute implements RevertibleDataFixtureInterface
*/
private ResourceModelAttribute $resourceModelAttribute;

/**
* @var ProductAttributeRepositoryInterface
*/
private ProductAttributeRepositoryInterface $productAttributeRepository;

/**
* @param ServiceFactory $serviceFactory
* @param ProcessorInterface $dataProcessor
Expand All @@ -104,6 +108,7 @@ class Attribute implements RevertibleDataFixtureInterface
* @param AttributeFactory $attributeFactory
* @param DataMerger $dataMerger
* @param ResourceModelAttribute $resourceModelAttribute
* @param ProductAttributeRepositoryInterface $productAttributeRepository
*/
public function __construct(
ServiceFactory $serviceFactory,
Expand All @@ -112,7 +117,8 @@ public function __construct(
ProductAttributeManagementInterface $productAttributeManagement,
AttributeFactory $attributeFactory,
DataMerger $dataMerger,
ResourceModelAttribute $resourceModelAttribute
ResourceModelAttribute $resourceModelAttribute,
ProductAttributeRepositoryInterface $productAttributeRepository
) {
$this->serviceFactory = $serviceFactory;
$this->dataProcessor = $dataProcessor;
Expand All @@ -121,6 +127,7 @@ public function __construct(
$this->attributeFactory = $attributeFactory;
$this->dataMerger = $dataMerger;
$this->resourceModelAttribute = $resourceModelAttribute;
$this->productAttributeRepository = $productAttributeRepository;
}

/**
Expand All @@ -134,16 +141,11 @@ public function apply(array $data = []): ?DataObject
return $this->applyAttributeWithAdditionalData($data);
}

$service = $this->serviceFactory->create(ProductAttributeRepositoryInterface::class, 'save');

/**
* @var ProductAttributeInterface $attribute
*/
$attribute = $service->execute(
[
'attribute' => $this->prepareData(array_diff_key($data, self::DEFAULT_ATTRIBUTE_SET_DATA))
]
$attribute = $this->attributeFactory->createAttribute(
EavAttribute::class,
$this->prepareData(array_diff_key($data, self::DEFAULT_ATTRIBUTE_SET_DATA))
);
$attribute = $this->productAttributeRepository->save($attribute);

$attributeSetData = $this->prepareAttributeSetData(
array_intersect_key($data, self::DEFAULT_ATTRIBUTE_SET_DATA)
Expand Down Expand Up @@ -201,6 +203,7 @@ private function applyAttributeWithAdditionalData(array $data = []): ?DataObject
private function prepareData(array $data): array
{
$data = array_merge(self::DEFAULT_DATA, $data);
$data['frontend_label'] ??= $data['default_frontend_label'];

return $this->dataProcessor->process($this, $data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public function getOptions(array $optionIds, ?int $storeId, array $attributeCode
'attribute_code' => 'a.attribute_code',
'attribute_label' => 'a.frontend_label',
'attribute_type' => 'a.frontend_input',
'position' => 'attribute_configuration.position'
'position' => 'attribute_configuration.position',
'is_filterable' => 'attribute_configuration.is_filterable',
]
)
->joinLeft(
Expand Down Expand Up @@ -107,7 +108,7 @@ public function getOptions(array $optionIds, ?int $storeId, array $attributeCode
'options.sort_order ' . Select::SQL_ASC
);

$select->where('option_value.option_id IN (?)', $optionIds);
$select->where('option_value.option_id IN (?) OR attribute_configuration.is_filterable = 2', $optionIds);

if (!empty($attributeCodes)) {
$select->orWhere(
Expand Down Expand Up @@ -136,10 +137,10 @@ private function formatResult(Select $select): array
$result[$option['attribute_code']] = [
'attribute_id' => $option['attribute_id'],
'attribute_code' => $option['attribute_code'],
'attribute_label' => $option['attribute_store_label']
? $option['attribute_store_label'] : $option['attribute_label'],
'attribute_label' => $option['attribute_store_label'] ?: $option['attribute_label'],
'attribute_type' => $option['attribute_type'],
'position' => $option['position'],
'is_filterable' => (int) $option['is_filterable'],
'options' => [],
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class Attribute implements LayerBuilderInterface
*/
private const CATEGORY_BUCKET = 'category_bucket';

private const ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS = 1;

/**
* @var AttributeOptionProvider
*/
Expand Down Expand Up @@ -91,23 +93,21 @@ public function build(AggregationInterface $aggregation, ?int $storeId): array

$result[$bucketName] = $this->layerFormatter->buildLayer(
$attribute['attribute_label'] ?? $bucketName,
\count($bucket->getValues()),
0,
$attribute['attribute_code'] ?? $bucketName,
isset($attribute['position']) ? $attribute['position'] : null
);

$options = $this->getSortedOptions(
$bucket,
isset($attribute['options']) ? $attribute['options'] : [],
($attribute['attribute_type']) ? $attribute['attribute_type']: ''
);
foreach ($options as $option) {
$result[$bucketName]['options'][] = $this->layerFormatter->buildItem(
$option['label'],
$option['value'],
$option['count']
$optionLabels = $attribute['attribute_type'] === 'boolean'
? $this->YesNo->toArray()
: $attribute['options'] ?? [];
$result[$bucketName]['options'] = $this->getSortedOptions($bucket, $optionLabels);
if (self::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS === $attribute['is_filterable']) {
$result[$bucketName]['options'] = array_filter(
$result[$bucketName]['options'],
fn ($option) => $option['count']
);
}
$result[$bucketName]['count'] = count($result[$bucketName]['options']);
}

return $result;
Expand Down Expand Up @@ -181,38 +181,24 @@ function (AggregationValueInterface $value) {
*
* @param BucketInterface $bucket
* @param array $optionLabels
* @param string $attributeType
* @return array
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
private function getSortedOptions(BucketInterface $bucket, array $optionLabels, string $attributeType): array
private function getSortedOptions(BucketInterface $bucket, array $optionLabels): array
{
$options = [];
/**
* Option labels array has been sorted
*/
$options = $optionLabels;
foreach ($optionLabels as $optionId => $optionLabel) {
$options[$optionId] = $this->layerFormatter->buildItem($optionLabel, $optionId, 0);
}
foreach ($bucket->getValues() as $value) {
$metrics = $value->getMetrics();
$optionValue = $metrics['value'];
if (isset($optionLabels[$optionValue])) {
$optionLabel = $optionLabels[$optionValue];
$optionId = $metrics['value'];
if (isset($options[$optionId])) {
$options[$optionId]['count'] = $metrics['count'];
} else {
if ($attributeType === 'boolean') {
$yesNoOptions = $this->YesNo->toArray();
$optionLabel = $yesNoOptions[$optionValue];
} else {
$optionLabel = $optionValue;
}
}
$options[$optionValue] = $metrics + ['label' => $optionLabel];
}

/**
* Delete options without bucket values
*/
foreach ($options as $optionId => $option) {
if (!is_array($options[$optionId])) {
unset($options[$optionId]);
$options[$optionId] = $this->layerFormatter->buildItem($optionId, $optionId, $metrics['count']);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

namespace Magento\GraphQl\Catalog;

use Magento\Catalog\Test\Fixture\Product as ProductFixture;
use Magento\Catalog\Test\Fixture\SelectAttribute as SelectAttributeFixture;
use Magento\Eav\Test\Fixture\AttributeOption as AttributeOptionFixture;
use Magento\TestFramework\Fixture\DataFixture;
use Magento\TestFramework\TestCase\GraphQlAbstract;

class ProductSearchAggregationsTest extends GraphQlAbstract
Expand Down Expand Up @@ -154,6 +158,59 @@ function ($a) {
$this->assertEquals($expectedOptions, $priceAggregation['options']);
}

#[
DataFixture(
SelectAttributeFixture::class,
['attribute_code' => 'attr_with_results', 'options' => [], 'is_filterable' => 1]
),
DataFixture(
AttributeOptionFixture::class,
['entity_type' => 4, 'attribute_code' => 'attr_with_results'],
'attr1opt1'
),
DataFixture(
AttributeOptionFixture::class,
['entity_type' => 4, 'attribute_code' => 'attr_with_results'],
'attr1opt2'
),
DataFixture(
SelectAttributeFixture::class,
['attribute_code' => 'attr_no_results', 'options' => [], 'is_filterable' => 2]
),
DataFixture(
AttributeOptionFixture::class,
['entity_type' => 4, 'attribute_code' => 'attr_no_results'],
'attr2opt1'
),
DataFixture(
AttributeOptionFixture::class,
['entity_type' => 4, 'attribute_code' => 'attr_no_results'],
'attr2opt2'
),
DataFixture(
ProductFixture::class,
[
'sku' => 'simple_product1',
'attr_with_results' => '$attr1opt1.value$',
'attr_no_results' => '$attr2opt1.value$',
]
),
]
public function testAggregationFilterableAttributes(): void
{
$query = $this->getGraphQlQuery('"simple_product1"');
$result = $this->graphQlQuery($query);

self::assertArrayNotHasKey('errors', $result);
self::assertArrayHasKey('aggregations', $result['products']);

$aggregations = array_column($result['products']['aggregations'], null, 'attribute_code');
self::assertEquals(1, $aggregations['attr_with_results']['count']);
self::assertCount(1, $aggregations['attr_with_results']['options']);
self::assertEquals(2, $aggregations['attr_no_results']['count']);
self::assertCount(2, $aggregations['attr_no_results']['options']);
}

/**
* Get GraphQl products query with aggregations
*
Expand Down

0 comments on commit ac6941c

Please sign in to comment.