Version 1
[yaffs-website] / web / core / lib / Drupal / Core / EventSubscriber / CustomPageExceptionHtmlSubscriber.php
1 <?php
2
3 namespace Drupal\Core\EventSubscriber;
4
5 use Drupal\Core\Access\AccessManagerInterface;
6 use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
7 use Drupal\Core\Config\ConfigFactoryInterface;
8 use Drupal\Core\Routing\AccessAwareRouterInterface;
9 use Drupal\Core\Routing\RedirectDestinationInterface;
10 use Drupal\Core\Url;
11 use Psr\Log\LoggerInterface;
12 use Symfony\Component\HttpFoundation\Response;
13 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
14 use Symfony\Component\HttpKernel\HttpKernelInterface;
15 use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
16
17 /**
18  * Exception subscriber for handling core custom HTML error pages.
19  */
20 class CustomPageExceptionHtmlSubscriber extends DefaultExceptionHtmlSubscriber {
21
22   /**
23    * The configuration factory.
24    *
25    * @var \Drupal\Core\Config\ConfigFactoryInterface
26    */
27   protected $configFactory;
28
29   /**
30    * The access manager.
31    *
32    * @var \Drupal\Core\Access\AccessManagerInterface
33    */
34   protected $accessManager;
35
36   /**
37    * Constructs a new CustomPageExceptionHtmlSubscriber.
38    *
39    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
40    *   The configuration factory.
41    * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
42    *   The HTTP Kernel service.
43    * @param \Psr\Log\LoggerInterface $logger
44    *   The logger service.
45    * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
46    *   The redirect destination service.
47    * @param \Symfony\Component\Routing\Matcher\UrlMatcherInterface $access_unaware_router
48    *   A router implementation which does not check access.
49    * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
50    *   The access manager.
51    */
52   public function __construct(ConfigFactoryInterface $config_factory, HttpKernelInterface $http_kernel, LoggerInterface $logger, RedirectDestinationInterface $redirect_destination, UrlMatcherInterface $access_unaware_router, AccessManagerInterface $access_manager) {
53     parent::__construct($http_kernel, $logger, $redirect_destination, $access_unaware_router);
54     $this->configFactory = $config_factory;
55     $this->accessManager = $access_manager;
56   }
57
58   /**
59    * {@inheritdoc}
60    */
61   protected static function getPriority() {
62     return -50;
63   }
64
65   /**
66    * {@inheritdoc}
67    */
68   public function on403(GetResponseForExceptionEvent $event) {
69     $custom_403_path = $this->configFactory->get('system.site')->get('page.403');
70     if (!empty($custom_403_path)) {
71       $this->makeSubrequestToCustomPath($event, $custom_403_path, Response::HTTP_FORBIDDEN);
72     }
73   }
74
75   /**
76    * {@inheritdoc}
77    */
78   public function on404(GetResponseForExceptionEvent $event) {
79     $custom_404_path = $this->configFactory->get('system.site')->get('page.404');
80     if (!empty($custom_404_path)) {
81       $this->makeSubrequestToCustomPath($event, $custom_404_path, Response::HTTP_NOT_FOUND);
82     }
83   }
84
85   /**
86    * Makes a subrequest to retrieve the custom error page.
87    *
88    * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
89    *   The event to process.
90    * @param string $custom_path
91    *   The custom path to which to make a subrequest for this error message.
92    * @param int $status_code
93    *   The status code for the error being handled.
94    */
95   protected function makeSubrequestToCustomPath(GetResponseForExceptionEvent $event, $custom_path, $status_code) {
96     $url = Url::fromUserInput($custom_path);
97     if ($url->isRouted()) {
98       $access_result = $this->accessManager->checkNamedRoute($url->getRouteName(), $url->getRouteParameters(), NULL, TRUE);
99       $request = $event->getRequest();
100
101       // Merge the custom path's route's access result's cacheability metadata
102       // with the existing one (from the master request), otherwise create it.
103       if (!$request->attributes->has(AccessAwareRouterInterface::ACCESS_RESULT)) {
104         $request->attributes->set(AccessAwareRouterInterface::ACCESS_RESULT, $access_result);
105       }
106       else {
107         $existing_access_result = $request->attributes->get(AccessAwareRouterInterface::ACCESS_RESULT);
108         if ($existing_access_result instanceof RefinableCacheableDependencyInterface) {
109           $existing_access_result->addCacheableDependency($access_result);
110         }
111       }
112
113       // Only perform the subrequest if the custom path is actually accessible.
114       if (!$access_result->isAllowed()) {
115         return;
116       }
117     }
118
119     $this->makeSubrequest($event, $custom_path, $status_code);
120   }
121
122 }