WhiteOctoberPagerfantaBundle icon indicating copy to clipboard operation
WhiteOctoberPagerfantaBundle copied to clipboard

[RFC] Redirect to last available page strategy

Open Koc opened this issue 11 years ago • 4 comments

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.

Koc avatar Sep 15 '14 10:09 Koc

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? :)

pablodip avatar Sep 17 '14 19:09 pablodip

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.

Koc avatar Sep 19 '14 09:09 Koc

Aren't they on the request?

pablodip avatar Sep 19 '14 15:09 pablodip

As you see it can be customized https://github.com/whiteoctober/WhiteOctoberPagerfantaBundle/blob/master/Twig/PagerfantaExtension.php#L105

Koc avatar Sep 19 '14 15:09 Koc