-
-
Notifications
You must be signed in to change notification settings - Fork 590
Expand file tree
/
Copy pathAbstractDoctrineTypeDriver.php
More file actions
160 lines (130 loc) · 5.03 KB
/
AbstractDoctrineTypeDriver.php
File metadata and controls
160 lines (130 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<?php
declare(strict_types=1);
namespace JMS\Serializer\Metadata\Driver;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\Mapping\ClassMetadata as DoctrineClassMetadata;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\ExpressionPropertyMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\StaticPropertyMetadata;
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
use JMS\Serializer\Type\Parser;
use JMS\Serializer\Type\ParserInterface;
use Metadata\ClassMetadata as BaseClassMetadata;
use Metadata\Driver\DriverInterface;
/**
* This class decorates any other driver. If the inner driver does not provide a
* a property type, the decorator will guess based on Doctrine 2 metadata.
*/
abstract class AbstractDoctrineTypeDriver implements DriverInterface
{
/**
* Map of doctrine 2 field types to JMS\Serializer types
*
* @var array
*/
protected $fieldMapping = [
'string' => 'string',
'ascii_string' => 'string',
'text' => 'string',
'blob' => 'string',
'guid' => 'string',
'integer' => 'integer',
'smallint' => 'integer',
'bigint' => 'integer',
'datetime' => 'DateTime',
'datetimetz' => 'DateTime',
'time' => 'DateTime',
'date' => 'DateTime',
'datetime_immutable' => 'DateTimeImmutable',
'datetimetz_immutable' => 'DateTimeImmutable',
'time_immutable' => 'DateTimeImmutable',
'date_immutable' => 'DateTimeImmutable',
'dateinterval' => 'DateInterval',
'float' => 'float',
'decimal' => 'float',
'boolean' => 'boolean',
'array' => 'array',
'json_array' => 'array',
'simple_array' => 'array<string>',
];
/**
* @var DriverInterface
*/
protected $delegate;
/**
* @var ManagerRegistry
*/
protected $registry;
/**
* @var ParserInterface
*/
protected $typeParser;
public function __construct(DriverInterface $delegate, ManagerRegistry $registry, ?ParserInterface $typeParser = null)
{
$this->delegate = $delegate;
$this->registry = $registry;
$this->typeParser = $typeParser ?: new Parser();
}
public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadata
{
$classMetadata = $this->delegate->loadMetadataForClass($class);
\assert($classMetadata instanceof ClassMetadata);
// Abort if the given class is not a mapped entity
if (!$doctrineMetadata = $this->tryLoadingDoctrineMetadata($class->name)) {
return $classMetadata;
}
$this->setDiscriminator($doctrineMetadata, $classMetadata);
// We base our scan on the internal driver's property list so that we
// respect any internal white/blacklisting like in the AnnotationDriver
foreach ($classMetadata->propertyMetadata as $key => $propertyMetadata) {
// If the inner driver provides a type, don't guess anymore.
if ($propertyMetadata->type || $this->isVirtualProperty($propertyMetadata)) {
continue;
}
if ($this->hideProperty($doctrineMetadata, $propertyMetadata)) {
unset($classMetadata->propertyMetadata[$key]);
}
$this->setPropertyType($doctrineMetadata, $propertyMetadata);
}
// Add fields from mapped superclasses
if ($parentClass = $doctrineMetadata->getReflectionClass()->getParentClass()) {
$parentClassMetadata = $this->loadMetadataForClass($parentClass);
$classMetadata->propertyMetadata = array_merge($parentClassMetadata->propertyMetadata, $classMetadata->propertyMetadata);
}
return $classMetadata;
}
private function isVirtualProperty(PropertyMetadata $propertyMetadata): bool
{
return $propertyMetadata instanceof VirtualPropertyMetadata
|| $propertyMetadata instanceof StaticPropertyMetadata
|| $propertyMetadata instanceof ExpressionPropertyMetadata;
}
protected function setDiscriminator(DoctrineClassMetadata $doctrineMetadata, ClassMetadata $classMetadata): void
{
}
protected function hideProperty(DoctrineClassMetadata $doctrineMetadata, PropertyMetadata $propertyMetadata): bool
{
return false;
}
protected function setPropertyType(DoctrineClassMetadata $doctrineMetadata, PropertyMetadata $propertyMetadata): void
{
}
protected function tryLoadingDoctrineMetadata(string $className): ?DoctrineClassMetadata
{
if (!$manager = $this->registry->getManagerForClass($className)) {
return null;
}
if ($manager->getMetadataFactory()->isTransient($className)) {
return null;
}
return $manager->getClassMetadata($className);
}
protected function normalizeFieldType(string $type): ?string
{
if (!isset($this->fieldMapping[$type])) {
return null;
}
return $this->fieldMapping[$type];
}
}