Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\EventSubscriber;
|
Chris@0
|
4
|
Chris@0
|
5 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
Chris@0
|
6 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
Chris@0
|
7 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
Chris@0
|
8 use Symfony\Component\HttpKernel\KernelEvents;
|
Chris@0
|
9
|
Chris@0
|
10 /**
|
Chris@0
|
11 * Utility base class for exception subscribers.
|
Chris@0
|
12 *
|
Chris@0
|
13 * A subscriber may extend this class and implement getHandledFormats() to
|
Chris@0
|
14 * indicate which request formats it will respond to. Then implement an on*()
|
Chris@0
|
15 * method for any error code (HTTP response code) that should be handled. For
|
Chris@0
|
16 * example, to handle a specific error code like 404 Not Found messages add the
|
Chris@0
|
17 * method:
|
Chris@0
|
18 *
|
Chris@0
|
19 * @code
|
Chris@0
|
20 * public function on404(GetResponseForExceptionEvent $event) {}
|
Chris@0
|
21 * @endcode
|
Chris@0
|
22 *
|
Chris@0
|
23 * To implement a fallback for the entire 4xx class of codes, implement the
|
Chris@0
|
24 * method:
|
Chris@0
|
25 *
|
Chris@0
|
26 * @code
|
Chris@0
|
27 * public function on4xx(GetResponseForExceptionEvent $event) {}
|
Chris@0
|
28 * @endcode
|
Chris@0
|
29 *
|
Chris@0
|
30 * That method should then call $event->setResponse() to set the response object
|
Chris@0
|
31 * for the exception. Alternatively, it may opt not to do so and then other
|
Chris@0
|
32 * listeners will have the opportunity to handle the exception.
|
Chris@0
|
33 *
|
Chris@0
|
34 * Note: Core provides several important exception listeners by default. In most
|
Chris@0
|
35 * cases, setting the priority of a contrib listener to the default of 0 will
|
Chris@0
|
36 * do what you expect and handle the exceptions you'd expect it to handle.
|
Chris@0
|
37 * If a custom priority is set, be aware of the following core-registered
|
Chris@0
|
38 * listeners.
|
Chris@0
|
39 *
|
Chris@0
|
40 * - Fast404ExceptionHtmlSubscriber: 200. This subscriber will return a
|
Chris@0
|
41 * minimalist, high-performance 404 page for HTML requests. It is not
|
Chris@0
|
42 * recommended to have a priority higher than this one as it will only slow
|
Chris@0
|
43 * down that use case.
|
Chris@0
|
44 * - ExceptionLoggingSubscriber: 50. This subscriber logs all exceptions but
|
Chris@0
|
45 * does not handle them. Do not register a listener with a higher priority
|
Chris@0
|
46 * unless you want exceptions to not get logged, which makes debugging more
|
Chris@0
|
47 * difficult.
|
Chris@0
|
48 * - DefaultExceptionSubscriber: -256. The subscriber of last resort, this will
|
Chris@0
|
49 * provide generic handling for any exception. A listener with a lower
|
Chris@0
|
50 * priority will never get called.
|
Chris@0
|
51 *
|
Chris@0
|
52 * All other core-provided exception handlers have negative priorities so most
|
Chris@0
|
53 * module-provided listeners will naturally take precedence over them.
|
Chris@0
|
54 */
|
Chris@0
|
55 abstract class HttpExceptionSubscriberBase implements EventSubscriberInterface {
|
Chris@0
|
56
|
Chris@0
|
57 /**
|
Chris@0
|
58 * Specifies the request formats this subscriber will respond to.
|
Chris@0
|
59 *
|
Chris@0
|
60 * @return array
|
Chris@0
|
61 * An indexed array of the format machine names that this subscriber will
|
Chris@0
|
62 * attempt to process, such as "html" or "json". Returning an empty array
|
Chris@0
|
63 * will apply to all formats.
|
Chris@0
|
64 *
|
Chris@0
|
65 * @see \Symfony\Component\HttpFoundation\Request
|
Chris@0
|
66 */
|
Chris@0
|
67 abstract protected function getHandledFormats();
|
Chris@0
|
68
|
Chris@0
|
69 /**
|
Chris@0
|
70 * Specifies the priority of all listeners in this class.
|
Chris@0
|
71 *
|
Chris@0
|
72 * The default priority is 1, which is very low. To have listeners that have
|
Chris@0
|
73 * a "first attempt" at handling exceptions return a higher priority.
|
Chris@0
|
74 *
|
Chris@0
|
75 * @return int
|
Chris@0
|
76 * The event priority of this subscriber.
|
Chris@0
|
77 */
|
Chris@0
|
78 protected static function getPriority() {
|
Chris@0
|
79 return 0;
|
Chris@0
|
80 }
|
Chris@0
|
81
|
Chris@0
|
82 /**
|
Chris@0
|
83 * Handles errors for this subscriber.
|
Chris@0
|
84 *
|
Chris@0
|
85 * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
|
Chris@0
|
86 * The event to process.
|
Chris@0
|
87 */
|
Chris@0
|
88 public function onException(GetResponseForExceptionEvent $event) {
|
Chris@0
|
89 $exception = $event->getException();
|
Chris@0
|
90
|
Chris@0
|
91 // Make the exception available for example when rendering a block.
|
Chris@0
|
92 $request = $event->getRequest();
|
Chris@0
|
93 $request->attributes->set('exception', $exception);
|
Chris@0
|
94
|
Chris@0
|
95 $handled_formats = $this->getHandledFormats();
|
Chris@0
|
96
|
Chris@0
|
97 $format = $request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT, $request->getRequestFormat());
|
Chris@0
|
98
|
Chris@0
|
99 if ($exception instanceof HttpExceptionInterface && (empty($handled_formats) || in_array($format, $handled_formats))) {
|
Chris@0
|
100 $method = 'on' . $exception->getStatusCode();
|
Chris@0
|
101 // Keep just the leading number of the status code to produce either a
|
Chris@0
|
102 // on400 or a 500 method callback.
|
Chris@0
|
103 $method_fallback = 'on' . substr($exception->getStatusCode(), 0, 1) . 'xx';
|
Chris@0
|
104 // We want to allow the method to be called and still not set a response
|
Chris@0
|
105 // if it has additional filtering logic to determine when it will apply.
|
Chris@0
|
106 // It is therefore the method's responsibility to set the response on the
|
Chris@0
|
107 // event if appropriate.
|
Chris@0
|
108 if (method_exists($this, $method)) {
|
Chris@0
|
109 $this->$method($event);
|
Chris@0
|
110 }
|
Chris@0
|
111 elseif (method_exists($this, $method_fallback)) {
|
Chris@0
|
112 $this->$method_fallback($event);
|
Chris@0
|
113 }
|
Chris@0
|
114 }
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 /**
|
Chris@0
|
118 * Registers the methods in this class that should be listeners.
|
Chris@0
|
119 *
|
Chris@0
|
120 * @return array
|
Chris@0
|
121 * An array of event listener definitions.
|
Chris@0
|
122 */
|
Chris@0
|
123 public static function getSubscribedEvents() {
|
Chris@0
|
124 $events[KernelEvents::EXCEPTION][] = ['onException', static::getPriority()];
|
Chris@0
|
125 return $events;
|
Chris@0
|
126 }
|
Chris@0
|
127
|
Chris@0
|
128 }
|