Completed
Pull Request — master (#3263)
by
unknown
10:13
created

PayloadArgumentResolver::resolve()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
nc 2
nop 2
dl 0
loc 7
rs 10
c 1
b 0
f 0
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\Bridge\Symfony\Bundle\ArgumentResolver;
15
16
use ApiPlatform\Core\EventListener\ToggleableDeserializationTrait;
17
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
18
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
19
use ApiPlatform\Core\Util\RequestAttributesExtractor;
20
use Symfony\Component\HttpFoundation\Request;
21
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
22
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
23
24
class PayloadArgumentResolver implements ArgumentValueResolverInterface
25
{
26
    use ToggleableDeserializationTrait;
27
28
    /**
29
     * @var SerializerContextBuilderInterface
30
     */
31
    private $serializationContextBuilder;
32
33
    public function __construct(
34
        ResourceMetadataFactoryInterface $resourceMetadataFactory,
35
        SerializerContextBuilderInterface $serializationContextBuilder
36
    ) {
37
        $this->resourceMetadataFactory = $resourceMetadataFactory;
38
        $this->serializationContextBuilder = $serializationContextBuilder;
39
    }
40
41
    public function supports(Request $request, ArgumentMetadata $argument): bool
42
    {
43
        if ($argument->isVariadic()) {
44
            return false;
45
        }
46
47
        $class = $argument->getType();
48
49
        if (null === $class) {
50
            return false;
51
        }
52
53
        if (null === $request->attributes->get('data')) {
54
            return false;
55
        }
56
57
        $inputClass = $this->getExpectedInputClass($request);
58
59
        if (null === $inputClass) {
60
            return false;
61
        }
62
63
        return $inputClass === $class || is_subclass_of($inputClass, $class);
64
    }
65
66
    public function resolve(Request $request, ArgumentMetadata $argument): \Generator
67
    {
68
        if (!$this->supports($request, $argument)) {
69
            throw new \InvalidArgumentException('Given request and argument not supported.');
70
        }
71
72
        yield $request->attributes->get('data');
73
    }
74
75
    private function getExpectedInputClass(Request $request): ?string
76
    {
77
        $attributes = RequestAttributesExtractor::extractAttributes($request);
78
79
        if (!$this->isRequestToDeserialize($request, $attributes)) {
80
            return null;
81
        }
82
83
        $context = $this->serializationContextBuilder->createFromRequest($request, false, $attributes);
84
85
        return $context['input'] ?? $context['resource_class'];
86
    }
87
}
88