Passed
Pull Request — master (#2068)
by Antoine
03:53 queued 41s
created

IdentifierConverter   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 60
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 12
dl 0
loc 60
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B convert() 0 33 8
A getIdentifierMetadata() 0 7 3
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
    const HAS_IDENTIFIER_CONVERTER = 'has_identifier_converter';
29
30
    private $propertyMetadataFactory;
31
    private $identifiersExtractor;
32
    private $identifierDenormalizers;
33
34
    public function __construct(IdentifiersExtractorInterface $identifiersExtractor, PropertyMetadataFactoryInterface $propertyMetadataFactory, $identifierDenormalizers)
35
    {
36
        $this->propertyMetadataFactory = $propertyMetadataFactory;
37
        $this->identifiersExtractor = $identifiersExtractor;
38
        $this->identifierDenormalizers = $identifierDenormalizers;
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function convert(string $data, string $class): array
45
    {
46
        $keys = $this->identifiersExtractor->getIdentifiersFromResourceClass($class);
47
48
        if ($numIdentifiers = \count($keys) > 1) {
49
            $identifiers = CompositeIdentifierParser::parse($data);
50
        } elseif (0 === $numIdentifiers) {
0 ignored issues
show
introduced by
The condition 0 === $numIdentifiers is always false.
Loading history...
51
            throw new InvalidIdentifierException(sprintf('Resource "%s" has no identifiers.', $class));
52
        } else {
53
            $identifiers = [$keys[0] => $data];
54
        }
55
56
        // Normalize every identifier (DateTime, UUID etc.)
57
        foreach ($keys as $key) {
58
            if (!isset($identifiers[$key])) {
59
                throw new InvalidIdentifierException(sprintf('Invalid identifier "%1$s", "%1$s" was not found.', $key));
60
            }
61
62
            $metadata = $this->getIdentifierMetadata($class, $key);
63
            foreach ($this->identifierDenormalizers as $normalizer) {
64
                if (!$normalizer->supportsDenormalization($identifiers[$key], $metadata)) {
65
                    continue;
66
                }
67
68
                try {
69
                    $identifiers[$key] = $normalizer->denormalize($identifiers[$key], $metadata);
70
                } catch (InvalidIdentifierException $e) {
71
                    throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $key), $e->getCode(), $e);
72
                }
73
            }
74
        }
75
76
        return $identifiers;
77
    }
78
79
    private function getIdentifierMetadata($class, $propertyName)
80
    {
81
        if (!$type = $this->propertyMetadataFactory->create($class, $propertyName)->getType()) {
82
            return null;
83
        }
84
85
        return Type::BUILTIN_TYPE_OBJECT === ($builtInType = $type->getBuiltinType()) ? $type->getClassName() : $builtInType;
86
    }
87
}
88