Skip to content

Commit 8604fb7

Browse files
mtarldKorbeil
andcommitted
[PropertyInfo] Deprecate PropertyInfo Type
Co-authored-by: Baptiste Leduc <[email protected]>
1 parent 204c741 commit 8604fb7

File tree

52 files changed

+2971
-1354
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

+2971
-1354
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: 174 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
2525
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
2626
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
27-
use Symfony\Component\PropertyInfo\Type;
27+
use Symfony\Component\PropertyInfo\Type as LegacyType;
28+
use Symfony\Component\TypeInfo\Type;
29+
use Symfony\Component\TypeInfo\TypeIdentifier;
2830

2931
/**
3032
* Extracts data using Doctrine ORM and ODM metadata.
@@ -55,7 +57,7 @@ public function getProperties(string $class, array $context = []): ?array
5557
return $properties;
5658
}
5759

58-
public function getTypes(string $class, string $property, array $context = []): ?array
60+
public function getType(string $class, string $property, array $context = []): ?Type
5961
{
6062
if (null === $metadata = $this->getMetadata($class)) {
6163
return null;
@@ -67,16 +69,17 @@ public function getTypes(string $class, string $property, array $context = []):
6769
if ($metadata->isSingleValuedAssociation($property)) {
6870
if ($metadata instanceof ClassMetadata) {
6971
$associationMapping = $metadata->getAssociationMapping($property);
70-
7172
$nullable = $this->isAssociationNullable($associationMapping);
7273
} else {
7374
$nullable = false;
7475
}
7576

76-
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $class)];
77+
$t = Type::object($class);
78+
79+
return $nullable ? Type::nullable($t) : $t;
7780
}
7881

79-
$collectionKeyType = Type::BUILTIN_TYPE_INT;
82+
$collectionKeyType = TypeIdentifier::INT;
8083

8184
if ($metadata instanceof ClassMetadata) {
8285
$associationMapping = $metadata->getAssociationMapping($property);
@@ -110,55 +113,195 @@ public function getTypes(string $class, string $property, array $context = []):
110113
}
111114
}
112115

113-
return [new Type(
114-
Type::BUILTIN_TYPE_OBJECT,
116+
return Type::collection(Type::object(Collection::class), Type::object($class), Type::builtin($collectionKeyType));
117+
}
118+
119+
if ($metadata instanceof ClassMetadata && isset($metadata->embeddedClasses[$property])) {
120+
return Type::object(self::getMappingValue($metadata->embeddedClasses[$property], 'class'));
121+
}
122+
123+
if ($metadata->hasField($property)) {
124+
$typeOfField = $metadata->getTypeOfField($property);
125+
126+
if (!$builtinType = $this->getPhpType($typeOfField)) {
127+
return null;
128+
}
129+
130+
$nullable = $metadata instanceof ClassMetadata && $metadata->isNullable($property);
131+
$enumType = null;
132+
if (null !== $enumClass = self::getMappingValue($metadata->getFieldMapping($property), 'enumType') ?? null) {
133+
$enumType = Type::enum($enumClass);
134+
$enumType = $nullable ? Type::nullable($enumType) : $enumType;
135+
}
136+
137+
switch ($builtinType) {
138+
case TypeIdentifier::OBJECT:
139+
switch ($typeOfField) {
140+
case Types::DATE_MUTABLE:
141+
case Types::DATETIME_MUTABLE:
142+
case Types::DATETIMETZ_MUTABLE:
143+
case 'vardatetime':
144+
case Types::TIME_MUTABLE:
145+
$t = Type::object(\DateTime::class);
146+
147+
return $nullable ? Type::nullable($t) : $t;
148+
149+
case Types::DATE_IMMUTABLE:
150+
case Types::DATETIME_IMMUTABLE:
151+
case Types::DATETIMETZ_IMMUTABLE:
152+
case Types::TIME_IMMUTABLE:
153+
$t = Type::object(\DateTimeImmutable::class);
154+
155+
return $nullable ? Type::nullable($t) : $t;
156+
157+
case Types::DATEINTERVAL:
158+
$t = Type::object(\DateInterval::class);
159+
160+
return $nullable ? Type::nullable($t) : $t;
161+
}
162+
163+
break;
164+
case TypeIdentifier::ARRAY:
165+
switch ($typeOfField) {
166+
case 'array': // DBAL < 4
167+
case 'json_array': // DBAL < 3
168+
// return null if $enumType is set, because we can't determine if collectionKeyType is string or int
169+
if ($enumType) {
170+
return null;
171+
}
172+
173+
$t = Type::array();
174+
175+
return $nullable ? Type::nullable($t) : $t;
176+
177+
case Types::SIMPLE_ARRAY:
178+
$t = Type::list($enumType ?? Type::string());
179+
180+
return $nullable ? Type::nullable($t) : $t;
181+
}
182+
break;
183+
case TypeIdentifier::INT:
184+
case TypeIdentifier::STRING:
185+
if ($enumType) {
186+
return $enumType;
187+
}
188+
break;
189+
}
190+
191+
$t = Type::builtin($builtinType);
192+
193+
return $nullable ? Type::nullable($t) : $t;
194+
}
195+
196+
return null;
197+
}
198+
199+
public function getTypes(string $class, string $property, array $context = []): ?array
200+
{
201+
trigger_deprecation('symfony/doctrine-bridge', '7.1', 'The "%s()" method is deprecated, use "%s::getType()" instead.', __METHOD__, self::class);
202+
203+
if (null === $metadata = $this->getMetadata($class)) {
204+
return null;
205+
}
206+
207+
if ($metadata->hasAssociation($property)) {
208+
$class = $metadata->getAssociationTargetClass($property);
209+
210+
if ($metadata->isSingleValuedAssociation($property)) {
211+
if ($metadata instanceof ClassMetadata) {
212+
$associationMapping = $metadata->getAssociationMapping($property);
213+
214+
$nullable = $this->isAssociationNullable($associationMapping);
215+
} else {
216+
$nullable = false;
217+
}
218+
219+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, $class)];
220+
}
221+
222+
$collectionKeyType = LegacyType::BUILTIN_TYPE_INT;
223+
224+
if ($metadata instanceof ClassMetadata) {
225+
$associationMapping = $metadata->getAssociationMapping($property);
226+
227+
if (isset($associationMapping['indexBy'])) {
228+
$subMetadata = $this->entityManager->getClassMetadata($associationMapping['targetEntity']);
229+
230+
// Check if indexBy value is a property
231+
$fieldName = $associationMapping['indexBy'];
232+
if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) {
233+
$fieldName = $subMetadata->getFieldForColumn($associationMapping['indexBy']);
234+
// Not a property, maybe a column name?
235+
if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) {
236+
// Maybe the column name is the association join column?
237+
$associationMapping = $subMetadata->getAssociationMapping($fieldName);
238+
239+
$indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($fieldName);
240+
$subMetadata = $this->entityManager->getClassMetadata($associationMapping['targetEntity']);
241+
242+
// Not a property, maybe a column name?
243+
if (null === ($typeOfField = $subMetadata->getTypeOfField($indexProperty))) {
244+
$fieldName = $subMetadata->getFieldForColumn($indexProperty);
245+
$typeOfField = $subMetadata->getTypeOfField($fieldName);
246+
}
247+
}
248+
}
249+
250+
if (!$collectionKeyType = $this->getPhpType($typeOfField)?->value) {
251+
return null;
252+
}
253+
}
254+
}
255+
256+
return [new LegacyType(
257+
LegacyType::BUILTIN_TYPE_OBJECT,
115258
false,
116259
Collection::class,
117260
true,
118-
new Type($collectionKeyType),
119-
new Type(Type::BUILTIN_TYPE_OBJECT, false, $class)
261+
new LegacyType($collectionKeyType),
262+
new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, $class)
120263
)];
121264
}
122265

123266
if ($metadata instanceof ClassMetadata && isset($metadata->embeddedClasses[$property])) {
124-
return [new Type(Type::BUILTIN_TYPE_OBJECT, false, self::getMappingValue($metadata->embeddedClasses[$property], 'class'))];
267+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class'])];
125268
}
126269

127270
if ($metadata->hasField($property)) {
128271
$typeOfField = $metadata->getTypeOfField($property);
129272

130-
if (!$builtinType = $this->getPhpType($typeOfField)) {
273+
if (!$builtinType = $this->getPhpType($typeOfField)?->value) {
131274
return null;
132275
}
133276

134277
$nullable = $metadata instanceof ClassMetadata && $metadata->isNullable($property);
135278
$enumType = null;
136-
if (null !== $enumClass = self::getMappingValue($metadata->getFieldMapping($property), 'enumType') ?? null) {
137-
$enumType = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $enumClass);
279+
if (null !== $enumClass = $metadata->getFieldMapping($property)['enumType'] ?? null) {
280+
$enumType = new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, $enumClass);
138281
}
139282

140283
switch ($builtinType) {
141-
case Type::BUILTIN_TYPE_OBJECT:
284+
case LegacyType::BUILTIN_TYPE_OBJECT:
142285
switch ($typeOfField) {
143286
case Types::DATE_MUTABLE:
144287
case Types::DATETIME_MUTABLE:
145288
case Types::DATETIMETZ_MUTABLE:
146289
case 'vardatetime':
147290
case Types::TIME_MUTABLE:
148-
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')];
291+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')];
149292

150293
case Types::DATE_IMMUTABLE:
151294
case Types::DATETIME_IMMUTABLE:
152295
case Types::DATETIMETZ_IMMUTABLE:
153296
case Types::TIME_IMMUTABLE:
154-
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')];
297+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')];
155298

156299
case Types::DATEINTERVAL:
157-
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')];
300+
return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')];
158301
}
159302

160303
break;
161-
case Type::BUILTIN_TYPE_ARRAY:
304+
case LegacyType::BUILTIN_TYPE_ARRAY:
162305
switch ($typeOfField) {
163306
case 'array': // DBAL < 4
164307
case 'json_array': // DBAL < 3
@@ -167,21 +310,21 @@ public function getTypes(string $class, string $property, array $context = []):
167310
return null;
168311
}
169312

170-
return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)];
313+
return [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, $nullable, null, true)];
171314

172315
case Types::SIMPLE_ARRAY:
173-
return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), $enumType ?? new Type(Type::BUILTIN_TYPE_STRING))];
316+
return [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, $nullable, null, true, new LegacyType(LegacyType::BUILTIN_TYPE_INT), $enumType ?? new LegacyType(LegacyType::BUILTIN_TYPE_STRING))];
174317
}
175318
break;
176-
case Type::BUILTIN_TYPE_INT:
177-
case Type::BUILTIN_TYPE_STRING:
319+
case LegacyType::BUILTIN_TYPE_INT:
320+
case LegacyType::BUILTIN_TYPE_STRING:
178321
if ($enumType) {
179322
return [$enumType];
180323
}
181324
break;
182325
}
183326

184-
return [new Type($builtinType, $nullable)];
327+
return [new LegacyType($builtinType, $nullable)];
185328
}
186329

187330
return null;
@@ -244,20 +387,20 @@ private function isAssociationNullable(array|AssociationMapping $associationMapp
244387
/**
245388
* Gets the corresponding built-in PHP type.
246389
*/
247-
private function getPhpType(string $doctrineType): ?string
390+
private function getPhpType(string $doctrineType): ?TypeIdentifier
248391
{
249392
return match ($doctrineType) {
250393
Types::SMALLINT,
251-
Types::INTEGER => Type::BUILTIN_TYPE_INT,
252-
Types::FLOAT => Type::BUILTIN_TYPE_FLOAT,
394+
Types::INTEGER => TypeIdentifier::INT,
395+
Types::FLOAT => TypeIdentifier::FLOAT,
253396
Types::BIGINT,
254397
Types::STRING,
255398
Types::TEXT,
256399
Types::GUID,
257-
Types::DECIMAL => Type::BUILTIN_TYPE_STRING,
258-
Types::BOOLEAN => Type::BUILTIN_TYPE_BOOL,
400+
Types::DECIMAL => TypeIdentifier::STRING,
401+
Types::BOOLEAN => TypeIdentifier::BOOL,
259402
Types::BLOB,
260-
Types::BINARY => Type::BUILTIN_TYPE_RESOURCE,
403+
Types::BINARY => TypeIdentifier::RESOURCE,
261404
'object', // DBAL < 4
262405
Types::DATE_MUTABLE,
263406
Types::DATETIME_MUTABLE,
@@ -268,10 +411,10 @@ private function getPhpType(string $doctrineType): ?string
268411
Types::DATETIME_IMMUTABLE,
269412
Types::DATETIMETZ_IMMUTABLE,
270413
Types::TIME_IMMUTABLE,
271-
Types::DATEINTERVAL => Type::BUILTIN_TYPE_OBJECT,
414+
Types::DATEINTERVAL => TypeIdentifier::OBJECT,
272415
'array', // DBAL < 4
273416
'json_array', // DBAL < 3
274-
Types::SIMPLE_ARRAY => Type::BUILTIN_TYPE_ARRAY,
417+
Types::SIMPLE_ARRAY => TypeIdentifier::ARRAY,
275418
default => null,
276419
};
277420
}

0 commit comments

Comments
 (0)