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