10
10
use Doctrine \ORM \Mapping \FieldMapping ;
11
11
use Doctrine \Persistence \Mapping \MappingException ;
12
12
use InvalidArgumentException ;
13
+ use JsonException ;
13
14
use Symfony \Component \Console \Completion \CompletionInput ;
14
15
use Symfony \Component \Console \Completion \CompletionSuggestions ;
15
16
use Symfony \Component \Console \Input \InputArgument ;
@@ -52,27 +53,44 @@ final class MappingDescribeCommand extends AbstractEntityManagerCommand
52
53
protected function configure (): void
53
54
{
54
55
$ this ->setName ('orm:mapping:describe ' )
55
- ->addArgument ('entityName ' , InputArgument::REQUIRED , 'Full or partial name of entity ' )
56
- ->setDescription ('Display information about mapped objects ' )
57
- ->addOption ('em ' , null , InputOption::VALUE_REQUIRED , 'Name of the entity manager to operate on ' )
58
- ->setHelp (<<<'EOT'
56
+ ->addArgument ('entityName ' , InputArgument::REQUIRED , 'Full or partial name of entity ' )
57
+ ->setDescription ('Display information about mapped objects ' )
58
+ ->addOption ('em ' , null , InputOption::VALUE_REQUIRED , 'Name of the entity manager to operate on ' )
59
+ ->addOption (
60
+ 'format ' ,
61
+ null ,
62
+ InputOption::VALUE_REQUIRED ,
63
+ 'Output format (text, json) ' ,
64
+ 'text ' ,
65
+ array_map (static fn (MappingDescribeCommandFormat $ format ) => $ format ->value , MappingDescribeCommandFormat::cases ()),
66
+ )
67
+ ->setHelp (<<<'EOT'
59
68
The %command.full_name% command describes the metadata for the given full or partial entity class name.
60
69
61
70
<info>%command.full_name%</info> My\Namespace\Entity\MyEntity
62
71
63
72
Or:
64
73
65
74
<info>%command.full_name%</info> MyEntity
75
+
76
+ To output the metadata in JSON format, use the <info>--format</info> option:
77
+
78
+ <info>%command.full_name% My\Namespace\Entity\MyEntity --format=json</info>
79
+
80
+ To use a specific entity manager (e.g., for multi-DB projects), use the <info>--em</info> option:
81
+
82
+ <info>%command.full_name% My\Namespace\Entity\MyEntity --em=my_custom_entity_manager</info>
83
+
66
84
EOT);
67
85
}
68
86
69
87
protected function execute (InputInterface $ input , OutputInterface $ output ): int
70
88
{
71
- $ ui = new SymfonyStyle ($ input , $ output );
72
-
89
+ $ ui = new SymfonyStyle ($ input , $ output );
73
90
$ entityManager = $ this ->getEntityManager ($ input );
91
+ $ format = MappingDescribeCommandFormat::from ($ input ->getOption ('format ' ));
74
92
75
- $ this ->displayEntity ($ input ->getArgument ('entityName ' ), $ entityManager , $ ui );
93
+ $ this ->displayEntity ($ input ->getArgument ('entityName ' ), $ entityManager , $ ui, $ format );
76
94
77
95
return 0 ;
78
96
}
@@ -89,6 +107,10 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti
89
107
90
108
$ suggestions ->suggestValues (array_values ($ entities ));
91
109
}
110
+
111
+ if ($ input ->mustSuggestOptionValuesFor ('format ' )) {
112
+ $ suggestions ->suggestValues (array_map (static fn (MappingDescribeCommandFormat $ format ) => $ format ->value , MappingDescribeCommandFormat::cases ()));
113
+ }
92
114
}
93
115
94
116
/**
@@ -100,9 +122,47 @@ private function displayEntity(
100
122
string $ entityName ,
101
123
EntityManagerInterface $ entityManager ,
102
124
SymfonyStyle $ ui ,
125
+ MappingDescribeCommandFormat $ format ,
103
126
): void {
104
127
$ metadata = $ this ->getClassMetadata ($ entityName , $ entityManager );
105
128
129
+ if ($ format === MappingDescribeCommandFormat::JSON ) {
130
+ $ ui ->text (json_encode (
131
+ [
132
+ 'name ' => $ metadata ->name ,
133
+ 'rootEntityName ' => $ metadata ->rootEntityName ,
134
+ 'customGeneratorDefinition ' => $ this ->formatValueToJson ($ metadata ->customGeneratorDefinition ),
135
+ 'customRepositoryClassName ' => $ metadata ->customRepositoryClassName ,
136
+ 'isMappedSuperclass ' => $ metadata ->isMappedSuperclass ,
137
+ 'isEmbeddedClass ' => $ metadata ->isEmbeddedClass ,
138
+ 'parentClasses ' => $ metadata ->parentClasses ,
139
+ 'subClasses ' => $ metadata ->subClasses ,
140
+ 'embeddedClasses ' => $ metadata ->embeddedClasses ,
141
+ 'identifier ' => $ metadata ->identifier ,
142
+ 'inheritanceType ' => $ metadata ->inheritanceType ,
143
+ 'discriminatorColumn ' => $ this ->formatValueToJson ($ metadata ->discriminatorColumn ),
144
+ 'discriminatorValue ' => $ metadata ->discriminatorValue ,
145
+ 'discriminatorMap ' => $ metadata ->discriminatorMap ,
146
+ 'generatorType ' => $ metadata ->generatorType ,
147
+ 'table ' => $ this ->formatValueToJson ($ metadata ->table ),
148
+ 'isIdentifierComposite ' => $ metadata ->isIdentifierComposite ,
149
+ 'containsForeignIdentifier ' => $ metadata ->containsForeignIdentifier ,
150
+ 'containsEnumIdentifier ' => $ metadata ->containsEnumIdentifier ,
151
+ 'sequenceGeneratorDefinition ' => $ this ->formatValueToJson ($ metadata ->sequenceGeneratorDefinition ),
152
+ 'changeTrackingPolicy ' => $ metadata ->changeTrackingPolicy ,
153
+ 'isVersioned ' => $ metadata ->isVersioned ,
154
+ 'versionField ' => $ metadata ->versionField ,
155
+ 'isReadOnly ' => $ metadata ->isReadOnly ,
156
+ 'entityListeners ' => $ metadata ->entityListeners ,
157
+ 'associationMappings ' => $ this ->formatMappingsToJson ($ metadata ->associationMappings ),
158
+ 'fieldMappings ' => $ this ->formatMappingsToJson ($ metadata ->fieldMappings ),
159
+ ],
160
+ JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR ,
161
+ ));
162
+
163
+ return ;
164
+ }
165
+
106
166
$ ui ->table (
107
167
['Field ' , 'Value ' ],
108
168
array_merge (
@@ -240,6 +300,22 @@ private function formatValue(mixed $value): string
240
300
throw new InvalidArgumentException (sprintf ('Do not know how to format value "%s" ' , print_r ($ value , true )));
241
301
}
242
302
303
+ /** @throws JsonException */
304
+ private function formatValueToJson (mixed $ value ): mixed
305
+ {
306
+ if (is_object ($ value )) {
307
+ $ value = (array ) $ value ;
308
+ }
309
+
310
+ if (is_array ($ value )) {
311
+ foreach ($ value as $ k => $ v ) {
312
+ $ value [$ k ] = $ this ->formatValueToJson ($ v );
313
+ }
314
+ }
315
+
316
+ return $ value ;
317
+ }
318
+
243
319
/**
244
320
* Add the given label and value to the two column table output
245
321
*
@@ -281,6 +357,22 @@ private function formatMappings(array $propertyMappings): array
281
357
return $ output ;
282
358
}
283
359
360
+ /**
361
+ * @param array<string, FieldMapping|AssociationMapping> $propertyMappings
362
+ *
363
+ * @return array<string, mixed>
364
+ */
365
+ private function formatMappingsToJson (array $ propertyMappings ): array
366
+ {
367
+ $ output = [];
368
+
369
+ foreach ($ propertyMappings as $ propertyName => $ mapping ) {
370
+ $ output [$ propertyName ] = $ this ->formatValueToJson ((array ) $ mapping );
371
+ }
372
+
373
+ return $ output ;
374
+ }
375
+
284
376
/**
285
377
* Format the entity listeners
286
378
*
0 commit comments