Skip to content

Commit f0db5ae

Browse files
mtarldKorbeil
andcommitted
[PropertyInfo] Deprecate PropertyInfo Type
Co-authored-by: Baptiste Leduc <[email protected]>
1 parent e4cfb66 commit f0db5ae

File tree

52 files changed

+2970
-1352
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2970
-1352
lines changed

UPGRADE-7.1.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ Messenger
1616

1717
* Make `#[AsMessageHandler]` final
1818

19+
PropertyInfo
20+
------------
21+
22+
* The `PropertyTypeExtractorInterface::getTypes` method is deprecated, use `PropertyTypeExtractorInterface::getType` instead
23+
1924
SecurityBundle
2025
--------------
2126

src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php

Lines changed: 173 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
2222
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
2323
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
24-
use Symfony\Component\PropertyInfo\Type;
24+
use Symfony\Component\PropertyInfo\Type as LegacyType;
25+
use Symfony\Component\TypeInfo\Type;
26+
use Symfony\Component\TypeInfo\TypeIdentifier;
2527

2628
/**
2729
* Extracts data using Doctrine ORM and ODM metadata.
@@ -52,8 +54,150 @@ public function getProperties(string $class, array $context = []): ?array
5254
return $properties;
5355
}
5456

57+
public function getType(string $class, string $property, array $context = []): ?Type
58+
{
59+
if (null === $metadata = $this->getMetadata($class)) {
60+
return null;
61+
}
62+
63+
if ($metadata->hasAssociation($property)) {
64+
$class = $metadata->getAssociationTargetClass($property);
65+
66+
if ($metadata->isSingleValuedAssociation($property)) {
67+
if ($metadata instanceof ClassMetadata) {
68+
$associationMapping = $metadata->getAssociationMapping($property);
69+
$nullable = $this->isAssociationNullable($associationMapping);
70+
} else {
71+
$nullable = false;
72+
}
73+
74+
$t = Type::object($class);
75+
76+
return $nullable ? Type::nullable($t) : $t;
77+
}
78+
79+
$collectionKeyType = TypeIdentifier::INT;
80+
81+
if ($metadata instanceof ClassMetadata) {
82+
$associationMapping = $metadata->getAssociationMapping($property);
83+
84+
if (isset($associationMapping['indexBy'])) {
85+
$subMetadata = $this->entityManager->getClassMetadata($associationMapping['targetEntity']);
86+
87+
// Check if indexBy value is a property
88+
$fieldName = $associationMapping['indexBy'];
89+
if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) {
90+
$fieldName = $subMetadata->getFieldForColumn($associationMapping['indexBy']);
91+
// Not a property, maybe a column name?
92+
if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) {
93+
// Maybe the column name is the association join column?
94+
$associationMapping = $subMetadata->getAssociationMapping($fieldName);
95+
96+
$indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($fieldName);
97+
$subMetadata = $this->entityManager->getClassMetadata($associationMapping['targetEntity']);
98+
99+
// Not a property, maybe a column name?
100+
if (null === ($typeOfField = $subMetadata->getTypeOfField($indexProperty))) {
101+
$fieldName = $subMetadata->getFieldForColumn($indexProperty);
102+
$typeOfField = $subMetadata->getTypeOfField($fieldName);
103+
}
104+
}
105+
}
106+
107+
if (!$collectionKeyType = $this->getPhpType($typeOfField)) {
108+
return null;
109+
}
110+
}
111+
}
112+
113+
return Type::collection(Type::object(Collection::class), Type::object($class), Type::builtin($collectionKeyType));
114+
}
115+
116+
if ($metadata instanceof ClassMetadata && isset($metadata->embeddedClasses[$property])) {
117+
return Type::object($metadata->embeddedClasses[$property]['class']);
118+
}
119+
120+
if ($metadata->hasField($property)) {
121+
$typeOfField = $metadata->getTypeOfField($property);
122+
123+
if (!$builtinType = $this->getPhpType($typeOfField)) {
124+
return null;
125+
}
126+
127+
$nullable = $metadata instanceof ClassMetadata && $metadata->isNullable($property);
128+
$enumType = null;
129+
130+
if (null !== $enumClass = $metadata->getFieldMapping($property)['enumType'] ?? null) {
131+
$enumType = Type::enum($enumClass);
132+
$enumType = $nullable ? Type::nullable($enumType) : $enumType;
133+
}
134+
135+
switch ($builtinType) {
136+
case TypeIdentifier::OBJECT:
137+
switch ($typeOfField) {
138+
case Types::DATE_MUTABLE:
139+
case Types::DATETIME_MUTABLE:
140+
case Types::DATETIMETZ_MUTABLE:
141+
case 'vardatetime':
142+
case Types::TIME_MUTABLE:
143+
$t = Type::object(\DateTime::class);
144+
145+
return $nullable ? Type::nullable($t) : $t;
146+
147+
case Types::DATE_IMMUTABLE:
148+
case Types::DATETIME_IMMUTABLE:
149+
case Types::DATETIMETZ_IMMUTABLE:
150+
case Types::TIME_IMMUTABLE:
151+
$t = Type::object(\DateTimeImmutable::class);
152+
153+
return $nullable ? Type::nullable($t) : $t;
154+
155+
case Types::DATEINTERVAL:
156+
$t = Type::object(\DateInterval::class);
157+
158+
return $nullable ? Type::nullable($t) : $t;
159+
}
160+
161+
break;
162+
case TypeIdentifier::ARRAY:
163+
switch ($typeOfField) {
164+
case 'array': // DBAL < 4
165+
case 'json_array': // DBAL < 3
166+
// return null if $enumType is set, because we can't determine if collectionKeyType is string or int
167+
if ($enumType) {
168+
return null;
169+
}
170+
171+
$t = Type::array();
172+
173+
return $nullable ? Type::nullable($t) : $t;
174+
175+
case Types::SIMPLE_ARRAY:
176+
$t = Type::list($enumType ?? Type::string());
177+
178+
return $nullable ? Type::nullable($t) : $t;
179+
}
180+
break;
181+
case TypeIdentifier::INT:
182+
case TypeIdentifier::STRING:
183+
if ($enumType) {
184+
return $enumType;
185+
}
186+
break;
187+
}
188+
189+
$t = Type::builtin($builtinType);
190+
191+
return $nullable ? Type::nullable($t) : $t;
192+
}
193+
194+
return null;
195+
}
196+
55197
public function getTypes(string $class, string $property, array $context = []): ?array
56198
{
199+
trigger_deprecation('symfony/doctrine-bridge', '7.1', 'The "%s()" method is deprecated, use "%s::getType()" instead.', __METHOD__, self::class);
200+
57201
if (null === $metadata = $this->getMetadata($class)) {
58202
return null;
59203
}
@@ -70,10 +214,10 @@ public function getTypes(string $class, string $property, array $context = []):
70214
$nullable = false;
71215
}
72216

73-
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $class)];
217+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, $class)];
74218
}
75219

76-
$collectionKeyType = Type::BUILTIN_TYPE_INT;
220+
$collectionKeyType = LegacyType::BUILTIN_TYPE_INT;
77221

78222
if ($metadata instanceof ClassMetadata) {
79223
$associationMapping = $metadata->getAssociationMapping($property);
@@ -101,61 +245,61 @@ public function getTypes(string $class, string $property, array $context = []):
101245
}
102246
}
103247

104-
if (!$collectionKeyType = $this->getPhpType($typeOfField)) {
248+
if (!$collectionKeyType = $this->getPhpType($typeOfField)?->value) {
105249
return null;
106250
}
107251
}
108252
}
109253

110-
return [new Type(
111-
Type::BUILTIN_TYPE_OBJECT,
254+
return [new LegacyType(
255+
LegacyType::BUILTIN_TYPE_OBJECT,
112256
false,
113257
Collection::class,
114258
true,
115-
new Type($collectionKeyType),
116-
new Type(Type::BUILTIN_TYPE_OBJECT, false, $class)
259+
new LegacyType($collectionKeyType),
260+
new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, $class)
117261
)];
118262
}
119263

120264
if ($metadata instanceof ClassMetadata && isset($metadata->embeddedClasses[$property])) {
121-
return [new Type(Type::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class'])];
265+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class'])];
122266
}
123267

124268
if ($metadata->hasField($property)) {
125269
$typeOfField = $metadata->getTypeOfField($property);
126270

127-
if (!$builtinType = $this->getPhpType($typeOfField)) {
271+
if (!$builtinType = $this->getPhpType($typeOfField)?->value) {
128272
return null;
129273
}
130274

131275
$nullable = $metadata instanceof ClassMetadata && $metadata->isNullable($property);
132276
$enumType = null;
133277
if (null !== $enumClass = $metadata->getFieldMapping($property)['enumType'] ?? null) {
134-
$enumType = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $enumClass);
278+
$enumType = new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, $enumClass);
135279
}
136280

137281
switch ($builtinType) {
138-
case Type::BUILTIN_TYPE_OBJECT:
282+
case LegacyType::BUILTIN_TYPE_OBJECT:
139283
switch ($typeOfField) {
140284
case Types::DATE_MUTABLE:
141285
case Types::DATETIME_MUTABLE:
142286
case Types::DATETIMETZ_MUTABLE:
143287
case 'vardatetime':
144288
case Types::TIME_MUTABLE:
145-
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')];
289+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')];
146290

147291
case Types::DATE_IMMUTABLE:
148292
case Types::DATETIME_IMMUTABLE:
149293
case Types::DATETIMETZ_IMMUTABLE:
150294
case Types::TIME_IMMUTABLE:
151-
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')];
295+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')];
152296

153297
case Types::DATEINTERVAL:
154-
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')];
298+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')];
155299
}
156300

157301
break;
158-
case Type::BUILTIN_TYPE_ARRAY:
302+
case LegacyType::BUILTIN_TYPE_ARRAY:
159303
switch ($typeOfField) {
160304
case 'array': // DBAL < 4
161305
case 'json_array': // DBAL < 3
@@ -164,21 +308,21 @@ public function getTypes(string $class, string $property, array $context = []):
164308
return null;
165309
}
166310

167-
return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)];
311+
return [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, $nullable, null, true)];
168312

169313
case Types::SIMPLE_ARRAY:
170-
return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), $enumType ?? new Type(Type::BUILTIN_TYPE_STRING))];
314+
return [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, $nullable, null, true, new LegacyType(LegacyType::BUILTIN_TYPE_INT), $enumType ?? new LegacyType(LegacyType::BUILTIN_TYPE_STRING))];
171315
}
172316
break;
173-
case Type::BUILTIN_TYPE_INT:
174-
case Type::BUILTIN_TYPE_STRING:
317+
case LegacyType::BUILTIN_TYPE_INT:
318+
case LegacyType::BUILTIN_TYPE_STRING:
175319
if ($enumType) {
176320
return [$enumType];
177321
}
178322
break;
179323
}
180324

181-
return [new Type($builtinType, $nullable)];
325+
return [new LegacyType($builtinType, $nullable)];
182326
}
183327

184328
return null;
@@ -241,20 +385,20 @@ private function isAssociationNullable(array|AssociationMapping $associationMapp
241385
/**
242386
* Gets the corresponding built-in PHP type.
243387
*/
244-
private function getPhpType(string $doctrineType): ?string
388+
private function getPhpType(string $doctrineType): ?TypeIdentifier
245389
{
246390
return match ($doctrineType) {
247391
Types::SMALLINT,
248-
Types::INTEGER => Type::BUILTIN_TYPE_INT,
249-
Types::FLOAT => Type::BUILTIN_TYPE_FLOAT,
392+
Types::INTEGER => TypeIdentifier::INT,
393+
Types::FLOAT => TypeIdentifier::FLOAT,
250394
Types::BIGINT,
251395
Types::STRING,
252396
Types::TEXT,
253397
Types::GUID,
254-
Types::DECIMAL => Type::BUILTIN_TYPE_STRING,
255-
Types::BOOLEAN => Type::BUILTIN_TYPE_BOOL,
398+
Types::DECIMAL => TypeIdentifier::STRING,
399+
Types::BOOLEAN => TypeIdentifier::BOOL,
256400
Types::BLOB,
257-
Types::BINARY => Type::BUILTIN_TYPE_RESOURCE,
401+
Types::BINARY => TypeIdentifier::RESOURCE,
258402
'object', // DBAL < 4
259403
Types::DATE_MUTABLE,
260404
Types::DATETIME_MUTABLE,
@@ -265,10 +409,10 @@ private function getPhpType(string $doctrineType): ?string
265409
Types::DATETIME_IMMUTABLE,
266410
Types::DATETIMETZ_IMMUTABLE,
267411
Types::TIME_IMMUTABLE,
268-
Types::DATEINTERVAL => Type::BUILTIN_TYPE_OBJECT,
412+
Types::DATEINTERVAL => TypeIdentifier::OBJECT,
269413
'array', // DBAL < 4
270414
'json_array', // DBAL < 3
271-
Types::SIMPLE_ARRAY => Type::BUILTIN_TYPE_ARRAY,
415+
Types::SIMPLE_ARRAY => TypeIdentifier::ARRAY,
272416
default => null,
273417
};
274418
}

0 commit comments

Comments
 (0)