Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
94.44% covered (success)
94.44%
17 / 18
85.00% covered (warning)
85.00%
17 / 20
21.74% covered (danger)
21.74%
5 / 23
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
UnprocessableEntityHttpExceptionNormalizer
94.44% covered (success)
94.44%
17 / 18
85.00% covered (warning)
85.00%
17 / 20
21.74% covered (danger)
21.74%
5 / 23
80.00% covered (warning)
80.00%
4 / 5
69.00
0.00% covered (danger)
0.00%
0 / 1
 supportsNormalization
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 normalizeErrors
92.86% covered (success)
92.86%
13 / 14
81.25% covered (warning)
81.25%
13 / 16
5.26% covered (danger)
5.26%
1 / 19
0.00% covered (danger)
0.00%
0 / 1
48.66
 getSupportedTypes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getErrorCode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStatus
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Shared\Infrastructure\Normalizer;
4
5use App\Shared\Domain\Exception\ErrorCode;
6use InvalidArgumentException;
7use Symfony\Component\Clock\ClockAwareTrait;
8use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
9use Symfony\Component\HttpFoundation\Response;
10use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
11use Symfony\Component\Validator\Constraint;
12use Symfony\Component\Validator\Exception\ValidationFailedException;
13use Throwable;
14
15#[AutoconfigureTag('app.exception_normalizer')]
16class UnprocessableEntityHttpExceptionNormalizer extends ExceptionNormalizer
17{
18
19    use ClockAwareTrait;
20
21    /**
22     * @param mixed $data
23     * @param string|null $format
24     * @param array<string, mixed> $context
25     * @return bool
26     */
27    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
28    {
29        return $data instanceof UnprocessableEntityHttpException;
30    }
31
32    /**
33     * @param Throwable $throwable
34     * @return array<string, array<string, string[]|int[]>>
35     */
36    protected function normalizeErrors(Throwable $throwable): array
37    {
38        if (!$throwable instanceof UnprocessableEntityHttpException) {
39            throw new InvalidArgumentException();
40        }
41
42        /**
43         * @var ValidationFailedException $validationFailedException
44         */
45        $validationFailedException = $throwable->getPrevious();
46
47        $errorsAsArray = [];
48        foreach ($validationFailedException->getViolations() as $violation) {
49            $propertyPath = $violation->getPropertyPath();
50            /** @var class-string<Constraint> $constraintClass */
51            $constraintClass = $violation->getConstraint() ? $violation->getConstraint()::class : null;
52            $detailCode = $constraintClass ? $constraintClass::getErrorName($violation->getCode()) : ErrorCode::UNKNOWN_ERROR->getCode();
53            if (!isset($errorsAsArray[$propertyPath])) {
54                $errorsAsArray[$propertyPath] = [];
55            }
56            if (!isset($errorsAsArray[$propertyPath][$detailCode])) {
57                $errorsAsArray[$propertyPath][$detailCode] = [];
58            }
59            $errorsAsArray[$propertyPath][$detailCode][strtolower($detailCode)] = $violation->getMessage();
60        }
61        return $errorsAsArray;
62    }
63
64    public function getSupportedTypes(?string $format): array
65    {
66        return [UnprocessableEntityHttpException::class => true];
67    }
68
69    #[\Override]
70    protected function getErrorCode(Throwable $throwable): string
71    {
72        return 'validation-error';
73    }
74
75    #[\Override]
76    protected function getStatus(Throwable $throwable): int
77    {
78        return Response::HTTP_UNPROCESSABLE_ENTITY;
79    }
80}

Branches

Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

