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) { |
|
|
|
|
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
|
|
|
|
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.