View source
<?php
namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
class RouterListener implements EventSubscriberInterface {
private $matcher;
private $context;
private $logger;
private $request;
private $requestStack;
public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null, RequestStack $requestStack = null) {
if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
}
if (null === $context && !$matcher instanceof RequestContextAwareInterface) {
throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.');
}
if (!$requestStack instanceof RequestStack) {
@trigger_error('The ' . __METHOD__ . ' method now requires a RequestStack instance as ' . __CLASS__ . '::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
}
$this->matcher = $matcher;
$this->context = $context ?: $matcher
->getContext();
$this->requestStack = $requestStack;
$this->logger = $logger;
}
public function setRequest(Request $request = null) {
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 2.4 and will be made private in 3.0.', E_USER_DEPRECATED);
$this
->setCurrentRequest($request);
}
private function setCurrentRequest(Request $request = null) {
if (null !== $request && $this->request !== $request) {
$this->context
->fromRequest($request);
}
$this->request = $request;
}
public function onKernelFinishRequest(FinishRequestEvent $event) {
if (null === $this->requestStack) {
return;
}
$this
->setCurrentRequest($this->requestStack
->getParentRequest());
}
public function onKernelRequest(GetResponseEvent $event) {
$request = $event
->getRequest();
if (null !== $this->requestStack) {
$this
->setCurrentRequest($request);
}
if ($request->attributes
->has('_controller')) {
return;
}
try {
if ($this->matcher instanceof RequestMatcherInterface) {
$parameters = $this->matcher
->matchRequest($request);
}
else {
$parameters = $this->matcher
->match($request
->getPathInfo());
}
if (null !== $this->logger) {
$this->logger
->info(sprintf('Matched route "%s".', isset($parameters['_route']) ? $parameters['_route'] : 'n/a'), array(
'route_parameters' => $parameters,
'request_uri' => $request
->getUri(),
));
}
$request->attributes
->add($parameters);
unset($parameters['_route'], $parameters['_controller']);
$request->attributes
->set('_route_params', $parameters);
} catch (ResourceNotFoundException $e) {
$message = sprintf('No route found for "%s %s"', $request
->getMethod(), $request
->getPathInfo());
if ($referer = $request->headers
->get('referer')) {
$message .= sprintf(' (from "%s")', $referer);
}
throw new NotFoundHttpException($message, $e);
} catch (MethodNotAllowedException $e) {
$message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request
->getMethod(), $request
->getPathInfo(), implode(', ', $e
->getAllowedMethods()));
throw new MethodNotAllowedHttpException($e
->getAllowedMethods(), $message, $e);
}
}
public static function getSubscribedEvents() {
return array(
KernelEvents::REQUEST => array(
array(
'onKernelRequest',
32,
),
),
KernelEvents::FINISH_REQUEST => array(
array(
'onKernelFinishRequest',
0,
),
),
);
}
}