• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 7358244626

29 Dec 2023 04:31PM UTC coverage: 37.248%. Remained the same
7358244626

push

github

soyuka
style: latest cs-fixer

2 of 3 new or added lines in 2 files covered. (66.67%)

69 existing lines in 7 files now uncovered.

10299 of 27650 relevant lines covered (37.25%)

28.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.37
/src/Symfony/EventListener/RespondListener.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
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\Symfony\EventListener;
15

16
use ApiPlatform\Api\IriConverterInterface as LegacyIriConverterInterface;
17
use ApiPlatform\Metadata\Exception\HttpExceptionInterface;
18
use ApiPlatform\Metadata\IriConverterInterface;
19
use ApiPlatform\Metadata\Put;
20
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
21
use ApiPlatform\Metadata\UrlGeneratorInterface;
22
use ApiPlatform\State\Util\OperationRequestInitiatorTrait;
23
use ApiPlatform\Symfony\Util\RequestAttributesExtractor;
24
use Symfony\Component\HttpFoundation\Response;
25
use Symfony\Component\HttpKernel\Event\ViewEvent;
26

27
/**
28
 * Builds the response object.
29
 *
30
 * @author Kévin Dunglas <dunglas@gmail.com>
31
 */
32
final class RespondListener
33
{
34
    use OperationRequestInitiatorTrait;
35

36
    public const METHOD_TO_CODE = [
37
        'POST' => Response::HTTP_CREATED,
38
        'DELETE' => Response::HTTP_NO_CONTENT,
39
    ];
40

41
    public function __construct(
42
        ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null,
43
        private readonly null|IriConverterInterface|LegacyIriConverterInterface $iriConverter = null,
44
    ) {
45
        $this->resourceMetadataCollectionFactory = $resourceMetadataFactory;
58✔
46
    }
47

48
    /**
49
     * Creates a Response to send to the client according to the requested format.
50
     */
51
    public function onKernelView(ViewEvent $event): void
52
    {
53
        $request = $event->getRequest();
58✔
54
        $controllerResult = $event->getControllerResult();
58✔
55
        $operation = $this->initializeOperation($request);
58✔
56

57
        if ('api_platform.symfony.main_controller' === $operation?->getController() || $request->attributes->get('_api_platform_disable_listeners')) {
58✔
58
            return;
×
59
        }
60

61
        $attributes = RequestAttributesExtractor::extractAttributes($request);
58✔
62

63
        if ($controllerResult instanceof Response && ($attributes['respond'] ?? false)) {
58✔
64
            $event->setResponse($controllerResult);
4✔
65

66
            return;
4✔
67
        }
68

69
        if ($controllerResult instanceof Response || !($attributes['respond'] ?? $request->attributes->getBoolean('_api_respond'))) {
54✔
70
            return;
8✔
71
        }
72

73
        $headers = [
46✔
74
            'Content-Type' => sprintf('%s; charset=utf-8', $request->getMimeType($request->getRequestFormat())),
46✔
75
            'Vary' => 'Accept',
46✔
76
            'X-Content-Type-Options' => 'nosniff',
46✔
77
            'X-Frame-Options' => 'deny',
46✔
78
        ];
46✔
79

80
        $status = $operation?->getStatus();
46✔
81

82
        if ($sunset = $operation?->getSunset()) {
46✔
83
            $headers['Sunset'] = (new \DateTimeImmutable($sunset))->format(\DateTime::RFC1123);
4✔
84
        }
85

86
        if ($acceptPatch = $operation?->getAcceptPatch()) {
46✔
UNCOV
87
            $headers['Accept-Patch'] = $acceptPatch;
5✔
88
        }
89

90
        $method = $request->getMethod();
46✔
91
        if (
92
            $this->iriConverter
46✔
93
            && $operation
94
            && ($operation->getExtraProperties()['is_alternate_resource_metadata'] ?? false)
46✔
95
            && 301 === $operation->getStatus()
46✔
96
        ) {
97
            $status = 301;
×
98
            $headers['Location'] = $this->iriConverter->getIriFromResource($request->attributes->get('data'), UrlGeneratorInterface::ABS_PATH, $operation);
×
99
        } elseif ('PUT' === $method && !($attributes['previous_data'] ?? null) && null === $status && ($operation instanceof Put && ($operation->getAllowCreate() ?? false))) {
46✔
100
            $status = Response::HTTP_CREATED;
×
101
        }
102

103
        $status ??= self::METHOD_TO_CODE[$request->getMethod()] ?? Response::HTTP_OK;
46✔
104

105
        if ($request->attributes->has('_api_write_item_iri')) {
46✔
106
            $headers['Content-Location'] = $request->attributes->get('_api_write_item_iri');
15✔
107

108
            if ((Response::HTTP_CREATED === $status || (300 <= $status && $status < 400)) && 'POST' === $method) {
15✔
109
                $headers['Location'] = $request->attributes->get('_api_write_item_iri');
11✔
110
            }
111
        }
112

113
        if (($exception = $request->attributes->get('data')) instanceof HttpExceptionInterface) {
46✔
114
            $headers = array_merge($headers, $exception->getHeaders());
×
115
        }
116

117
        $event->setResponse(new Response(
46✔
118
            $controllerResult,
46✔
119
            $status,
46✔
120
            $headers
46✔
121
        ));
46✔
122
    }
123
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc