<?php
namespace Nellapp\Bundle\SDKBundle\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use UnexpectedValueException;
/**
* Invalid KnpPaginator sort params (e.g. "t.createdat" lowercased by a crawler, unknown field,
* array value) throw an UnexpectedValueException from the sortable subscribers/walkers.
* Redirect to the same URL without sort params instead of returning a 500.
*/
class InvalidPaginationSortSubscriber implements EventSubscriberInterface
{
private const SORTABLE_NAMESPACE = 'Knp\\Component\\Pager\\Event\\Subscriber\\Sortable\\';
public static function getSubscribedEvents(): array
{
return [
// Before Sentry (128) and Symfony's ErrorListener (0) so the exception is not reported.
KernelEvents::EXCEPTION => ['onKernelException', 200],
];
}
public function onKernelException(ExceptionEvent $event): void
{
$request = $event->getRequest();
$exception = $event->getThrowable();
if (
!$request->isMethod('GET')
|| !$exception instanceof UnexpectedValueException
|| !$this->isFromSortable($exception)
) {
return;
}
$query = $request->query->all();
unset($query['sort'], $query['direction']);
$event->setResponse(new RedirectResponse(
$request->getBaseUrl() . $request->getPathInfo() . ($query ? '?' . http_build_query($query) : '')
));
$event->stopPropagation();
}
private function isFromSortable(UnexpectedValueException $exception): bool
{
foreach ($exception->getTrace() as $frame) {
if (str_starts_with($frame['class'] ?? '', self::SORTABLE_NAMESPACE)) {
return true;
}
}
return false;
}
}