09d61481186c53a2ee7fe1797342eb929ba00003
[yaffs-website] / web / core / lib / Drupal / Core / Routing / Enhancer / ParamConversionEnhancer.php
1 <?php
2
3 namespace Drupal\Core\Routing\Enhancer;
4
5 use Drupal\Core\ParamConverter\ParamConverterManagerInterface;
6 use Drupal\Core\ParamConverter\ParamNotConvertedException;
7 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
8 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
9 use Symfony\Component\HttpFoundation\ParameterBag;
10 use Symfony\Component\HttpFoundation\Request;
11 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
12 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
13 use Symfony\Component\HttpKernel\KernelEvents;
14 use Symfony\Component\Routing\Route;
15
16 /**
17  * Provides a route enhancer that handles parameter conversion.
18  */
19 class ParamConversionEnhancer implements RouteEnhancerInterface, EventSubscriberInterface {
20
21   /**
22    * The parameter conversion manager.
23    *
24    * @var \Drupal\Core\ParamConverter\ParamConverterManagerInterface
25    */
26   protected $paramConverterManager;
27
28   /**
29    * Constructs a new ParamConversionEnhancer.
30    *
31    * @param \Drupal\Core\ParamConverter\ParamConverterManagerInterface $param_converter_manager
32    *   The parameter conversion manager.
33    */
34   public function __construct(ParamConverterManagerInterface $param_converter_manager) {
35     $this->paramConverterManager = $param_converter_manager;
36   }
37
38   /**
39    * {@inheritdoc}
40    */
41   public function enhance(array $defaults, Request $request) {
42     // Just run the parameter conversion once per request.
43     if (!isset($defaults['_raw_variables'])) {
44       $defaults['_raw_variables'] = $this->copyRawVariables($defaults);
45       $defaults = $this->paramConverterManager->convert($defaults);
46     }
47     return $defaults;
48   }
49
50   /**
51    * Store a backup of the raw values that corresponding to the route pattern.
52    *
53    * @param array $defaults
54    *   The route defaults array.
55    *
56    * @return \Symfony\Component\HttpFoundation\ParameterBag
57    */
58   protected function copyRawVariables(array $defaults) {
59     /** @var $route \Symfony\Component\Routing\Route */
60     $route = $defaults[RouteObjectInterface::ROUTE_OBJECT];
61     $variables = array_flip($route->compile()->getVariables());
62     // Foreach will copy the values from the array it iterates. Even if they
63     // are references, use it to break them. This avoids any scenarios where raw
64     // variables also get replaced with converted values.
65     $raw_variables = [];
66     foreach (array_intersect_key($defaults, $variables) as $key => $value) {
67       $raw_variables[$key] = $value;
68     }
69     return new ParameterBag($raw_variables);
70   }
71
72   /**
73    * Catches failed parameter conversions and throw a 404 instead.
74    *
75    * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
76    */
77   public function onException(GetResponseForExceptionEvent $event) {
78     $exception = $event->getException();
79     if ($exception instanceof ParamNotConvertedException) {
80       $event->setException(new NotFoundHttpException($exception->getMessage(), $exception));
81     }
82   }
83
84   /**
85    * {@inheritdoc}
86    */
87   public static function getSubscribedEvents() {
88     $events[KernelEvents::EXCEPTION][] = ['onException', 75];
89     return $events;
90   }
91
92   /**
93    * {@inheritdoc}
94    */
95   public function applies(Route $route) {
96     return TRUE;
97   }
98
99 }