vendor/friendsofsymfony/elastica-bundle/src/Subscriber/PaginateElasticaQuerySubscriber.php line 33

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the FOSElasticaBundle package.
  4.  *
  5.  * (c) FriendsOfSymfony <https://friendsofsymfony.github.com/>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace FOS\ElasticaBundle\Subscriber;
  11. use FOS\ElasticaBundle\Paginator\PaginatorAdapterInterface;
  12. use FOS\ElasticaBundle\Paginator\PartialResultsInterface;
  13. use Knp\Component\Pager\Event\ItemsEvent;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\RequestStack;
  17. class PaginateElasticaQuerySubscriber implements EventSubscriberInterface
  18. {
  19.     private RequestStack $requestStack;
  20.     public function __construct(RequestStack $requestStack)
  21.     {
  22.         $this->requestStack $requestStack;
  23.     }
  24.     /**
  25.      * @return void
  26.      */
  27.     public function items(ItemsEvent $event)
  28.     {
  29.         if ($event->target instanceof PaginatorAdapterInterface) {
  30.             // Add sort to query
  31.             $this->setSorting($event);
  32.             /** @var PartialResultsInterface $results */
  33.             $results $event->target->getResults($event->getOffset(), $event->getLimit());
  34.             $event->count $results->getTotalHits();
  35.             $event->items $results->toArray();
  36.             $aggregations $results->getAggregations();
  37.             if (null != $aggregations) {
  38.                 $event->setCustomPaginationParameter('aggregations'$aggregations);
  39.             }
  40.             $event->stopPropagation();
  41.         }
  42.     }
  43.     public static function getSubscribedEvents(): array
  44.     {
  45.         return [
  46.             'knp_pager.items' => ['items'1],
  47.         ];
  48.     }
  49.     /**
  50.      * Adds knp paging sort to query.
  51.      *
  52.      * @return void
  53.      */
  54.     protected function setSorting(ItemsEvent $event)
  55.     {
  56.         // Bugfix for PHP 7.4 as options can be null and generate a "Trying to access array offset on value of type null" error
  57.         // @phpstan-ignore-next-line
  58.         $options $event->options ?? [];
  59.         $sortField $this->getFromRequest($options['sortFieldParameterName'] ?? null);
  60.         if (!$sortField && isset($options['defaultSortFieldName'])) {
  61.             $sortField $options['defaultSortFieldName'];
  62.         }
  63.         if (!empty($sortField)) {
  64.             $event->target->getQuery()->setSort([
  65.                 $sortField => $this->getSort($sortField$options),
  66.             ]);
  67.         }
  68.     }
  69.     /**
  70.      * @param string               $sortField
  71.      * @param array<string, mixed> $options
  72.      *
  73.      * @return array<string, mixed>
  74.      */
  75.     protected function getSort($sortField, array $options = [])
  76.     {
  77.         $sort = [
  78.             'order' => $this->getSortDirection($sortField$options),
  79.         ];
  80.         if (isset($options['sortNestedPath'])) {
  81.             $path \is_callable($options['sortNestedPath']) ?
  82.                 $options['sortNestedPath']($sortField) : $options['sortNestedPath'];
  83.             if (!empty($path)) {
  84.                 $sort['nested_path'] = $path;
  85.             }
  86.         }
  87.         if (isset($options['sortNestedFilter'])) {
  88.             $filter \is_callable($options['sortNestedFilter']) ?
  89.                 $options['sortNestedFilter']($sortField) : $options['sortNestedFilter'];
  90.             if (!empty($filter)) {
  91.                 $sort['nested_filter'] = $filter;
  92.             }
  93.         }
  94.         return $sort;
  95.     }
  96.     /**
  97.      * @param string               $sortField
  98.      * @param array<string, mixed> $options
  99.      *
  100.      * @return string
  101.      */
  102.     protected function getSortDirection($sortField, array $options = [])
  103.     {
  104.         $dir 'asc';
  105.         $sortDirection $this->getFromRequest($options['sortDirectionParameterName']);
  106.         if (empty($sortDirection) && isset($options['defaultSortDirection'])) {
  107.             $sortDirection $options['defaultSortDirection'];
  108.         }
  109.         if (null !== $sortDirection && 'desc' === \strtolower($sortDirection)) {
  110.             $dir 'desc';
  111.         }
  112.         // check if the requested sort field is in the sort whitelist
  113.         if (isset($options['sortFieldAllowList']) && !\in_array($sortField$options['sortFieldAllowList'], true)) {
  114.             throw new \UnexpectedValueException(\sprintf('Cannot sort by: [%s] this field is not in whitelist'$sortField));
  115.         }
  116.         return $dir;
  117.     }
  118.     private function getRequest(): ?Request
  119.     {
  120.         return $this->requestStack->getCurrentRequest();
  121.     }
  122.     /**
  123.      * @return mixed|null
  124.      */
  125.     private function getFromRequest(?string $key)
  126.     {
  127.         if (null !== $key && null !== $request $this->getRequest()) {
  128.             return $request->get($key);
  129.         }
  130.         return null;
  131.     }
  132. }