Passed
Pull Request — master (#2068)
by Antoine
03:06
created

IdentifierConverter::convert()   B

Complexity

Conditions 8
Paths 13

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 8.1475
c 0
b 0
f 0
cc 8
nc 13
nop 2
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\Identifier;
15
16
use ApiPlatform\Core\Api\IdentifiersExtractorInterface;
17
use ApiPlatform\Core\Exception\InvalidIdentifierException;
18
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
19
use Symfony\Component\PropertyInfo\Type;
20
21
/**
22
 * Identifier converter that chains identifier denormalizers.
23
 *
24
 * @author Antoine Bluchet <[email protected]>
25
 */
26
final class IdentifierConverter implements IdentifierConverterInterface
27
{
28
    private $propertyMetadataFactory;
29
    private $identifiersExtractor;
30
    private $identifierDenormalizers;
31
32
    public function __construct(IdentifiersExtractorInterface $identifiersExtractor, PropertyMetadataFactoryInterface $propertyMetadataFactory, $identifierDenormalizers)
33
    {
34
        $this->propertyMetadataFactory = $propertyMetadataFactory;
35
        $this->identifiersExtractor = $identifiersExtractor;
36
        $this->identifierDenormalizers = $identifierDenormalizers;
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    public function convert(string $data, string $class): array
43
    {
44
        $keys = $this->identifiersExtractor->getIdentifiersFromResourceClass($class);
45
46
        if ($numIdentifiers = \count($keys) > 1) {
47
            $identifiers = CompositeIdentifierParser::parse($data);
48
        } elseif (0 === $numIdentifiers) {
0 ignored issues
show
introduced by
The condition 0 === $numIdentifiers is always false.
Loading history...
49
            throw new InvalidIdentifierException(sprintf('Resource "%s" has no identifiers.', $class));
50
        } else {
51
            $identifiers = [$keys[0] => $data];
52
        }
53
54
        // Normalize every identifier (DateTime, UUID etc.)
55
        foreach ($keys as $key) {
56
            if (!isset($identifiers[$key])) {
57
                throw new InvalidIdentifierException(sprintf('Invalid identifier "%1$s", "%1$s" was not found.', $key));
58
            }
59
60
            $metadata = $this->getIdentifierMetadata($class, $key);
61
            foreach ($this->identifierDenormalizers as $normalizer) {
62
                if (!$normalizer->supportsDenormalization($identifiers[$key], $metadata)) {
63
                    continue;
64
                }
65
66
                try {
67
                    $identifiers[$key] = $normalizer->denormalize($identifiers[$key], $metadata);
68
                } catch (InvalidIdentifierException $e) {
69
                    throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $key), $e->getCode(), $e);
70
                }
71
            }
72
        }
73
74
        return $identifiers;
75
    }
76
77
    private function getIdentifierMetadata($class, $propertyName)
78
    {
79
        if (!$type = $this->propertyMetadataFactory->create($class, $propertyName)->getType()) {
80
            return null;
81
        }
82
83
        return Type::BUILTIN_TYPE_OBJECT === ($builtInType = $type->getBuiltinType()) ? $type->getClassName() : $builtInType;
84
    }
85
}
86