Chris@18
|
1 <?php
|
Chris@18
|
2
|
Chris@18
|
3 namespace Drupal\jsonapi\EventSubscriber;
|
Chris@18
|
4
|
Chris@18
|
5 use Drupal\jsonapi\JsonApiResource\ErrorCollection;
|
Chris@18
|
6 use Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel;
|
Chris@18
|
7 use Drupal\jsonapi\JsonApiResource\LinkCollection;
|
Chris@18
|
8 use Drupal\jsonapi\JsonApiResource\NullIncludedData;
|
Chris@18
|
9 use Drupal\jsonapi\ResourceResponse;
|
Chris@18
|
10 use Drupal\jsonapi\Routing\Routes;
|
Chris@18
|
11 use Drupal\serialization\EventSubscriber\DefaultExceptionSubscriber as SerializationDefaultExceptionSubscriber;
|
Chris@18
|
12 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
Chris@18
|
13 use Symfony\Component\HttpKernel\Exception\HttpException;
|
Chris@18
|
14
|
Chris@18
|
15 /**
|
Chris@18
|
16 * Serializes exceptions in compliance with the JSON:API specification.
|
Chris@18
|
17 *
|
Chris@18
|
18 * @internal JSON:API maintains no PHP API. The API is the HTTP API. This class
|
Chris@18
|
19 * may change at any time and could break any dependencies on it.
|
Chris@18
|
20 *
|
Chris@18
|
21 * @see https://www.drupal.org/project/jsonapi/issues/3032787
|
Chris@18
|
22 * @see jsonapi.api.php
|
Chris@18
|
23 */
|
Chris@18
|
24 class DefaultExceptionSubscriber extends SerializationDefaultExceptionSubscriber {
|
Chris@18
|
25
|
Chris@18
|
26 /**
|
Chris@18
|
27 * {@inheritdoc}
|
Chris@18
|
28 */
|
Chris@18
|
29 protected static function getPriority() {
|
Chris@18
|
30 return parent::getPriority() + 25;
|
Chris@18
|
31 }
|
Chris@18
|
32
|
Chris@18
|
33 /**
|
Chris@18
|
34 * {@inheritdoc}
|
Chris@18
|
35 */
|
Chris@18
|
36 protected function getHandledFormats() {
|
Chris@18
|
37 return ['api_json'];
|
Chris@18
|
38 }
|
Chris@18
|
39
|
Chris@18
|
40 /**
|
Chris@18
|
41 * {@inheritdoc}
|
Chris@18
|
42 */
|
Chris@18
|
43 public function onException(GetResponseForExceptionEvent $event) {
|
Chris@18
|
44 if (!$this->isJsonApiExceptionEvent($event)) {
|
Chris@18
|
45 return;
|
Chris@18
|
46 }
|
Chris@18
|
47 if (($exception = $event->getException()) && !$exception instanceof HttpException) {
|
Chris@18
|
48 $exception = new HttpException(500, $exception->getMessage(), $exception);
|
Chris@18
|
49 $event->setException($exception);
|
Chris@18
|
50 }
|
Chris@18
|
51
|
Chris@18
|
52 $this->setEventResponse($event, $exception->getStatusCode());
|
Chris@18
|
53 }
|
Chris@18
|
54
|
Chris@18
|
55 /**
|
Chris@18
|
56 * {@inheritdoc}
|
Chris@18
|
57 */
|
Chris@18
|
58 protected function setEventResponse(GetResponseForExceptionEvent $event, $status) {
|
Chris@18
|
59 /* @var \Symfony\Component\HttpKernel\Exception\HttpException $exception */
|
Chris@18
|
60 $exception = $event->getException();
|
Chris@18
|
61 $response = new ResourceResponse(new JsonApiDocumentTopLevel(new ErrorCollection([$exception]), new NullIncludedData(), new LinkCollection([])), $exception->getStatusCode(), $exception->getHeaders());
|
Chris@18
|
62 $response->addCacheableDependency($exception);
|
Chris@18
|
63 $event->setResponse($response);
|
Chris@18
|
64 }
|
Chris@18
|
65
|
Chris@18
|
66 /**
|
Chris@18
|
67 * Check if the error should be formatted using JSON:API.
|
Chris@18
|
68 *
|
Chris@18
|
69 * The JSON:API format is supported if the format is explicitly set or the
|
Chris@18
|
70 * request is for a known JSON:API route.
|
Chris@18
|
71 *
|
Chris@18
|
72 * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $exception_event
|
Chris@18
|
73 * The exception event.
|
Chris@18
|
74 *
|
Chris@18
|
75 * @return bool
|
Chris@18
|
76 * TRUE if it needs to be formatted using JSON:API. FALSE otherwise.
|
Chris@18
|
77 */
|
Chris@18
|
78 protected function isJsonApiExceptionEvent(GetResponseForExceptionEvent $exception_event) {
|
Chris@18
|
79 $request = $exception_event->getRequest();
|
Chris@18
|
80 $parameters = $request->attributes->all();
|
Chris@18
|
81 return $request->getRequestFormat() === 'api_json' || (bool) Routes::getResourceTypeNameFromParameters($parameters);
|
Chris@18
|
82 }
|
Chris@18
|
83
|
Chris@18
|
84 }
|