src/module-elasticsuite-catalog-graph-ql/DataProvider/Product/LayeredNavigation/Builder/Price.php
<?php
/**
* DISCLAIMER
* Do not edit or add to this file if you wish to upgrade Smile Elastic Suite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteCatalogGraphQl
* @author Romain Ruaud <romain.ruaud@smile.fr>
* @copyright 2020 Smile
* @license Open Software License ("OSL") v. 3.0
*/
namespace Smile\ElasticsuiteCatalogGraphQl\DataProvider\Product\LayeredNavigation\Builder;
use Magento\Catalog\Model\Product\Attribute\Repository as AttributeRepository;
use Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation\LayerBuilderInterface;
use Magento\Framework\Api\Search\AggregationInterface;
use Magento\Framework\Api\Search\BucketInterface;
use Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation\Formatter\LayerFormatter;
use Magento\Framework\Phrase;
/**
* Layered Navigation Builder for Price items.
*
* @category Smile
* @package Smile\ElasticsuiteCatalogGraphQl
* @author Romain Ruaud <romain.ruaud@smile.fr>
*/
class Price implements LayerBuilderInterface
{
/**
* @var string
*/
const PRICE_BUCKET = 'price.price';
/**
* @var LayerFormatter
*/
private $layerFormatter;
/**
* @var AttributeRepository
*/
private $attributeRepository;
/**
* @var string
*/
private $attributeCode;
/**
* @var array
*/
private static $bucketMap = [
self::PRICE_BUCKET => [
'request_name' => 'price',
'label' => 'Price',
],
];
/**
* @param LayerFormatter $layerFormatter Layer Formatter
* @param AttributeRepository $attributeRepository Attribute Repository
* @param string $attributeCode Attribute code used to load the localized frontend label
*/
public function __construct(
LayerFormatter $layerFormatter,
AttributeRepository $attributeRepository,
string $attributeCode = 'price'
) {
$this->layerFormatter = $layerFormatter;
$this->attributeRepository = $attributeRepository;
$this->attributeCode = $attributeCode;
}
/**
* {@inheritdoc}
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function build(AggregationInterface $aggregation, ?int $storeId): array
{
$bucket = $aggregation->getBucket(self::PRICE_BUCKET);
if ($this->isBucketEmpty($bucket)) {
return [];
}
$label = __(self::$bucketMap[self::PRICE_BUCKET]['label']);
if ($frontendLabel = $this->getFrontendLabel($storeId)) {
$label = $frontendLabel;
}
$result = $this->layerFormatter->buildLayer(
$label,
\count($bucket->getValues()),
self::$bucketMap[self::PRICE_BUCKET]['request_name']
);
foreach ($bucket->getValues() as $value) {
$metrics = $value->getMetrics();
$result['options'][] = $this->layerFormatter->buildItem(
$value->getValue(),
$value->getValue(),
$metrics['count']
);
}
$result['has_more'] = false;
$result['rel_nofollow'] = false;
$attribute = $this->attributeRepository->get($this->attributeCode);
$result['frontend_input'] = $attribute->getFrontendInput();
return ['price' => $result];
}
/**
* Check that bucket contains data
*
* @param BucketInterface|null $bucket Bucket
*
* @return bool
*/
private function isBucketEmpty(?BucketInterface $bucket): bool
{
return null === $bucket || !$bucket->getValues();
}
/**
* Return the frontend label of the configured attribute for the given store, if available.
*
* @param int|null $storeId Store ID.
*
* @return string|null
*/
private function getFrontendLabel(?int $storeId): ?string
{
$label = null;
try {
$attribute = $this->attributeRepository->get($this->attributeCode);
$label = $attribute->getDefaultFrontendLabel();
$frontendLabels = array_filter(
$attribute->getFrontendLabels(),
function ($frontendLabel) use ($storeId) {
return $frontendLabel->getStoreId() == $storeId;
}
);
if (!empty($frontendLabels)) {
$label = reset($frontendLabels)->getLabel();
}
} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) {
;
}
return $label;
}
}