Passed
Push — master ( dd03d9...cef246 )
by Kévin
04:20 queued 30s
created

supportsDenormalization()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 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\Normalizer;
15
16
use ApiPlatform\Core\Api\IdentifiersExtractorInterface;
17
use ApiPlatform\Core\Exception\InvalidIdentifierException;
18
use ApiPlatform\Core\Identifier\CompositeIdentifierParser;
19
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
20
use Symfony\Component\PropertyInfo\Type;
21
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
22
23
/**
24
 * Identifier normalizer.
25
 *
26
 * @author Antoine Bluchet <[email protected]>
27
 */
28
final class ChainIdentifierNormalizer implements DenormalizerInterface
29
{
30
    const HAS_IDENTIFIER_NORMALIZER = 'has_normalized_identifier';
31
32
    private $propertyMetadataFactory;
33
    private $identifiersExtractor;
34
    private $identifierNormalizers;
35
    private $compositeIdentifierParser;
36
37
    public function __construct(IdentifiersExtractorInterface $identifiersExtractor, PropertyMetadataFactoryInterface $propertyMetadataFactory, $identifierNormalizers)
38
    {
39
        $this->propertyMetadataFactory = $propertyMetadataFactory;
40
        $this->identifiersExtractor = $identifiersExtractor;
41
        $this->identifierNormalizers = $identifierNormalizers;
42
        $this->compositeIdentifierParser = new CompositeIdentifierParser();
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     *
48
     * @throws InvalidIdentifierException
49
     */
50
    public function denormalize($data, $class, $format = null, array $context = [])
51
    {
52
        $keys = $this->identifiersExtractor->getIdentifiersFromResourceClass($class);
53
54
        if (\count($keys) > 1) {
55
            $identifiers = $this->compositeIdentifierParser->parse($data);
56
        } else {
57
            $identifiers = [$keys[0] => $data];
58
        }
59
60
        // Normalize every identifier (DateTime, UUID etc.)
61
        foreach ($keys as $key) {
62
            foreach ($this->identifierNormalizers as $normalizer) {
63
                if (!isset($identifiers[$key])) {
64
                    throw new InvalidIdentifierException(sprintf('Invalid identifier "%s", "%s" was not found.', $key, $key));
65
                }
66
67
                $metadata = $this->getIdentifierMetadata($class, $key);
68
69
                if (!$normalizer->supportsDenormalization($identifiers[$key], $metadata)) {
70
                    continue;
71
                }
72
73
                try {
74
                    $identifiers[$key] = $normalizer->denormalize($identifiers[$key], $metadata);
75
                } catch (InvalidIdentifierException $e) {
76
                    throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $key), $e->getCode(), $e);
77
                }
78
            }
79
        }
80
81
        return $identifiers;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $identifiers returns the type array which is incompatible with the return type mandated by Symfony\Component\Serial...nterface::denormalize() of object.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function supportsDenormalization($data, $type, $format = null)
88
    {
89
        return true;
90
    }
91
92
    private function getIdentifierMetadata($class, $propertyName)
93
    {
94
        $propertyMetadata = $this->propertyMetadataFactory->create($class, $propertyName);
95
        $type = $propertyMetadata->getType();
96
97
        return $type && Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType() ? $type->getClassName() : null;
98
    }
99
}
100