<?php
declare(strict_types=1);
namespace BitBag\OpenMarketplace\Component\Elasticsearch\Form\Resolver;
use BitBag\OpenMarketplace\Component\Elasticsearch\QueryBuilder\ListProductsQueryBuilderInterface;
use BitBag\SyliusElasticsearchPlugin\Facet\RegistryInterface;
use Elastica\Aggregation\Filter as FilterAggregation;
use Elastica\Query\BoolQuery;
use FOS\ElasticaBundle\Finder\PaginatedFinderInterface;
use Pagerfanta\Pagerfanta;
use Symfony\Component\Form\FormEvent;
final class ListProductsFacetsResolver implements ListProductsFacetsResolverInterface
{
public function __construct(
private ListProductsQueryBuilderInterface $queryBuilder,
private RegistryInterface $facetRegistry,
private PaginatedFinderInterface $finder
) {
}
public function resolveFacets(FormEvent $event): Pagerfanta
{
$query = $this->queryBuilder->getQuery($event);
$eventData = $event->getData() ?? [];
$rangeFilters = [];
foreach ($eventData['filters'] ?? [] as $facetId => $selectedBuckets) {
if (!empty($selectedBuckets) && is_array($selectedBuckets)
&& (array_key_exists('min', $selectedBuckets) || array_key_exists('max', $selectedBuckets))
) {
$rangeFilters[(string) $facetId] = $selectedBuckets;
}
}
foreach ($this->facetRegistry->getFacets() as $facetId => $facet) {
$aggregation = $facet->getAggregation()->setName((string) $facetId);
$otherRanges = array_diff_key($rangeFilters, [(string) $facetId => true]);
if (!empty($otherRanges)) {
$filterBool = new BoolQuery();
foreach ($otherRanges as $rfId => $rfBuckets) {
try {
$rangeFacet = $this->facetRegistry->getFacetById($rfId);
$filterBool->addFilter($rangeFacet->getQuery($rfBuckets));
} catch (\Exception $e) {
continue;
}
}
$aggregation->setName('_inner');
$filterAgg = new FilterAggregation((string) $facetId, $filterBool);
$filterAgg->addAggregation($aggregation);
$query->addAggregation($filterAgg);
} else {
$query->addAggregation($aggregation);
}
}
$query->setSize(0);
return $this->finder->findPaginated($query);
}
}