21
21
use Symfony \Component \PropertyInfo \PropertyAccessExtractorInterface ;
22
22
use Symfony \Component \PropertyInfo \PropertyListExtractorInterface ;
23
23
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 ;
25
27
26
28
/**
27
29
* Extracts data using Doctrine ORM and ODM metadata.
@@ -52,8 +54,150 @@ public function getProperties(string $class, array $context = []): ?array
52
54
return $ properties ;
53
55
}
54
56
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
+
55
197
public function getTypes (string $ class , string $ property , array $ context = []): ?array
56
198
{
199
+ trigger_deprecation ('symfony/doctrine-bridge ' , '7.1 ' , 'The "%s()" method is deprecated, use "%s::getType()" instead. ' , __METHOD__ , self ::class);
200
+
57
201
if (null === $ metadata = $ this ->getMetadata ($ class )) {
58
202
return null ;
59
203
}
@@ -70,10 +214,10 @@ public function getTypes(string $class, string $property, array $context = []):
70
214
$ nullable = false ;
71
215
}
72
216
73
- return [new Type (Type ::BUILTIN_TYPE_OBJECT , $ nullable , $ class )];
217
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_OBJECT , $ nullable , $ class )];
74
218
}
75
219
76
- $ collectionKeyType = Type ::BUILTIN_TYPE_INT ;
220
+ $ collectionKeyType = LegacyType ::BUILTIN_TYPE_INT ;
77
221
78
222
if ($ metadata instanceof ClassMetadata) {
79
223
$ associationMapping = $ metadata ->getAssociationMapping ($ property );
@@ -101,61 +245,61 @@ public function getTypes(string $class, string $property, array $context = []):
101
245
}
102
246
}
103
247
104
- if (!$ collectionKeyType = $ this ->getPhpType ($ typeOfField )) {
248
+ if (!$ collectionKeyType = $ this ->getPhpType ($ typeOfField )?->value ) {
105
249
return null ;
106
250
}
107
251
}
108
252
}
109
253
110
- return [new Type (
111
- Type ::BUILTIN_TYPE_OBJECT ,
254
+ return [new LegacyType (
255
+ LegacyType ::BUILTIN_TYPE_OBJECT ,
112
256
false ,
113
257
Collection::class,
114
258
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 )
117
261
)];
118
262
}
119
263
120
264
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 ' ])];
122
266
}
123
267
124
268
if ($ metadata ->hasField ($ property )) {
125
269
$ typeOfField = $ metadata ->getTypeOfField ($ property );
126
270
127
- if (!$ builtinType = $ this ->getPhpType ($ typeOfField )) {
271
+ if (!$ builtinType = $ this ->getPhpType ($ typeOfField )?->value ) {
128
272
return null ;
129
273
}
130
274
131
275
$ nullable = $ metadata instanceof ClassMetadata && $ metadata ->isNullable ($ property );
132
276
$ enumType = null ;
133
277
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 );
135
279
}
136
280
137
281
switch ($ builtinType ) {
138
- case Type ::BUILTIN_TYPE_OBJECT :
282
+ case LegacyType ::BUILTIN_TYPE_OBJECT :
139
283
switch ($ typeOfField ) {
140
284
case Types::DATE_MUTABLE :
141
285
case Types::DATETIME_MUTABLE :
142
286
case Types::DATETIMETZ_MUTABLE :
143
287
case 'vardatetime ' :
144
288
case Types::TIME_MUTABLE :
145
- return [new Type (Type ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateTime ' )];
289
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateTime ' )];
146
290
147
291
case Types::DATE_IMMUTABLE :
148
292
case Types::DATETIME_IMMUTABLE :
149
293
case Types::DATETIMETZ_IMMUTABLE :
150
294
case Types::TIME_IMMUTABLE :
151
- return [new Type (Type ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateTimeImmutable ' )];
295
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateTimeImmutable ' )];
152
296
153
297
case Types::DATEINTERVAL :
154
- return [new Type (Type ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateInterval ' )];
298
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateInterval ' )];
155
299
}
156
300
157
301
break ;
158
- case Type ::BUILTIN_TYPE_ARRAY :
302
+ case LegacyType ::BUILTIN_TYPE_ARRAY :
159
303
switch ($ typeOfField ) {
160
304
case 'array ' : // DBAL < 4
161
305
case 'json_array ' : // DBAL < 3
@@ -164,21 +308,21 @@ public function getTypes(string $class, string $property, array $context = []):
164
308
return null ;
165
309
}
166
310
167
- return [new Type (Type ::BUILTIN_TYPE_ARRAY , $ nullable , null , true )];
311
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_ARRAY , $ nullable , null , true )];
168
312
169
313
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 ))];
171
315
}
172
316
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 :
175
319
if ($ enumType ) {
176
320
return [$ enumType ];
177
321
}
178
322
break ;
179
323
}
180
324
181
- return [new Type ($ builtinType , $ nullable )];
325
+ return [new LegacyType ($ builtinType , $ nullable )];
182
326
}
183
327
184
328
return null ;
@@ -241,20 +385,20 @@ private function isAssociationNullable(array|AssociationMapping $associationMapp
241
385
/**
242
386
* Gets the corresponding built-in PHP type.
243
387
*/
244
- private function getPhpType (string $ doctrineType ): ?string
388
+ private function getPhpType (string $ doctrineType ): ?TypeIdentifier
245
389
{
246
390
return match ($ doctrineType ) {
247
391
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 ,
250
394
Types::BIGINT ,
251
395
Types::STRING ,
252
396
Types::TEXT ,
253
397
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 ,
256
400
Types::BLOB ,
257
- Types::BINARY => Type:: BUILTIN_TYPE_RESOURCE ,
401
+ Types::BINARY => TypeIdentifier:: RESOURCE ,
258
402
'object ' , // DBAL < 4
259
403
Types::DATE_MUTABLE ,
260
404
Types::DATETIME_MUTABLE ,
@@ -265,10 +409,10 @@ private function getPhpType(string $doctrineType): ?string
265
409
Types::DATETIME_IMMUTABLE ,
266
410
Types::DATETIMETZ_IMMUTABLE ,
267
411
Types::TIME_IMMUTABLE ,
268
- Types::DATEINTERVAL => Type:: BUILTIN_TYPE_OBJECT ,
412
+ Types::DATEINTERVAL => TypeIdentifier:: OBJECT ,
269
413
'array ' , // DBAL < 4
270
414
'json_array ' , // DBAL < 3
271
- Types::SIMPLE_ARRAY => Type:: BUILTIN_TYPE_ARRAY ,
415
+ Types::SIMPLE_ARRAY => TypeIdentifier:: ARRAY ,
272
416
default => null ,
273
417
};
274
418
}
0 commit comments