24
24
use Symfony \Component \PropertyInfo \PropertyAccessExtractorInterface ;
25
25
use Symfony \Component \PropertyInfo \PropertyListExtractorInterface ;
26
26
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 ;
28
30
29
31
/**
30
32
* Extracts data using Doctrine ORM and ODM metadata.
@@ -55,7 +57,7 @@ public function getProperties(string $class, array $context = []): ?array
55
57
return $ properties ;
56
58
}
57
59
58
- public function getTypes (string $ class , string $ property , array $ context = []): ?array
60
+ public function getType (string $ class , string $ property , array $ context = []): ?Type
59
61
{
60
62
if (null === $ metadata = $ this ->getMetadata ($ class )) {
61
63
return null ;
@@ -67,16 +69,17 @@ public function getTypes(string $class, string $property, array $context = []):
67
69
if ($ metadata ->isSingleValuedAssociation ($ property )) {
68
70
if ($ metadata instanceof ClassMetadata) {
69
71
$ associationMapping = $ metadata ->getAssociationMapping ($ property );
70
-
71
72
$ nullable = $ this ->isAssociationNullable ($ associationMapping );
72
73
} else {
73
74
$ nullable = false ;
74
75
}
75
76
76
- return [new Type (Type::BUILTIN_TYPE_OBJECT , $ nullable , $ class )];
77
+ $ t = Type::object ($ class );
78
+
79
+ return $ nullable ? Type::nullable ($ t ) : $ t ;
77
80
}
78
81
79
- $ collectionKeyType = Type:: BUILTIN_TYPE_INT ;
82
+ $ collectionKeyType = TypeIdentifier:: INT ;
80
83
81
84
if ($ metadata instanceof ClassMetadata) {
82
85
$ associationMapping = $ metadata ->getAssociationMapping ($ property );
@@ -110,55 +113,195 @@ public function getTypes(string $class, string $property, array $context = []):
110
113
}
111
114
}
112
115
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 ,
115
258
false ,
116
259
Collection::class,
117
260
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 )
120
263
)];
121
264
}
122
265
123
266
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 ' ] )];
125
268
}
126
269
127
270
if ($ metadata ->hasField ($ property )) {
128
271
$ typeOfField = $ metadata ->getTypeOfField ($ property );
129
272
130
- if (!$ builtinType = $ this ->getPhpType ($ typeOfField )) {
273
+ if (!$ builtinType = $ this ->getPhpType ($ typeOfField )?->value ) {
131
274
return null ;
132
275
}
133
276
134
277
$ nullable = $ metadata instanceof ClassMetadata && $ metadata ->isNullable ($ property );
135
278
$ 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 );
138
281
}
139
282
140
283
switch ($ builtinType ) {
141
- case Type ::BUILTIN_TYPE_OBJECT :
284
+ case LegacyType ::BUILTIN_TYPE_OBJECT :
142
285
switch ($ typeOfField ) {
143
286
case Types::DATE_MUTABLE :
144
287
case Types::DATETIME_MUTABLE :
145
288
case Types::DATETIMETZ_MUTABLE :
146
289
case 'vardatetime ' :
147
290
case Types::TIME_MUTABLE :
148
- return [new Type (Type ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateTime ' )];
291
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateTime ' )];
149
292
150
293
case Types::DATE_IMMUTABLE :
151
294
case Types::DATETIME_IMMUTABLE :
152
295
case Types::DATETIMETZ_IMMUTABLE :
153
296
case Types::TIME_IMMUTABLE :
154
- return [new Type (Type ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateTimeImmutable ' )];
297
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateTimeImmutable ' )];
155
298
156
299
case Types::DATEINTERVAL :
157
- return [new Type (Type ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateInterval ' )];
300
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_OBJECT , $ nullable , 'DateInterval ' )];
158
301
}
159
302
160
303
break ;
161
- case Type ::BUILTIN_TYPE_ARRAY :
304
+ case LegacyType ::BUILTIN_TYPE_ARRAY :
162
305
switch ($ typeOfField ) {
163
306
case 'array ' : // DBAL < 4
164
307
case 'json_array ' : // DBAL < 3
@@ -167,21 +310,21 @@ public function getTypes(string $class, string $property, array $context = []):
167
310
return null ;
168
311
}
169
312
170
- return [new Type (Type ::BUILTIN_TYPE_ARRAY , $ nullable , null , true )];
313
+ return [new LegacyType (LegacyType ::BUILTIN_TYPE_ARRAY , $ nullable , null , true )];
171
314
172
315
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 ))];
174
317
}
175
318
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 :
178
321
if ($ enumType ) {
179
322
return [$ enumType ];
180
323
}
181
324
break ;
182
325
}
183
326
184
- return [new Type ($ builtinType , $ nullable )];
327
+ return [new LegacyType ($ builtinType , $ nullable )];
185
328
}
186
329
187
330
return null ;
@@ -244,20 +387,20 @@ private function isAssociationNullable(array|AssociationMapping $associationMapp
244
387
/**
245
388
* Gets the corresponding built-in PHP type.
246
389
*/
247
- private function getPhpType (string $ doctrineType ): ?string
390
+ private function getPhpType (string $ doctrineType ): ?TypeIdentifier
248
391
{
249
392
return match ($ doctrineType ) {
250
393
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 ,
253
396
Types::BIGINT ,
254
397
Types::STRING ,
255
398
Types::TEXT ,
256
399
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 ,
259
402
Types::BLOB ,
260
- Types::BINARY => Type:: BUILTIN_TYPE_RESOURCE ,
403
+ Types::BINARY => TypeIdentifier:: RESOURCE ,
261
404
'object ' , // DBAL < 4
262
405
Types::DATE_MUTABLE ,
263
406
Types::DATETIME_MUTABLE ,
@@ -268,10 +411,10 @@ private function getPhpType(string $doctrineType): ?string
268
411
Types::DATETIME_IMMUTABLE ,
269
412
Types::DATETIMETZ_IMMUTABLE ,
270
413
Types::TIME_IMMUTABLE ,
271
- Types::DATEINTERVAL => Type:: BUILTIN_TYPE_OBJECT ,
414
+ Types::DATEINTERVAL => TypeIdentifier:: OBJECT ,
272
415
'array ' , // DBAL < 4
273
416
'json_array ' , // DBAL < 3
274
- Types::SIMPLE_ARRAY => Type:: BUILTIN_TYPE_ARRAY ,
417
+ Types::SIMPLE_ARRAY => TypeIdentifier:: ARRAY ,
275
418
default => null ,
276
419
};
277
420
}
0 commit comments