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

api-platform / core / 10729306835

05 Sep 2024 10:46PM UTC coverage: 7.655% (-0.01%) from 7.665%
10729306835

push

github

web-flow
Merge pull request #6586 from soyuka/merge-342

Merge 3.4

0 of 54 new or added lines in 12 files covered. (0.0%)

8760 existing lines in 277 files now uncovered.

12505 of 163357 relevant lines covered (7.66%)

22.84 hits per line

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

78.05
/src/State/Provider/DeserializeProvider.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\State\Provider;
15

16
use ApiPlatform\Metadata\HttpOperation;
17
use ApiPlatform\Metadata\Operation;
18
use ApiPlatform\Serializer\SerializerContextBuilderInterface as LegacySerializerContextBuilderInterface;
19
use ApiPlatform\State\ProviderInterface;
20
use ApiPlatform\State\SerializerContextBuilderInterface;
21
use ApiPlatform\Validator\Exception\ValidationException;
22
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
23
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
24
use Symfony\Component\Serializer\Exception\PartialDenormalizationException;
25
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
26
use Symfony\Component\Serializer\SerializerInterface;
27
use Symfony\Component\Validator\Constraints\Type;
28
use Symfony\Component\Validator\ConstraintViolation;
29
use Symfony\Component\Validator\ConstraintViolationList;
30
use Symfony\Contracts\Translation\LocaleAwareInterface;
31
use Symfony\Contracts\Translation\TranslatorInterface;
32
use Symfony\Contracts\Translation\TranslatorTrait;
33

34
final class DeserializeProvider implements ProviderInterface
35
{
36
    public function __construct(
37
        private readonly ?ProviderInterface $decorated,
38
        private readonly SerializerInterface $serializer,
39
        private readonly LegacySerializerContextBuilderInterface|SerializerContextBuilderInterface $serializerContextBuilder,
40
        private ?TranslatorInterface $translator = null,
41
    ) {
UNCOV
42
        if (null === $this->translator) {
1,847✔
43
            $this->translator = new class implements TranslatorInterface, LocaleAwareInterface {
×
44
                use TranslatorTrait;
45
            };
×
46
            $this->translator->setLocale('en');
×
47
        }
48
    }
49

50
    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
51
    {
52
        // We need request content
UNCOV
53
        if (!$operation instanceof HttpOperation || !($request = $context['request'] ?? null)) {
1,847✔
54
            return $this->decorated?->provide($operation, $uriVariables, $context);
×
55
        }
56

UNCOV
57
        $data = $this->decorated ? $this->decorated->provide($operation, $uriVariables, $context) : $request->attributes->get('data');
1,847✔
58

UNCOV
59
        if (!$operation->canDeserialize()) {
1,835✔
UNCOV
60
            return $data;
1,352✔
61
        }
62

UNCOV
63
        $contentType = $request->headers->get('CONTENT_TYPE');
588✔
UNCOV
64
        if (null === $contentType || '' === $contentType) {
588✔
65
            throw new UnsupportedMediaTypeHttpException('The "Content-Type" header must exist.');
×
66
        }
67

UNCOV
68
        $serializerContext = $this->serializerContextBuilder->createFromRequest($request, false, [
588✔
UNCOV
69
            'resource_class' => $operation->getClass(),
588✔
UNCOV
70
            'operation' => $operation,
588✔
UNCOV
71
        ]);
588✔
72

UNCOV
73
        $serializerContext['uri_variables'] = $uriVariables;
588✔
74

UNCOV
75
        if (!$format = $request->attributes->get('input_format') ?? null) {
588✔
76
            throw new UnsupportedMediaTypeHttpException('Format not supported.');
×
77
        }
78

UNCOV
79
        $method = $operation->getMethod();
588✔
80

81
        if (
UNCOV
82
            null !== $data
588✔
83
            && (
UNCOV
84
                'POST' === $method
588✔
UNCOV
85
                || 'PATCH' === $method
588✔
UNCOV
86
                || ('PUT' === $method && !($operation->getExtraProperties()['standard_put'] ?? false))
588✔
87
            )
88
        ) {
UNCOV
89
            $serializerContext[AbstractNormalizer::OBJECT_TO_POPULATE] = $data;
86✔
90
        }
91

92
        try {
UNCOV
93
            return $this->serializer->deserialize((string) $request->getContent(), $operation->getClass(), $format, $serializerContext);
588✔
UNCOV
94
        } catch (PartialDenormalizationException $e) {
60✔
95
            if (!class_exists(ConstraintViolationList::class)) {
1✔
96
                throw $e;
×
97
            }
98

99
            $violations = new ConstraintViolationList();
1✔
100
            foreach ($e->getErrors() as $exception) {
1✔
101
                if (!$exception instanceof NotNormalizableValueException) {
1✔
102
                    continue;
×
103
                }
104
                $message = (new Type($exception->getExpectedTypes() ?? []))->message;
1✔
105
                $parameters = [];
1✔
106
                if ($exception->canUseMessageForUser()) {
1✔
107
                    $parameters['hint'] = $exception->getMessage();
1✔
108
                }
109
                $violations->add(new ConstraintViolation($this->translator->trans($message, ['{{ type }}' => implode('|', $exception->getExpectedTypes() ?? [])], 'validators'), $message, $parameters, null, $exception->getPath(), null, null, (string) Type::INVALID_TYPE_ERROR));
1✔
110
            }
111
            if (0 !== \count($violations)) {
1✔
112
                throw new ValidationException($violations);
1✔
113
            }
114
        }
115

116
        return $data;
×
117
    }
118
}
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