Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / redirect / src / EventSubscriber / RedirectRequestSubscriber.php
1 <?php
2
3 namespace Drupal\redirect\EventSubscriber;
4
5 use Drupal\Core\Cache\CacheableMetadata;
6 use Drupal\Core\Config\ConfigFactoryInterface;
7 use Drupal\Core\Entity\EntityManagerInterface;
8 use Drupal\Core\Extension\ModuleHandlerInterface;
9 use Drupal\Core\Language\LanguageManagerInterface;
10 use Drupal\Core\Logger\RfcLogLevel;
11 use Drupal\Core\Path\AliasManagerInterface;
12 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
13 use Drupal\Core\Routing\TrustedRedirectResponse;
14 use Drupal\Core\Url;
15 use Drupal\redirect\Exception\RedirectLoopException;
16 use Drupal\redirect\RedirectChecker;
17 use Drupal\redirect\RedirectRepository;
18 use Symfony\Component\HttpFoundation\Response;
19 use Symfony\Component\HttpKernel\HttpKernelInterface;
20 use Symfony\Component\HttpKernel\KernelEvents;
21 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
22 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
23 use Symfony\Component\Routing\RequestContext;
24
25 /**
26  * Redirect subscriber for controller requests.
27  */
28 class RedirectRequestSubscriber implements EventSubscriberInterface {
29
30   /** @var  \Drupal\redirect\RedirectRepository */
31   protected $redirectRepository;
32
33   /**
34    * @var \Drupal\Core\Language\LanguageManagerInterface
35    */
36   protected $languageManager;
37
38   /**
39    * @var \Drupal\Core\Config\Config
40    */
41   protected $config;
42
43   /**
44    * @var \Drupal\Core\Path\AliasManager
45    */
46   protected $aliasManager;
47
48   /**
49    * @var \Drupal\Core\Extension\ModuleHandlerInterface
50    */
51   protected $moduleHandler;
52
53   /**
54    * @var \Drupal\Core\Entity\EntityManagerInterface
55    */
56   protected $entityManager;
57
58   /**
59    * @var \Drupal\redirect\RedirectChecker
60    */
61   protected $checker;
62
63   /**
64    * @var \Symfony\Component\Routing\RequestContext
65    */
66   protected $context;
67
68   /**
69    * A path processor manager for resolving the system path.
70    *
71    * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface
72    */
73   protected $pathProcessor;
74
75   /**
76    * Constructs a \Drupal\redirect\EventSubscriber\RedirectRequestSubscriber object.
77    *
78    * @param \Drupal\redirect\RedirectRepository $redirect_repository
79    *   The redirect entity repository.
80    * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
81    *   The language manager service.
82    * @param \Drupal\Core\Config\ConfigFactoryInterface $config
83    *   The config.
84    * @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
85    *   The alias manager service.
86    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
87    *   The module handler service.
88    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
89    *   The entity manager service.
90    * @param \Drupal\redirect\RedirectChecker $checker
91    *   The redirect checker service.
92    * @param \Symfony\Component\Routing\RequestContext
93    *   Request context.
94    */
95   public function __construct(RedirectRepository $redirect_repository, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config, AliasManagerInterface $alias_manager, ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager, RedirectChecker $checker, RequestContext $context, InboundPathProcessorInterface $path_processor) {
96     $this->redirectRepository = $redirect_repository;
97     $this->languageManager = $language_manager;
98     $this->config = $config->get('redirect.settings');
99     $this->aliasManager = $alias_manager;
100     $this->moduleHandler = $module_handler;
101     $this->entityManager = $entity_manager;
102     $this->checker = $checker;
103     $this->context = $context;
104     $this->pathProcessor = $path_processor;
105   }
106
107   /**
108    * Handles the redirect if any found.
109    *
110    * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
111    *   The event to process.
112    */
113   public function onKernelRequestCheckRedirect(GetResponseEvent $event) {
114     // Get a clone of the request. During inbound processing the request
115     // can be altered. Allowing this here can lead to unexpected behavior.
116     // For example the path_processor.files inbound processor provided by
117     // the system module alters both the path and the request; only the
118     // changes to the request will be propagated, while the change to the
119     // path will be lost.
120     $request = clone $event->getRequest();
121
122     if (!$this->checker->canRedirect($request)) {
123       return;
124     }
125
126     // Get URL info and process it to be used for hash generation.
127     parse_str($request->getQueryString(), $request_query);
128
129     if (strpos($request->getPathInfo(), '/system/files/') === 0 && !$request->query->has('file')) {
130       // Private files paths are split by the inbound path processor and the
131       // relative file path is moved to the 'file' query string parameter. This
132       // is because the route system does not allow an arbitrary amount of
133       // parameters. We preserve the path as is returned by the request object.
134       // @see \Drupal\system\PathProcessor\PathProcessorFiles::processInbound()
135       $path = $request->getPathInfo();
136     }
137     else {
138       // Do the inbound processing so that for example language prefixes are
139       // removed.
140       $path = $this->pathProcessor->processInbound($request->getPathInfo(), $request);
141     }
142     $path = trim($path, '/');
143
144     $this->context->fromRequest($request);
145
146     try {
147       $redirect = $this->redirectRepository->findMatchingRedirect($path, $request_query, $this->languageManager->getCurrentLanguage()->getId());
148     }
149     catch (RedirectLoopException $e) {
150       \Drupal::logger('redirect')->warning($e->getMessage());
151       $response = new Response();
152       $response->setStatusCode(503);
153       $response->setContent('Service unavailable');
154       $event->setResponse($response);
155       return;
156     }
157
158     if (!empty($redirect)) {
159
160       // Handle internal path.
161       $url = $redirect->getRedirectUrl();
162       if ($this->config->get('passthrough_querystring')) {
163         $url->setOption('query', (array) $url->getOption('query') + $request_query);
164       }
165       $headers = [
166         'X-Redirect-ID' => $redirect->id(),
167       ];
168       $response = new TrustedRedirectResponse($url->setAbsolute()->toString(), $redirect->getStatusCode(), $headers);
169       $response->addCacheableDependency($redirect);
170       $event->setResponse($response);
171     }
172   }
173
174   /**
175    * Prior to set the response it check if we can redirect.
176    *
177    * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
178    *   The event object.
179    * @param \Drupal\Core\Url $url
180    *   The Url where we want to redirect.
181    */
182   protected function setResponse(GetResponseEvent $event, Url $url) {
183     $request = $event->getRequest();
184     $this->context->fromRequest($request);
185
186     parse_str($request->getQueryString(), $query);
187     $url->setOption('query', $query);
188     $url->setAbsolute(TRUE);
189
190     // We can only check access for routed URLs.
191     if (!$url->isRouted() || $this->checker->canRedirect($request, $url->getRouteName())) {
192       // Add the 'rendered' cache tag, so that we can invalidate all responses
193       // when settings are changed.
194       $response = new TrustedRedirectResponse($url->toString(), 301);
195       $response->addCacheableDependency(CacheableMetadata::createFromRenderArray([])->addCacheTags(['rendered']));
196       $event->setResponse($response);
197     }
198   }
199
200   /**
201    * {@inheritdoc}
202    */
203   public static function getSubscribedEvents() {
204     // This needs to run before RouterListener::onKernelRequest(), which has
205     // a priority of 32. Otherwise, that aborts the request if no matching
206     // route is found.
207     $events[KernelEvents::REQUEST][] = array('onKernelRequestCheckRedirect', 33);
208     return $events;
209   }
210
211 }