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

IdentifierConverter   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 62
Duplicated Lines 0 %

Importance

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

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B convert() 0 35 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 (!$keys) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $keys of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
49
            throw new InvalidIdentifierException(sprintf('Resource "%s" has no identifiers.', $class));
50
        }
51
52
        if (\count($keys) > 1) {
53
            $identifiers = CompositeIdentifierParser::parse($data);
54
        } else {
55
            $identifiers = [$keys[0] => $data];
56
        }
57
58
        // Normalize every identifier (DateTime, UUID etc.)
59
        foreach ($keys as $key) {
60
            if (!isset($identifiers[$key])) {
61
                throw new InvalidIdentifierException(sprintf('Invalid identifier "%1$s", "%1$s" was not found.', $key));
62
            }
63
64
            $metadata = $this->getIdentifierMetadata($class, $key);
65
            foreach ($this->identifierDenormalizers as $normalizer) {
66
                if (!$normalizer->supportsDenormalization($identifiers[$key], $metadata)) {
67
                    continue;
68
                }
69
70
                try {
71
                    $identifiers[$key] = $normalizer->denormalize($identifiers[$key], $metadata);
72
                } catch (InvalidIdentifierException $e) {
73
                    throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $key), $e->getCode(), $e);
74
                }
75
            }
76
        }
77
78
        return $identifiers;
79
    }
80
81
    private function getIdentifierMetadata($class, $propertyName)
82
    {
83
        if (!$type = $this->propertyMetadataFactory->create($class, $propertyName)->getType()) {
84
            return null;
85
        }
86
87
        return Type::BUILTIN_TYPE_OBJECT === ($builtInType = $type->getBuiltinType()) ? $type->getClassName() : $builtInType;
88
    }
89
}
90