class RedirectRequestSubscriber in Redirect 8
Redirect subscriber for controller requests.
Hierarchy
- class \Drupal\redirect\EventSubscriber\RedirectRequestSubscriber implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
Expanded class hierarchy of RedirectRequestSubscriber
1 file declares its use of RedirectRequestSubscriber
- RedirectRequestSubscriberTest.php in tests/
src/ Unit/ RedirectRequestSubscriberTest.php
1 string reference to 'RedirectRequestSubscriber'
1 service uses RedirectRequestSubscriber
File
- src/
EventSubscriber/ RedirectRequestSubscriber.php, line 26
Namespace
Drupal\redirect\EventSubscriberView source
class RedirectRequestSubscriber implements EventSubscriberInterface {
/** @var \Drupal\redirect\RedirectRepository */
protected $redirectRepository;
/**
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* @var \Drupal\Core\Config\Config
*/
protected $config;
/**
* @var \Drupal\path_alias\AliasManagerInterface
*/
protected $aliasManager;
/**
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* @var \Drupal\redirect\RedirectChecker
*/
protected $checker;
/**
* @var \Symfony\Component\Routing\RequestContext
*/
protected $context;
/**
* A path processor manager for resolving the system path.
*
* @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface
*/
protected $pathProcessor;
/**
* Constructs a \Drupal\redirect\EventSubscriber\RedirectRequestSubscriber object.
*
* @param \Drupal\redirect\RedirectRepository $redirect_repository
* The redirect entity repository.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config
* The config.
* @param \Drupal\path_alias\AliasManagerInterface $alias_manager
* The alias manager service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\redirect\RedirectChecker $checker
* The redirect checker service.
* @param \Symfony\Component\Routing\RequestContext
* Request context.
*/
public function __construct(RedirectRepository $redirect_repository, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config, AliasManagerInterface $alias_manager, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager, RedirectChecker $checker, RequestContext $context, InboundPathProcessorInterface $path_processor) {
$this->redirectRepository = $redirect_repository;
$this->languageManager = $language_manager;
$this->config = $config
->get('redirect.settings');
$this->aliasManager = $alias_manager;
$this->moduleHandler = $module_handler;
$this->entityTypeManager = $entity_type_manager;
$this->checker = $checker;
$this->context = $context;
$this->pathProcessor = $path_processor;
}
/**
* Handles the redirect if any found.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* The event to process.
*/
public function onKernelRequestCheckRedirect(GetResponseEvent $event) {
// Get a clone of the request. During inbound processing the request
// can be altered. Allowing this here can lead to unexpected behavior.
// For example the path_processor.files inbound processor provided by
// the system module alters both the path and the request; only the
// changes to the request will be propagated, while the change to the
// path will be lost.
$request = clone $event
->getRequest();
if (!$this->checker
->canRedirect($request)) {
return;
}
// Get URL info and process it to be used for hash generation.
parse_str($request
->getQueryString(), $request_query);
if (strpos($request
->getPathInfo(), '/system/files/') === 0 && !$request->query
->has('file')) {
// Private files paths are split by the inbound path processor and the
// relative file path is moved to the 'file' query string parameter. This
// is because the route system does not allow an arbitrary amount of
// parameters. We preserve the path as is returned by the request object.
// @see \Drupal\system\PathProcessor\PathProcessorFiles::processInbound()
$path = $request
->getPathInfo();
}
else {
// Do the inbound processing so that for example language prefixes are
// removed.
$path = $this->pathProcessor
->processInbound($request
->getPathInfo(), $request);
}
$path = trim($path, '/');
$this->context
->fromRequest($request);
try {
$redirect = $this->redirectRepository
->findMatchingRedirect($path, $request_query, $this->languageManager
->getCurrentLanguage()
->getId());
} catch (RedirectLoopException $e) {
\Drupal::logger('redirect')
->warning('Redirect loop identified at %path for redirect %rid', [
'%path' => $e
->getPath(),
'%rid' => $e
->getRedirectId(),
]);
$response = new Response();
$response
->setStatusCode(503);
$response
->setContent('Service unavailable');
$event
->setResponse($response);
return;
}
if (!empty($redirect)) {
// Handle internal path.
$url = $redirect
->getRedirectUrl();
if ($this->config
->get('passthrough_querystring')) {
$url
->setOption('query', (array) $url
->getOption('query') + $request_query);
}
$headers = [
'X-Redirect-ID' => $redirect
->id(),
];
$response = new TrustedRedirectResponse($url
->setAbsolute()
->toString(), $redirect
->getStatusCode(), $headers);
$response
->addCacheableDependency($redirect);
$event
->setResponse($response);
}
}
/**
* Prior to set the response it check if we can redirect.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* The event object.
* @param \Drupal\Core\Url $url
* The Url where we want to redirect.
*/
protected function setResponse(GetResponseEvent $event, Url $url) {
$request = $event
->getRequest();
$this->context
->fromRequest($request);
parse_str($request
->getQueryString(), $query);
$url
->setOption('query', $query);
$url
->setAbsolute(TRUE);
// We can only check access for routed URLs.
if (!$url
->isRouted() || $this->checker
->canRedirect($request, $url
->getRouteName())) {
// Add the 'rendered' cache tag, so that we can invalidate all responses
// when settings are changed.
$response = new TrustedRedirectResponse($url
->toString(), 301);
$response
->addCacheableDependency(CacheableMetadata::createFromRenderArray([])
->addCacheTags([
'rendered',
]));
$event
->setResponse($response);
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
// This needs to run before RouterListener::onKernelRequest(), which has
// a priority of 32. Otherwise, that aborts the request if no matching
// route is found.
$events[KernelEvents::REQUEST][] = [
'onKernelRequestCheckRedirect',
33,
];
return $events;
}
}