vendor/easycorp/easyadmin-bundle/src/Orm/EntityPaginator.php line 65

Open in your IDE?
  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Orm;
  3. use Doctrine\ORM\Query;
  4. use Doctrine\ORM\QueryBuilder;
  5. use Doctrine\ORM\Tools\Pagination\CountWalker;
  6. use Doctrine\ORM\Tools\Pagination\Paginator;
  7. use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA;
  8. use EasyCorp\Bundle\EasyAdminBundle\Contracts\Orm\EntityPaginatorInterface;
  9. use EasyCorp\Bundle\EasyAdminBundle\Dto\PaginatorDto;
  10. use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
  11. use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
  12. /**
  13.  * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  14.  */
  15. final class EntityPaginator implements EntityPaginatorInterface
  16. {
  17.     private $adminUrlGenerator;
  18.     private $entityFactory;
  19.     private $currentPage;
  20.     private $pageSize;
  21.     private $rangeSize;
  22.     private $rangeEdgeSize;
  23.     private $results;
  24.     private $numResults;
  25.     public function __construct(AdminUrlGenerator $adminUrlGeneratorEntityFactory $entityFactory)
  26.     {
  27.         $this->adminUrlGenerator $adminUrlGenerator;
  28.         $this->entityFactory $entityFactory;
  29.     }
  30.     public function paginate(PaginatorDto $paginatorDtoQueryBuilder $queryBuilder): EntityPaginatorInterface
  31.     {
  32.         $this->pageSize $paginatorDto->getPageSize();
  33.         $this->rangeSize $paginatorDto->getRangeSize();
  34.         $this->rangeEdgeSize $paginatorDto->getRangeEdgeSize();
  35.         $this->currentPage max(1$paginatorDto->getPageNumber());
  36.         $firstResult = ($this->currentPage 1) * $this->pageSize;
  37.         /** @var Query $query */
  38.         $query $queryBuilder
  39.             ->setFirstResult($firstResult)
  40.             ->setMaxResults($this->pageSize)
  41.             ->getQuery();
  42.         if (=== \count($queryBuilder->getDQLPart('join'))) {
  43.             $query->setHint(CountWalker::HINT_DISTINCTfalse);
  44.         }
  45.         $paginator = new Paginator($query$paginatorDto->fetchJoinCollection());
  46.         if (null === $useOutputWalkers $paginatorDto->useOutputWalkers()) {
  47.             $havingPart $queryBuilder->getDQLPart('having');
  48.             if (\is_array($havingPart)) {
  49.                 $useOutputWalkers = \count($havingPart) > 0;
  50.             } else {
  51.                 $useOutputWalkers null !== $havingPart;
  52.             }
  53.         }
  54.         $paginator->setUseOutputWalkers($useOutputWalkers);
  55.         $this->results $paginator->getIterator();
  56.         $this->numResults $paginator->count();
  57.         return $this;
  58.     }
  59.     public function generateUrlForPage(int $page): string
  60.     {
  61.         return $this->adminUrlGenerator->set(EA::PAGE$page)->includeReferrer()->generateUrl();
  62.     }
  63.     public function getCurrentPage(): int
  64.     {
  65.         return $this->currentPage;
  66.     }
  67.     public function getLastPage(): int
  68.     {
  69.         return (int) ceil($this->numResults $this->pageSize);
  70.     }
  71.     /**
  72.      * It returns the closest available pages around the current page.
  73.      * E.g. a paginator with 35 pages, if current page = 1, returns [1, 2, 3, 4, null, 35]
  74.      *      if current page = 18, returns [1, null, 15, 16, 17, 18, 19, 20, 21, null, 35]
  75.      * NULL values mean a gap in the pagination (they can be represented as ellipsis in the templates).
  76.      *
  77.      * This code was inspired by https://github.com/django/django/blob/55fabc53373a8c7ef31d8c4cffd2a07be0a88c2e/django/core/paginator.py#L134
  78.      * (c) Django Project
  79.      *
  80.      * @return int[]
  81.      */
  82.     public function getPageRange(int $pagesOnEachSide nullint $pagesOnEdges null): iterable
  83.     {
  84.         $pagesOnEachSide $pagesOnEachSide ?? $this->rangeSize;
  85.         $pagesOnEdges $pagesOnEdges ?? $this->rangeEdgeSize;
  86.         if (=== $pagesOnEachSide) {
  87.             return null;
  88.         }
  89.         if ($this->getLastPage() <= ($pagesOnEachSide $pagesOnEdges) * 2) {
  90.             return yield from range(1$this->getLastPage());
  91.         }
  92.         if ($this->getCurrentPage() > ($pagesOnEachSide $pagesOnEdges 1)) {
  93.             yield from range(1$pagesOnEdges);
  94.             yield null;
  95.             yield from range($this->getCurrentPage() - $pagesOnEachSide$this->getCurrentPage());
  96.         } else {
  97.             yield from range(1$this->getCurrentPage());
  98.         }
  99.         if ($this->getCurrentPage() < ($this->getLastPage() - $pagesOnEachSide $pagesOnEdges 1)) {
  100.             yield from range($this->getCurrentPage() + 1$this->getCurrentPage() + $pagesOnEachSide);
  101.             yield null;
  102.             yield from range($this->getLastPage() - $pagesOnEdges 1$this->getLastPage());
  103.         } elseif ($this->getCurrentPage() + <= $this->getLastPage()) {
  104.             yield from range($this->getCurrentPage() + 1$this->getLastPage());
  105.         }
  106.     }
  107.     public function getPageSize(): int
  108.     {
  109.         return $this->pageSize;
  110.     }
  111.     public function hasPreviousPage(): bool
  112.     {
  113.         return $this->currentPage 1;
  114.     }
  115.     public function getPreviousPage(): int
  116.     {
  117.         return max(1$this->currentPage 1);
  118.     }
  119.     public function hasNextPage(): bool
  120.     {
  121.         return $this->currentPage $this->getLastPage();
  122.     }
  123.     public function getNextPage(): int
  124.     {
  125.         return min($this->getLastPage(), $this->currentPage 1);
  126.     }
  127.     public function hasToPaginate(): bool
  128.     {
  129.         return $this->numResults $this->pageSize;
  130.     }
  131.     public function isOutOfRange(): bool
  132.     {
  133.         if (=== $this->currentPage) {
  134.             return false;
  135.         }
  136.         return $this->currentPage || $this->currentPage $this->getLastPage();
  137.     }
  138.     public function getNumResults(): int
  139.     {
  140.         return $this->numResults;
  141.     }
  142.     public function getResults(): ?iterable
  143.     {
  144.         return $this->results;
  145.     }
  146.     public function getResultsAsJson(): string
  147.     {
  148.         foreach ($this->getResults() ?? [] as $entityInstance) {
  149.             $entityDto $this->entityFactory->createForEntityInstance($entityInstance);
  150.             $jsonResult['results'][] = [
  151.                 EA::ENTITY_ID => $entityDto->getPrimaryKeyValueAsString(),
  152.                 'entityAsString' => $entityDto->toString(),
  153.             ];
  154.         }
  155.         $nextPageUrl = !$this->hasNextPage() ? null $this->adminUrlGenerator->set(EA::PAGE$this->getNextPage())->removeReferrer()->generateUrl();
  156.         $jsonResult['next_page'] = $nextPageUrl;
  157.         return json_encode($jsonResult);
  158.     }
  159. }