1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the API Platform project. |
||
5 | * |
||
6 | * (c) Kévin Dunglas <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | declare(strict_types=1); |
||
13 | |||
14 | namespace ApiPlatform\Core\EventListener; |
||
15 | |||
16 | use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; |
||
17 | use ApiPlatform\Core\Util\RequestAttributesExtractor; |
||
18 | use Symfony\Component\HttpFoundation\Response; |
||
19 | use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; |
||
20 | |||
21 | /** |
||
22 | * Builds the response object. |
||
23 | * |
||
24 | * @author Kévin Dunglas <[email protected]> |
||
25 | */ |
||
26 | final class RespondListener |
||
27 | { |
||
28 | public const METHOD_TO_CODE = [ |
||
29 | 'POST' => Response::HTTP_CREATED, |
||
30 | 'DELETE' => Response::HTTP_NO_CONTENT, |
||
31 | ]; |
||
32 | |||
33 | private $resourceMetadataFactory; |
||
34 | |||
35 | public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory = null) |
||
36 | { |
||
37 | $this->resourceMetadataFactory = $resourceMetadataFactory; |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * Creates a Response to send to the client according to the requested format. |
||
42 | */ |
||
43 | public function onKernelView(GetResponseForControllerResultEvent $event): void |
||
44 | { |
||
45 | $controllerResult = $event->getControllerResult(); |
||
46 | $request = $event->getRequest(); |
||
47 | |||
48 | $attributes = RequestAttributesExtractor::extractAttributes($request); |
||
49 | if ($controllerResult instanceof Response && ($attributes['respond'] ?? false)) { |
||
50 | $event->setResponse($controllerResult); |
||
51 | |||
52 | return; |
||
53 | } |
||
54 | if ($controllerResult instanceof Response || !($attributes['respond'] ?? $request->attributes->getBoolean('_api_respond', false))) { |
||
55 | return; |
||
56 | } |
||
57 | |||
58 | $headers = [ |
||
59 | 'Content-Type' => sprintf('%s; charset=utf-8', $request->getMimeType($request->getRequestFormat())), |
||
60 | 'Vary' => 'Accept', |
||
61 | 'X-Content-Type-Options' => 'nosniff', |
||
62 | 'X-Frame-Options' => 'deny', |
||
63 | ]; |
||
64 | |||
65 | if ($request->attributes->has('_api_write_item_iri')) { |
||
66 | $headers['Content-Location'] = $request->attributes->get('_api_write_item_iri'); |
||
67 | |||
68 | if ($request->isMethod('POST')) { |
||
69 | $headers['Location'] = $request->attributes->get('_api_write_item_iri'); |
||
70 | } |
||
71 | } |
||
72 | |||
73 | $status = null; |
||
74 | if ($this->resourceMetadataFactory && $attributes) { |
||
0 ignored issues
–
show
|
|||
75 | $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); |
||
76 | |||
77 | if ($sunset = $resourceMetadata->getOperationAttribute($attributes, 'sunset', null, true)) { |
||
78 | $headers['Sunset'] = (new \DateTimeImmutable($sunset))->format(\DateTime::RFC1123); |
||
79 | } |
||
80 | |||
81 | $status = $resourceMetadata->getOperationAttribute($attributes, 'status'); |
||
82 | } |
||
83 | |||
84 | $event->setResponse(new Response( |
||
85 | $controllerResult, |
||
86 | $status ?? self::METHOD_TO_CODE[$request->getMethod()] ?? Response::HTTP_OK, |
||
87 | $headers |
||
88 | )); |
||
89 | } |
||
90 | } |
||
91 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.