<?php
namespace App\Event;
use ApiPlatform\Core\DataProvider\PaginatorInterface;
use ApiPlatform\Core\DataProvider\PartialPaginatorInterface;
use ApiPlatform\Core\Util\IriHelper;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\WebLink\GenericLinkProvider;
use Symfony\Component\WebLink\Link;
class PaginationHeadersListener implements EventSubscriberInterface
{
private $paginationParameterName;
public function __construct(string $paginationParameterName = 'page')
{
$this->paginationParameterName = $paginationParameterName;
}
public function onKernelResponse(ResponseEvent $event): void
{
if (HttpKernelInterface::MAIN_REQUEST !== $event->getRequestType()) {
return;
}
$request = $event->getRequest();
$response = $event->getResponse();
$data = $request->attributes->get('data');
if (!$data instanceof PartialPaginatorInterface) {
return;
}
$currentPage = (int) $data->getCurrentPage();
$response->headers->set('Pagination-Current-Page', $currentPage);
$response->headers->set('Pagination-Items-Per-Page', (int) $data->getItemsPerPage());
if (!$data instanceof PaginatorInterface) {
return;
}
$response->headers->set('X-Total-Count', $data->getTotalItems());
$lastPage = (int) $data->getLastPage();
$response->headers->set('Pagination-Last-Page', $lastPage);
$response->headers->set('Pagination-Total-Items', (int) $data->getTotalItems());
$linkProvider = $request->attributes->get('_links', new GenericLinkProvider());
foreach ($this->collectLinks($request, $currentPage, $lastPage) as $rel => $url) {
$linkProvider = $linkProvider->withLink(new Link($rel, $url));
}
$request->attributes->set('_links', $linkProvider);
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => ['onKernelResponse'],
];
}
private function collectLinks(Request $request, int $currentPage, int $lastPage): array
{
$links = [];
$parsed = IriHelper::parseIri($request->getUri(), $this->paginationParameterName);
$links['first'] = IriHelper::createIri($parsed['parts'], $parsed['parameters'], $this->paginationParameterName, 1);
$links['last'] = IriHelper::createIri($parsed['parts'], $parsed['parameters'], $this->paginationParameterName, $lastPage);
if (1 !== $currentPage) {
$links['prev'] = IriHelper::createIri($parsed['parts'], $parsed['parameters'], $this->paginationParameterName, $currentPage - 1);
}
if ($currentPage !== $lastPage) {
$links['next'] = IriHelper::createIri($parsed['parts'], $parsed['parameters'], $this->paginationParameterName, $currentPage + 1);
}
return $links;
}
}