sampart/WhiteOctoberPagerfantaBundle

[RFC] Redirect to last available page strategy

Opened this issue · 4 comments

Koc commented

This is follow up of #60.

I want create redirect to last available page when trying open non-existent page (OutOfRangeCurrentPageException). Currently I've code like this

<?php

namespace Metal\ProjectBundle\Pagerfanta\EventListener;

use Pagerfanta\Exception\NotValidCurrentPageException;
use Pagerfanta\Exception\OutOfRangeCurrentPageException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class HandleOutOfRangeCurrentPage implements EventSubscriberInterface
{
    private $router;

    public function __construct(UrlGeneratorInterface $router)
    {
        $this->router = $router;
    }

    /**
     * @param GetResponseForExceptionEvent $event
     */
    public function onException(GetResponseForExceptionEvent $event)
    {
        $rootException = $exception = $event->getException();

        do {
            if ($exception instanceof OutOfRangeCurrentPageException) {
                preg_match('/"(\d+)"$/', $exception->getMessage(), $matches); // this hack can be easy removed: create field "maxAvailablePage" in exception class
                $maxPage = $matches[1];
                $request = $event->getRequest();
                $url = $this->router->generate(
                    $request->attributes->get('_route'),
                    array_merge(
                        $request->attributes->get('_route_params'),
                        $request->query->all(),
                        array('page' => $maxPage) // we have hardcoded page parameter name here
                    ),
                    true
                );

                $event->setResponse(RedirectResponse::create($url, 301));

                return;
            }

            if ($exception instanceof NotValidCurrentPageException) {
                $event->setException(new NotFoundHttpException('Page Not Found', $rootException));
                return;
            }
        } while ($exception = $exception->getPrevious()); // Twig wraps actual exception into his own
    }

    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::EXCEPTION => array('onException', 512)
        );
    }
}

As you can see from code above, main problem is that we cann't dehardcode parameter for page name. Has anybody any suggestions for how to deal with it?

I think, that we can create method like Form::handleRequest, something like $pagerfanta->handleRequest($request, 'nameOfPageParameter') and then use this parameter on route generation.

A good solution could be setting the max available page to the exception, which should be done on Pagerfanta itself. Would you like to create a PR? :)

Koc commented

I'm can create PR but max available page is not enough. We should to know whan route or query parameter used for page generation.

Aren't they on the request?