/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php

https://github.com/nattaphat/hgis · PHP · 118 lines · 74 code · 18 blank · 26 comment · 8 complexity · 94c34a4a43b6ffe25017ef8a0cbb9be8 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpKernel\EventListener;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  13. use Symfony\Component\HttpKernel\KernelEvents;
  14. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  15. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  16. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  17. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  18. use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
  19. use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
  20. use Symfony\Component\Routing\RequestContext;
  21. use Symfony\Component\Routing\RequestContextAwareInterface;
  22. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  23. /**
  24. * Initializes the context from the request and sets request attributes based on a matching route.
  25. *
  26. * @author Fabien Potencier <fabien@symfony.com>
  27. */
  28. class RouterListener implements EventSubscriberInterface
  29. {
  30. private $matcher;
  31. private $context;
  32. private $logger;
  33. /**
  34. * Constructor.
  35. *
  36. * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher
  37. * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface)
  38. * @param LoggerInterface|null $logger The logger
  39. *
  40. * @throws \InvalidArgumentException
  41. */
  42. public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null)
  43. {
  44. if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
  45. throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
  46. }
  47. if (null === $context && !$matcher instanceof RequestContextAwareInterface) {
  48. throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.');
  49. }
  50. $this->matcher = $matcher;
  51. $this->context = $context ?: $matcher->getContext();
  52. $this->logger = $logger;
  53. }
  54. public function onKernelRequest(GetResponseEvent $event)
  55. {
  56. $request = $event->getRequest();
  57. // initialize the context that is also used by the generator (assuming matcher and generator share the same context instance)
  58. $this->context->fromRequest($request);
  59. if ($request->attributes->has('_controller')) {
  60. // routing is already done
  61. return;
  62. }
  63. // add attributes based on the request (routing)
  64. try {
  65. // matching a request is more powerful than matching a URL path + context, so try that first
  66. if ($this->matcher instanceof RequestMatcherInterface) {
  67. $parameters = $this->matcher->matchRequest($request);
  68. } else {
  69. $parameters = $this->matcher->match($request->getPathInfo());
  70. }
  71. if (null !== $this->logger) {
  72. $this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->parametersToString($parameters)));
  73. }
  74. $request->attributes->add($parameters);
  75. unset($parameters['_route']);
  76. unset($parameters['_controller']);
  77. $request->attributes->set('_route_params', $parameters);
  78. } catch (ResourceNotFoundException $e) {
  79. $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo());
  80. throw new NotFoundHttpException($message, $e);
  81. } catch (MethodNotAllowedException $e) {
  82. $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), strtoupper(implode(', ', $e->getAllowedMethods())));
  83. throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e);
  84. }
  85. }
  86. private function parametersToString(array $parameters)
  87. {
  88. $pieces = array();
  89. foreach ($parameters as $key => $val) {
  90. $pieces[] = sprintf('"%s": "%s"', $key, (is_string($val) ? $val : json_encode($val)));
  91. }
  92. return implode(', ', $pieces);
  93. }
  94. public static function getSubscribedEvents()
  95. {
  96. return array(
  97. KernelEvents::REQUEST => array(array('onKernelRequest', 32)),
  98. );
  99. }
  100. }