src/Search/Request/Taxon.php line 158

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Monsieur Biz' Search plugin for Sylius.
  4.  *
  5.  * (c) Monsieur Biz <sylius@monsieurbiz.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE.txt
  8.  * file that was distributed with this source code.
  9.  */
  10. declare(strict_types=1);
  11. namespace App\Search\Request;
  12. use App\Repository\Brand\BrandRepository;
  13. use Elastica\Query;
  14. use Elastica\QueryBuilder;
  15. use MonsieurBiz\SyliusSearchPlugin\Model\Documentable\DocumentableInterface;
  16. use MonsieurBiz\SyliusSearchPlugin\Repository\ProductAttributeRepositoryInterface;
  17. use MonsieurBiz\SyliusSearchPlugin\Repository\ProductOptionRepositoryInterface;
  18. use MonsieurBiz\SyliusSearchPlugin\Search\Request\AggregationBuilder;
  19. use MonsieurBiz\SyliusSearchPlugin\Search\Request\FunctionScore\FunctionScoreRegistryInterface;
  20. use MonsieurBiz\SyliusSearchPlugin\Search\Request\PostFilter\PostFilterRegistryInterface;
  21. use MonsieurBiz\SyliusSearchPlugin\Search\Request\QueryFilter\QueryFilterRegistryInterface;
  22. use MonsieurBiz\SyliusSearchPlugin\Search\Request\RequestConfiguration;
  23. use MonsieurBiz\SyliusSearchPlugin\Search\Request\RequestInterface;
  24. use MonsieurBiz\SyliusSearchPlugin\Search\Request\Sorting\SorterRegistryInterface;
  25. use RuntimeException;
  26. use Sylius\Component\Channel\Context\ChannelContextInterface;
  27. use Sylius\Component\Registry\ServiceRegistryInterface;
  28. final class Taxon implements RequestInterface
  29. {
  30.     private DocumentableInterface $documentable;
  31.     private ProductAttributeRepositoryInterface $productAttributeRepository;
  32.     private ProductOptionRepositoryInterface $productOptionRepository;
  33.     private ChannelContextInterface $channelContext;
  34.     private AggregationBuilder $aggregationBuilder;
  35.     private ?RequestConfiguration $configuration;
  36.     private QueryFilterRegistryInterface $queryFilterRegistry;
  37.     private PostFilterRegistryInterface $postFilterRegistry;
  38.     private SorterRegistryInterface $sorterRegistry;
  39.     private FunctionScoreRegistryInterface $functionScoreRegistry;
  40.     /** @var BrandRepository */
  41.     private $brandRepository;
  42.     public function __construct(
  43.         ServiceRegistryInterface $documentableRegistry,
  44.         ProductAttributeRepositoryInterface $productAttributeRepository,
  45.         ProductOptionRepositoryInterface $productOptionRepository,
  46.         BrandRepository $brandRepository,
  47.         ChannelContextInterface $channelContext,
  48.         AggregationBuilder $aggregationBuilder,
  49.         QueryFilterRegistryInterface $queryFilterRegistry,
  50.         PostFilterRegistryInterface $postFilterRegistry,
  51.         SorterRegistryInterface $sorterRegistry,
  52.         FunctionScoreRegistryInterface $functionScoreRegistry
  53.     ) {
  54.         /** @var DocumentableInterface $documentable */
  55.         $documentable $documentableRegistry->get('search.documentable.monsieurbiz_product');
  56.         $this->documentable $documentable;
  57.         $this->productAttributeRepository $productAttributeRepository;
  58.         $this->productOptionRepository $productOptionRepository;
  59.         $this->brandRepository $brandRepository;
  60.         $this->channelContext $channelContext;
  61.         $this->aggregationBuilder $aggregationBuilder;
  62.         $this->queryFilterRegistry $queryFilterRegistry;
  63.         $this->postFilterRegistry $postFilterRegistry;
  64.         $this->sorterRegistry $sorterRegistry;
  65.         $this->functionScoreRegistry $functionScoreRegistry;
  66.     }
  67.     public function getType(): string
  68.     {
  69.         return RequestInterface::TAXON_TYPE;
  70.     }
  71.     public function getDocumentable(): DocumentableInterface
  72.     {
  73.         return $this->documentable;
  74.     }
  75.     public function getQuery(): Query
  76.     {
  77.         $qb = new QueryBuilder();
  78.         $boolQuery $qb->query()->bool();
  79.         foreach ($this->queryFilterRegistry->all() as $queryFilter) {
  80.             $queryFilter->apply($boolQuery$this->configuration);
  81.         }
  82.         $query Query::create($boolQuery);
  83.         $postFilter = new Query\BoolQuery();
  84.         foreach ($this->postFilterRegistry->all() as $postFilterApplier) {
  85.             $postFilterApplier->apply($postFilter$this->configuration);
  86.         }
  87.         $query->setPostFilter($postFilter);
  88.         $this->addAggregations($query$postFilter);
  89.         foreach ($this->sorterRegistry->all() as $sorter) {
  90.             $sorter->apply($query$this->configuration);
  91.         }
  92.         /** @var Query\AbstractQuery $queryObject */
  93.         $queryObject $query->getQuery();
  94.         $functionScore $qb->query()->function_score()
  95.             ->setQuery($queryObject)
  96.             ->setBoostMode(Query\FunctionScore::BOOST_MODE_MULTIPLY)
  97.             ->setScoreMode(Query\FunctionScore::SCORE_MODE_MULTIPLY)
  98.         ;
  99.         foreach ($this->functionScoreRegistry->all() as $functionScoreClass) {
  100.             $functionScoreClass->addFunctionScore($functionScore$this->configuration);
  101.         }
  102.         $query->setQuery($functionScore);
  103.         return $query;
  104.     }
  105.     public function supports(string $typestring $documentableCode): bool
  106.     {
  107.         return RequestInterface::TAXON_TYPE === $type && $documentableCode === $this->getDocumentable()->getIndexCode();
  108.     }
  109.     public function setConfiguration(RequestConfiguration $configuration): void
  110.     {
  111.         $this->configuration $configuration;
  112.     }
  113.     private function addAggregations(Query $queryQuery\BoolQuery $postFilter): void
  114.     {
  115.         if (null === $this->configuration) {
  116.             throw new RuntimeException('Missing request configuration');
  117.         }
  118.         $aggregations $this->aggregationBuilder->buildAggregations(
  119.             [
  120.                 ['taxons' => $this->configuration->getTaxon()],
  121.                 'price',
  122.                 $this->productAttributeRepository->findIsSearchableOrFilterable(),
  123.                 $this->productOptionRepository->findIsSearchableOrFilterable(),
  124.                 'brand',
  125.             ],
  126.             $postFilter->hasParam('must') ? $postFilter->getParam('must') : []
  127.         );
  128.         foreach ($aggregations as $aggregation) {
  129.             $query->addAggregation($aggregation);
  130.         }
  131.     }
  132. }