3 namespace Drupal\redirect_404\EventSubscriber;
5 use Drupal\Component\Utility\Unicode;
6 use Drupal\Core\Config\ConfigFactoryInterface;
7 use Drupal\Core\Language\LanguageManagerInterface;
8 use Drupal\Core\Path\PathMatcherInterface;
9 use Drupal\redirect_404\RedirectNotFoundStorageInterface;
10 use Drupal\Core\Path\CurrentPathStack;
11 use Symfony\Component\HttpFoundation\RequestStack;
12 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
13 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
14 use Symfony\Component\HttpKernel\KernelEvents;
15 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18 * An EventSubscriber that listens to redirect 404 errors.
20 class Redirect404Subscriber implements EventSubscriberInterface {
25 * @var \Drupal\Core\Path\CurrentPathStack
27 protected $currentPath;
32 * @var \Drupal\Core\Path\PathMatcherInterface
34 protected $pathMatcher;
37 * The request stack (get the URL argument(s) and combined it with the path).
39 * @var \Symfony\Component\HttpFoundation\RequestStack
41 protected $requestStack;
44 * The language manager.
46 * @var \Drupal\Core\Language\LanguageManagerInterface
48 protected $languageManager;
51 * The redirect storage.
53 * @var \Drupal\redirect_404\RedirectNotFoundStorageInterface
55 protected $redirectStorage;
58 * The configuration factory.
60 * @var \Drupal\Core\Config\ConfigFactoryInterface
65 * Constructs a new Redirect404Subscriber.
67 * @param \Drupal\Core\Path\CurrentPathStack $current_path
69 * @param \Drupal\Core\Path\PathMatcherInterface $path_matcher
70 * The path matcher service.
71 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
73 * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
74 * The language manager.
75 * @param \Drupal\redirect_404\RedirectNotFoundStorageInterface $redirect_storage
77 * @param \Drupal\Core\Config\ConfigFactoryInterface $config
78 * The configuration factory.
80 public function __construct(CurrentPathStack $current_path, PathMatcherInterface $path_matcher, RequestStack $request_stack, LanguageManagerInterface $language_manager, RedirectNotFoundStorageInterface $redirect_storage, ConfigFactoryInterface $config) {
81 $this->currentPath = $current_path;
82 $this->pathMatcher = $path_matcher;
83 $this->requestStack = $request_stack;
84 $this->languageManager = $language_manager;
85 $this->redirectStorage = $redirect_storage;
86 $this->config = $config->get('redirect_404.settings');
92 public static function getSubscribedEvents() {
93 $events[KernelEvents::EXCEPTION][] = 'onKernelException';
98 * Logs an exception of 404 Redirect errors.
100 * @param GetResponseForExceptionEvent $event
101 * Is given by the event dispatcher.
103 public function onKernelException(GetResponseForExceptionEvent $event) {
104 // Only log page not found (404) errors.
105 if ($event->getException() instanceof NotFoundHttpException) {
106 $path = $this->currentPath->getPath();
108 // Ignore paths specified in the redirect settings.
109 if ($pages = Unicode::strtolower($this->config->get('pages'))) {
110 // Do not trim a trailing slash if that is the complete path.
111 $path_to_match = $path === '/' ? $path : rtrim($path, '/');
113 if ($this->pathMatcher->matchPath(Unicode::strtolower($path_to_match), $pages)) {
118 // Allow to store paths with arguments.
119 if ($query_string = $this->requestStack->getCurrentRequest()->getQueryString()) {
120 $query_string = '?' . $query_string;
122 $path .= $query_string;
123 $langcode = $this->languageManager->getCurrentLanguage()->getId();
126 $this->redirectStorage->logRequest($path, $langcode);