UnprocessableEntityHttpExceptionNormalizer->getErrorCode
70    protected function getErrorCode(Throwable $throwable): string
71    {
72        return 'validation-error';
73    }
UnprocessableEntityHttpExceptionNormalizer->getStatus
76    protected function getStatus(Throwable $throwable): int
77    {
78        return Response::HTTP_UNPROCESSABLE_ENTITY;
79    }
UnprocessableEntityHttpExceptionNormalizer->getSupportedTypes
64    public function getSupportedTypes(?string $format): array
65    {
66        return [UnprocessableEntityHttpException::class => true];
67    }
UnprocessableEntityHttpExceptionNormalizer->normalizeErrors
36    protected function normalizeErrors(Throwable $throwable): array
37    {
38        if (!$throwable instanceof UnprocessableEntityHttpException) {
39            throw new InvalidArgumentException();
45        $validationFailedException = $throwable->getPrevious();
46
47        $errorsAsArray = [];
48        foreach ($validationFailedException->getViolations() as $violation) {
48        foreach ($validationFailedException->getViolations() as $violation) {
49            $propertyPath = $violation->getPropertyPath();
50            /** @var class-string<Constraint> $constraintClass */
51            $constraintClass = $violation->getConstraint() ? $violation->getConstraint()::class : null;
51            $constraintClass = $violation->getConstraint() ? $violation->getConstraint()::class : null;
51            $constraintClass = $violation->getConstraint() ? $violation->getConstraint()::class : null;
51            $constraintClass = $violation->getConstraint() ? $violation->getConstraint()::class : null;
52            $detailCode = $constraintClass ? $constraintClass::getErrorName($violation->getCode()) : ErrorCode::UNKNOWN_ERROR->getCode();
52            $detailCode = $constraintClass ? $constraintClass::getErrorName($violation->getCode()) : ErrorCode::UNKNOWN_ERROR->getCode();
52            $detailCode = $constraintClass ? $constraintClass::getErrorName($violation->getCode()) : ErrorCode::UNKNOWN_ERROR->getCode();
52            $detailCode = $constraintClass ? $constraintClass::getErrorName($violation->getCode()) : ErrorCode::UNKNOWN_ERROR->getCode();
53            if (!isset($errorsAsArray[$propertyPath])) {
54                $errorsAsArray[$propertyPath] = [];
55            }
56            if (!isset($errorsAsArray[$propertyPath][$detailCode])) {
56            if (!isset($errorsAsArray[$propertyPath][$detailCode])) {
57                $errorsAsArray[$propertyPath][$detailCode] = [];
58            }
59            $errorsAsArray[$propertyPath][$detailCode][strtolower($detailCode)] = $violation->getMessage();
48        foreach ($validationFailedException->getViolations() as $violation) {
49            $propertyPath = $violation->getPropertyPath();
50            /** @var class-string<Constraint> $constraintClass */
51            $constraintClass = $violation->getConstraint() ? $violation->getConstraint()::class : null;
52            $detailCode = $constraintClass ? $constraintClass::getErrorName($violation->getCode()) : ErrorCode::UNKNOWN_ERROR->getCode();
53            if (!isset($errorsAsArray[$propertyPath])) {
54                $errorsAsArray[$propertyPath] = [];
55            }
56            if (!isset($errorsAsArray[$propertyPath][$detailCode])) {
57                $errorsAsArray[$propertyPath][$detailCode] = [];
58            }
59            $errorsAsArray[$propertyPath][$detailCode][strtolower($detailCode)] = $violation->getMessage();
48        foreach ($validationFailedException->getViolations() as $violation) {
49            $propertyPath = $violation->getPropertyPath();
50            /** @var class-string<Constraint> $constraintClass */
51            $constraintClass = $violation->getConstraint() ? $violation->getConstraint()::class : null;
52            $detailCode = $constraintClass ? $constraintClass::getErrorName($violation->getCode()) : ErrorCode::UNKNOWN_ERROR->getCode();
53            if (!isset($errorsAsArray[$propertyPath])) {
54                $errorsAsArray[$propertyPath] = [];
55            }
56            if (!isset($errorsAsArray[$propertyPath][$detailCode])) {
57                $errorsAsArray[$propertyPath][$detailCode] = [];
58            }
59            $errorsAsArray[$propertyPath][$detailCode][strtolower($detailCode)] = $violation->getMessage();
60        }
61        return $errorsAsArray;
62    }
UnprocessableEntityHttpExceptionNormalizer->supportsNormalization
27    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
28    {
29        return $data instanceof UnprocessableEntityHttpException;
30    }
{main}
3namespace App\Shared\Infrastructure\Normalizer;
4
5use App\Shared\Domain\Exception\ErrorCode;
6use InvalidArgumentException;
7use Symfony\Component\Clock\ClockAwareTrait;
8use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
9use Symfony\Component\HttpFoundation\Response;
10use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
11use Symfony\Component\Validator\Constraint;
12use Symfony\Component\Validator\Exception\ValidationFailedException;
13use Throwable;
14
15#[AutoconfigureTag('app.exception_normalizer')]
16class UnprocessableEntityHttpExceptionNormalizer extends ExceptionNormalizer
17{
18
19    use ClockAwareTrait;
20
21    /**
22     * @param mixed $data
23     * @param string|null $format
24     * @param array<string, mixed> $context
25     * @return bool
26     */
27    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
28    {
29        return $data instanceof UnprocessableEntityHttpException;
30    }
31
32    /**
33     * @param Throwable $throwable
34     * @return array<string, array<string, string[]|int[]>>
35     */
36    protected function normalizeErrors(Throwable $throwable): array
37    {
38        if (!$throwable instanceof UnprocessableEntityHttpException) {
39            throw new InvalidArgumentException();
40        }
41
42        /**
43         * @var ValidationFailedException $validationFailedException
44         */
45        $validationFailedException = $throwable->getPrevious();
46
47        $errorsAsArray = [];
48        foreach ($validationFailedException->getViolations() as $violation) {
49            $propertyPath = $violation->getPropertyPath();
50            /** @var class-string<Constraint> $constraintClass */
51            $constraintClass = $violation->getConstraint() ? $violation->getConstraint()::class : null;
52            $detailCode = $constraintClass ? $constraintClass::getErrorName($violation->getCode()) : ErrorCode::UNKNOWN_ERROR->getCode();
53            if (!isset($errorsAsArray[$propertyPath])) {
54                $errorsAsArray[$propertyPath] = [];
55            }
56            if (!isset($errorsAsArray[$propertyPath][$detailCode])) {
57                $errorsAsArray[$propertyPath][$detailCode] = [];
58            }
59            $errorsAsArray[$propertyPath][$detailCode][strtolower($detailCode)] = $violation->getMessage();
60        }
61        return $errorsAsArray;
62    }
63
64    public function getSupportedTypes(?string $format): array
65    {
66        return [UnprocessableEntityHttpException::class => true];
67    }
68
69    #[\Override]
70    protected function getErrorCode(Throwable $throwable): string
71    {
72        return 'validation-error';
73    }
74
75    #[\Override]
76    protected function getStatus(Throwable $throwable): int
77    {
78        return Response::HTTP_UNPROCESSABLE_ENTITY;
79    }