TwitterBootstrap4PagelessView and PagelessDoctrineORMAdapter implemented to remove unnecessary COUNT() queries.

This commit is contained in:
Alexey Skobkin 2020-04-04 01:03:50 +03:00
parent 9a6b5e258d
commit 8663e9f5d9
No known key found for this signature in database
GPG key ID: 5D5CEF6F221278E7
6 changed files with 125 additions and 5 deletions

View file

@ -1,2 +1,2 @@
white_october_pagerfanta: white_october_pagerfanta:
default_view: twitter_bootstrap4 default_view: twitter_bootstrap4_pageless

View file

@ -48,3 +48,9 @@ services:
Monolog\Processor\PsrLogMessageProcessor: Monolog\Processor\PsrLogMessageProcessor:
tags: { name: monolog.processor, handler: sentry } tags: { name: monolog.processor, handler: sentry }
# Pagerfanta overrides
pagerfanta.view.bootstrap4_pageless:
class: App\Pager\View\TwitterBootstrap4PagelessView
public: false
tags: [{ name: pagerfanta.view, alias: twitter_bootstrap4_pageless }]

View file

@ -4,8 +4,8 @@ namespace App\Api\V1\Controller;
use App\Api\V1\DTO\ListPage; use App\Api\V1\DTO\ListPage;
use App\Magnetico\Entity\Torrent; use App\Magnetico\Entity\Torrent;
use App\Pager\PagelessDoctrineORMAdapter;
use App\Search\TorrentSearcher; use App\Search\TorrentSearcher;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta; use Pagerfanta\Pagerfanta;
use Symfony\Component\HttpFoundation\{JsonResponse, Request}; use Symfony\Component\HttpFoundation\{JsonResponse, Request};
@ -20,9 +20,10 @@ class TorrentController extends AbstractApiController
$orderBy = $request->query->get('order-by'); $orderBy = $request->query->get('order-by');
$order = $request->query->get('order', 'asc'); $order = $request->query->get('order', 'asc');
$pagerAdapter = new DoctrineORMAdapter($searcher->createSearchQueryBuilder($query, $orderBy, $order)); $pagerAdapter = new PagelessDoctrineORMAdapter($searcher->createSearchQueryBuilder($query, $orderBy, $order));
$pager = new Pagerfanta($pagerAdapter); $pager = new Pagerfanta($pagerAdapter);
$pager $pager
->setAllowOutOfRangePages(true)
->setCurrentPage($page) ->setCurrentPage($page)
->setMaxPerPage(self::PER_PAGE) ->setMaxPerPage(self::PER_PAGE)
; ;

View file

@ -4,7 +4,7 @@ namespace App\Controller;
use App\Magnetico\Entity\Torrent; use App\Magnetico\Entity\Torrent;
use App\Search\TorrentSearcher; use App\Search\TorrentSearcher;
use Pagerfanta\Adapter\DoctrineORMAdapter; use App\Pager\PagelessDoctrineORMAdapter;
use Pagerfanta\Pagerfanta; use Pagerfanta\Pagerfanta;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\{Request, Response}; use Symfony\Component\HttpFoundation\{Request, Response};
@ -20,9 +20,10 @@ class TorrentController extends AbstractController
$orderBy = $request->query->get('order-by'); $orderBy = $request->query->get('order-by');
$order = $request->query->get('order', 'asc'); $order = $request->query->get('order', 'asc');
$pagerAdapter = new DoctrineORMAdapter($searcher->createSearchQueryBuilder($query, $orderBy, $order)); $pagerAdapter = new PagelessDoctrineORMAdapter($searcher->createSearchQueryBuilder($query, $orderBy, $order));
$pager = new Pagerfanta($pagerAdapter); $pager = new Pagerfanta($pagerAdapter);
$pager $pager
->setAllowOutOfRangePages(true)
->setCurrentPage($page) ->setCurrentPage($page)
->setMaxPerPage(self::PER_PAGE) ->setMaxPerPage(self::PER_PAGE)
; ;

View file

@ -0,0 +1,16 @@
<?php
namespace App\Pager;
use Pagerfanta\Adapter\DoctrineORMAdapter;
/**
* This adapter don't make COUNT() queries.
*/
class PagelessDoctrineORMAdapter extends DoctrineORMAdapter
{
public function getNbResults()
{
return 1;
}
}

View file

@ -0,0 +1,96 @@
<?php
namespace App\Pager\View;
use Pagerfanta\Pagerfanta;
use Pagerfanta\PagerfantaInterface;
use Pagerfanta\View\Template\TemplateInterface;
use Pagerfanta\View\Template\TwitterBootstrap4Template;
use Pagerfanta\View\ViewInterface;
/**
* Modified TwitterBootstrap4View.
*
* Removes page list and don't disable 'non-existing' pages.
*/
class TwitterBootstrap4PagelessView implements ViewInterface
{
private TemplateInterface $template;
/** @var Pagerfanta */
private PagerfantaInterface $pagerfanta;
private int $currentPage;
public function __construct(TemplateInterface $template = null)
{
$this->template = $template ?: $this->createDefaultTemplate();
}
public function render(PagerfantaInterface $pagerfanta, $routeGenerator, array $options = array())
{
$this->initializePagerfanta($pagerfanta);
$this->configureTemplate($routeGenerator, $options);
return $this->generate();
}
public function getName()
{
return 'twitter_bootstrap4_pageless';
}
protected function createDefaultTemplate()
{
return new TwitterBootstrap4Template();
}
private function initializePagerfanta(PagerfantaInterface $pagerfanta)
{
$this->pagerfanta = $pagerfanta;
$this->currentPage = $pagerfanta->getCurrentPage();
}
private function configureTemplate($routeGenerator, $options)
{
$this->template->setRouteGenerator($routeGenerator);
$this->template->setOptions($options);
}
private function generate()
{
$pages = $this->generatePages();
return $this->generateContainer($pages);
}
private function generateContainer($pages)
{
return str_replace('%pages%', $pages, $this->template->container());
}
private function generatePages()
{
return $this->previous().$this->currentPage().$this->next();
}
private function previous(): string
{
if ($this->currentPage > 1) {
return $this->template->previousEnabled($this->pagerfanta->getPreviousPage());
}
return $this->template->previousDisabled();
}
private function next(): string
{
return $this->template->nextEnabled($this->currentPage + 1);
}
private function currentPage(): string
{
return $this->template->current($this->currentPage);
}
}