3 namespace Drupal\Core\Routing\Enhancer;
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;
17 * Provides a route enhancer that handles parameter conversion.
19 class ParamConversionEnhancer implements RouteEnhancerInterface, EventSubscriberInterface {
22 * The parameter conversion manager.
24 * @var \Drupal\Core\ParamConverter\ParamConverterManagerInterface
26 protected $paramConverterManager;
29 * Constructs a new ParamConversionEnhancer.
31 * @param \Drupal\Core\ParamConverter\ParamConverterManagerInterface $param_converter_manager
32 * The parameter conversion manager.
34 public function __construct(ParamConverterManagerInterface $param_converter_manager) {
35 $this->paramConverterManager = $param_converter_manager;
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);
51 * Store a backup of the raw values that corresponding to the route pattern.
53 * @param array $defaults
54 * The route defaults array.
56 * @return \Symfony\Component\HttpFoundation\ParameterBag
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.
66 foreach (array_intersect_key($defaults, $variables) as $key => $value) {
67 $raw_variables[$key] = $value;
69 return new ParameterBag($raw_variables);
73 * Catches failed parameter conversions and throw a 404 instead.
75 * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
77 public function onException(GetResponseForExceptionEvent $event) {
78 $exception = $event->getException();
79 if ($exception instanceof ParamNotConvertedException) {
80 $event->setException(new NotFoundHttpException($exception->getMessage(), $exception));
87 public static function getSubscribedEvents() {
88 $events[KernelEvents::EXCEPTION][] = ['onException', 75];
95 public function applies(Route $route) {