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

api-platform / core / 9881030386

10 Jul 2024 08:30PM UTC coverage: 64.71% (-0.03%) from 64.738%
9881030386

push

github

web-flow
feat(symfony): skip error handler (#6463)

1 of 1 new or added line in 1 file covered. (100.0%)

187 existing lines in 30 files now uncovered.

11475 of 17733 relevant lines covered (64.71%)

68.98 hits per line

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

75.68
/src/Action/ExceptionAction.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\Action;
15

16
use ApiPlatform\Metadata\ApiResource;
17
use ApiPlatform\Metadata\HttpOperation;
18
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
19
use ApiPlatform\State\Util\OperationRequestInitiatorTrait;
20
use ApiPlatform\Symfony\Util\RequestAttributesExtractor;
21
use ApiPlatform\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface;
22
use ApiPlatform\Util\ErrorFormatGuesser;
23
use ApiPlatform\Validator\Exception\ConstraintViolationListAwareExceptionInterface as ApiPlatformConstraintViolationListAwareExceptionInterface;
24
use Symfony\Component\ErrorHandler\Exception\FlattenException;
25
use Symfony\Component\HttpFoundation\Request;
26
use Symfony\Component\HttpFoundation\Response;
27
use Symfony\Component\Serializer\SerializerInterface;
28
use Symfony\Component\Validator\ConstraintViolationListInterface;
29

30
/**
31
 * Renders a normalized exception for a given see [FlattenException](https://github.com/symfony/symfony/blob/6.3/src/Symfony/Component/ErrorHandler/Exception/FlattenException.php).
32
 *
33
 * @author Baptiste Meyer <baptiste.meyer@gmail.com>
34
 * @author Kévin Dunglas <dunglas@gmail.com>
35
 *
36
 * @deprecated since API Platform 3 and Error resource is used {@see ApiPlatform\Symfony\EventListener\ErrorListener}
37
 */
38
final class ExceptionAction
39
{
40
    use OperationRequestInitiatorTrait;
41

42
    /**
43
     * @param array $errorFormats      A list of enabled error formats
44
     * @param array $exceptionToStatus A list of exceptions mapped to their HTTP status code
45
     */
46
    public function __construct(private readonly SerializerInterface $serializer, private readonly array $errorFormats, private readonly array $exceptionToStatus = [], ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null)
47
    {
48
        $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
60✔
49
    }
50

51
    /**
52
     * Converts an exception to a JSON response.
53
     */
54
    public function __invoke(FlattenException $exception, Request $request): Response
55
    {
56
        $operation = $this->initializeOperation($request);
60✔
57
        $exceptionClass = $exception->getClass();
60✔
58
        $statusCode = $exception->getStatusCode();
60✔
59

60
        $exceptionToStatus = array_merge(
60✔
61
            $this->exceptionToStatus,
60✔
62
            $operation ? $operation->getExceptionToStatus() ?? [] : $this->getOperationExceptionToStatus($request)
60✔
63
        );
60✔
64

65
        foreach ($exceptionToStatus as $class => $status) {
60✔
66
            if (is_a($exceptionClass, $class, true)) {
52✔
67
                $statusCode = $status;
52✔
68

69
                break;
52✔
70
            }
71
        }
72

73
        $headers = $exception->getHeaders();
60✔
74
        $format = ErrorFormatGuesser::guessErrorFormat($request, $this->errorFormats);
60✔
75
        $headers['Content-Type'] = sprintf('%s; charset=utf-8', $format['value'][0]);
60✔
76
        $headers['X-Content-Type-Options'] = 'nosniff';
60✔
77
        $headers['X-Frame-Options'] = 'deny';
60✔
78

79
        $context = ['statusCode' => $statusCode, 'rfc_7807_compliant_errors' => $operation?->getExtraProperties()['rfc_7807_compliant_errors'] ?? false];
60✔
80
        $error = $request->attributes->get('exception') ?? $exception;
60✔
81
        if ($error instanceof ConstraintViolationListAwareExceptionInterface || $error instanceof ApiPlatformConstraintViolationListAwareExceptionInterface) {
60✔
82
            $error = $error->getConstraintViolationList();
×
83
        } elseif (method_exists($error, 'getViolations') && $error->getViolations() instanceof ConstraintViolationListInterface) {
60✔
84
            $error = $error->getViolations();
×
85
        } else {
86
            $error = $exception;
60✔
87
        }
88

89
        $serializerFormat = $format['key'];
60✔
90
        if ('json' === $serializerFormat && 'application/problem+json' === $format['value'][0]) {
60✔
UNCOV
91
            $serializerFormat = 'jsonproblem';
×
92
        }
93

94
        return new Response($this->serializer->serialize($error, $serializerFormat, $context), $statusCode, $headers);
60✔
95
    }
96

97
    private function getOperationExceptionToStatus(Request $request): array
98
    {
99
        $attributes = RequestAttributesExtractor::extractAttributes($request);
8✔
100

101
        if ([] === $attributes) {
8✔
102
            return [];
8✔
103
        }
104

105
        $resourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($attributes['resource_class']);
×
106
        /** @var HttpOperation $operation */
107
        $operation = $resourceMetadataCollection->getOperation($attributes['operation_name'] ?? null);
×
108
        $exceptionToStatus = [$operation->getExceptionToStatus() ?: []];
×
109

110
        foreach ($resourceMetadataCollection as $resourceMetadata) {
×
111
            /* @var ApiResource $resourceMetadata */
112
            $exceptionToStatus[] = $resourceMetadata->getExceptionToStatus() ?: [];
×
113
        }
114

115
        return array_merge(...$exceptionToStatus);
×
116
    }
117
}
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