OP-7: Add facets to search form

This commit is contained in:
Gracjan Józefczyk
2022-12-05 22:28:03 +01:00
parent 07502b4ec0
commit 5d6226a4fd
3 changed files with 93 additions and 3 deletions

View File

@@ -10,16 +10,48 @@ declare(strict_types=1);
namespace BitBag\SyliusElasticsearchPlugin\Form\Type;
use BitBag\SyliusElasticsearchPlugin\Controller\RequestDataHandler\DataHandlerInterface;
use BitBag\SyliusElasticsearchPlugin\Facet\RegistryInterface;
use BitBag\SyliusElasticsearchPlugin\QueryBuilder\QueryBuilderInterface;
use FOS\ElasticaBundle\Finder\PaginatedFinderInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Pagerfanta\Adapter\AdapterInterface;
use FOS\ElasticaBundle\Paginator\FantaPaginatorAdapter;
use Elastica\Query;
use Symfony\Component\OptionsResolver\OptionsResolver;
final class ShopProductsFilterType extends AbstractFilterType
{
/** @var string */
private $namePropertyPrefix;
public function __construct(string $namePropertyPrefix)
{
/** @var PaginatedFinderInterface */
private $finder;
/** @var RegistryInterface */
private $facetRegistry;
/** @var QueryBuilderInterface */
private $searchProductsQueryBuilder;
/** @var DataHandlerInterface */
private $shopProductListDataHandler;
public function __construct(
string $namePropertyPrefix,
PaginatedFinderInterface $finder,
RegistryInterface $facetRegistry,
QueryBuilderInterface $searchProductsQueryBuilder,
DataHandlerInterface $shopProductListDataHandler
) {
$this->namePropertyPrefix = $namePropertyPrefix;
$this->finder = $finder;
$this->facetRegistry = $facetRegistry;
$this->searchProductsQueryBuilder = $searchProductsQueryBuilder;
$this->shopProductListDataHandler = $shopProductListDataHandler;
}
public function buildForm(FormBuilderInterface $builder, array $options): void
@@ -29,6 +61,57 @@ final class ShopProductsFilterType extends AbstractFilterType
->add('options', ProductOptionsFilterType::class, ['required' => false, 'label' => false])
->add('attributes', ProductAttributesFilterType::class, ['required' => false, 'label' => false])
->add('price', PriceFilterType::class, ['required' => false, 'label' => false])
;
->setMethod('GET');
$builder->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'resolveFacets']);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'csrf_protection' => false,
]);
}
public function resolveFacets(FormEvent $event): void
{
$query = $this->getQuery($event);
foreach ($this->facetRegistry->getFacets() as $facetId => $facet) {
$query->addAggregation($facet->getAggregation()->setName($facetId));
}
$query->setSize(0);
$results = $this->finder->findPaginated($query);
if ($results->getAdapter()) {
$this->modifyForm($event->getForm(), $results->getAdapter());
}
}
private function getQuery(FormEvent $event): Query
{
$eventData = $event->getData();
if (!isset($eventData[$this->namePropertyPrefix])) {
$eventData[$this->namePropertyPrefix] = '';
}
$data = $this->shopProductListDataHandler->retrieveData($eventData);
return new Query($this->searchProductsQueryBuilder->buildQuery($data));
}
private function modifyForm(FormInterface $form, AdapterInterface $adapter): void
{
if (!$adapter instanceof FantaPaginatorAdapter) {
return;
}
$form->add('facets', SearchFacetsType::class, [
'facets' => $adapter->getAggregations(),
'label' => false
]
);
}
}

View File

@@ -29,6 +29,10 @@
<service id="bitbag_sylius_elasticsearch_plugin.form.type.shop_products_filter" class="BitBag\SyliusElasticsearchPlugin\Form\Type\ShopProductsFilterType">
<argument>%bitbag_es_shop_name_property_prefix%</argument>
<argument type="service" id="fos_elastica.finder.bitbag_shop_product" />
<argument type="service" id="bitbag_sylius_elasticsearch_plugin.facet.taxon_registry" />
<argument type="service" id="bitbag_sylius_elasticsearch_plugin.query_builder.shop_products" />
<argument type="service" id="bitbag_sylius_elasticsearch_plugin.controller.request_data_handler.shop_product_list" />
<tag name="form.type" />
</service>

View File

@@ -7,6 +7,9 @@
<div class="item">
{{ form_row(form.price) }}
</div>
<div class="item">
{{ form_row(form.facets) }}
</div>
<div class="item">
<button type="submit" class="ui primary icon labeled button" style="width: 100%;"><i class="search icon"></i> {{ 'bitbag_sylius_elasticsearch_plugin.ui.filter'|trans }}</button>
</div>