1
+ <?php
2
+
3
+ namespace Sg \DatatablesBundle \Maker ;
4
+
5
+
6
+ use Symfony \Bundle \MakerBundle \InputAwareMakerInterface ;
7
+ use Symfony \Bundle \MakerBundle \Maker \AbstractMaker ;
8
+ use Symfony \Bundle \MakerBundle \ConsoleStyle ;
9
+ use Symfony \Bundle \MakerBundle \MakerInterface ;
10
+ use Symfony \Component \Console \Command \Command ;
11
+ use Symfony \Component \Console \Input \InputInterface ;
12
+ use Symfony \Bundle \MakerBundle \InputConfiguration ;
13
+ use Symfony \Bundle \MakerBundle \DependencyBuilder ;
14
+ Use Symfony \Bundle \MakerBundle \Generator ;
15
+ use Symfony \Bundle \MakerBundle \Doctrine \DoctrineHelper ;
16
+ use Symfony \Component \Console \Input \InputArgument ;
17
+ use Symfony \Bundle \MakerBundle \Str ;
18
+ use Symfony \Bundle \MakerBundle \Validator ;
19
+ use Symfony \Bundle \TwigBundle ;
20
+ use Doctrine \Bundle \DoctrineBundle ;
21
+ use Sensio \Bundle \FrameworkExtraBundle \Configuration \ParamConverter ;
22
+ use Symfony \Component \Console \Question \Question ;
23
+ use Doctrine \ORM \Mapping \ClassMetadataInfo ;
24
+
25
+
26
+ class MakeDatatable extends AbstractMaker
27
+ {
28
+ private $ doctrineHelper ;
29
+ private $ baseSleleton ;
30
+ private $ columnTypes = [ 'ActionColumn ' => 'ActionColumn ' ];
31
+
32
+ public function __construct (DoctrineHelper $ doctrineHelper )
33
+ {
34
+ $ this ->doctrineHelper = $ doctrineHelper ;
35
+ $ this ->baseSleleton = realpath (__DIR__ .'/../Resources/views/skeleton ' );
36
+ }
37
+
38
+
39
+ public static function getCommandName (): string
40
+ {
41
+ return 'make:datatable ' ;
42
+ }
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ */
47
+ public function configureCommand (Command $ command , InputConfiguration $ inputConfig )
48
+ {
49
+ $ command
50
+ ->setDescription ('Creates Datable for Doctrine entity class ' )
51
+ ->addArgument ('entity-class ' , InputArgument::OPTIONAL , sprintf ('The class name of the entity to create CRUD (e.g. <fg=yellow>%s</>) ' , Str::asClassName (Str::getRandomTerm ())))
52
+ ->setHelp (file_get_contents (__DIR__ .'/../Resources/help/MakeDatatable.txt ' ))
53
+ ;
54
+ $ inputConfig ->setArgumentAsNonInteractive ('entity-class ' );
55
+ }
56
+
57
+ public function interact (InputInterface $ input , ConsoleStyle $ io , Command $ command )
58
+ {
59
+ if (null === $ input ->getArgument ('entity-class ' )) {
60
+ $ argument = $ command ->getDefinition ()->getArgument ('entity-class ' );
61
+ $ entities = $ this ->doctrineHelper ->getEntitiesForAutocomplete ();
62
+ $ question = new Question ($ argument ->getDescription ());
63
+ $ question ->setAutocompleterValues ($ entities );
64
+ $ value = $ io ->askQuestion ($ question );
65
+ $ input ->setArgument ('entity-class ' , $ value );
66
+ }
67
+ }
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ public function configureDependencies (DependencyBuilder $ dependencies )
73
+ {
74
+ }
75
+
76
+ public function generate (InputInterface $ input , ConsoleStyle $ io , Generator $ generator )
77
+ {
78
+ $ entityClassDetails = $ generator ->createClassNameDetails (
79
+ Validator::entityExists ($ input ->getArgument ('entity-class ' ), $ this ->doctrineHelper ->getEntitiesForAutocomplete ()),
80
+ 'Entity \\'
81
+ );
82
+
83
+
84
+ $ entityDoctrineDetails = $ this ->doctrineHelper ->createDoctrineDetails ($ entityClassDetails ->getFullName ());
85
+
86
+ $ datatableClassDetails = $ generator ->createClassNameDetails (
87
+ $ entityClassDetails ->getRelativeNameWithoutSuffix (),
88
+ 'Datatables \\' ,
89
+ 'Datatable '
90
+ );
91
+
92
+ $ className = $ datatableClassDetails ->getShortName ();
93
+ $ entityClassLowerCase = strtolower ($ className );
94
+
95
+ $ metadata = $ this ->getEntityMetadata ($ entityClassDetails ->getFullName ());
96
+ $ fields = $ this ->getFieldsFromMetadata ($ metadata );
97
+
98
+ sort ($ this ->columnTypes );
99
+ $ generator ->generateClass (
100
+ $ datatableClassDetails ->getFullName (),
101
+ $ this ->baseSleleton . '/Datatable.tpl.php ' ,
102
+ [
103
+ 'bounded_full_class_name ' => $ entityClassDetails ->getFullName (),
104
+ 'bounded_class_name ' => $ entityClassDetails ->getShortName (),
105
+ 'fields ' => $ fields ,
106
+ 'class_name ' => $ className ,
107
+ 'datatable_name ' => $ entityClassLowerCase .'_datatable ' ,
108
+ 'route_pref ' => $ entityClassLowerCase ,
109
+ 'column_types ' => $ this ->columnTypes ,
110
+ 'id ' => $ this ->getIdentifierFromMetadata ($ metadata ),
111
+ ]
112
+ );
113
+
114
+ $ generator ->writeChanges ();
115
+
116
+ }
117
+
118
+ //-------------------------------------------------
119
+ // Helper
120
+ //-------------------------------------------------
121
+
122
+ /**
123
+ * Parse fields.
124
+ *
125
+ * @param string $input
126
+ *
127
+ * @return array
128
+ */
129
+ private static function parseFields ($ input )
130
+ {
131
+ $ fields = array ();
132
+
133
+ foreach (explode (' ' , $ input ) as $ value ) {
134
+ $ elements = explode (': ' , $ value );
135
+
136
+ $ row = array ();
137
+ $ row ['property ' ] = $ elements [0 ];
138
+ $ row ['column_type ' ] = 'Column::class ' ;
139
+ $ row ['data ' ] = null ;
140
+ $ row ['title ' ] = ucwords (str_replace ('. ' , ' ' , $ elements [0 ]));
141
+
142
+ if (isset ($ elements [1 ])) {
143
+ switch ($ elements [1 ]) {
144
+ case 'datetime ' :
145
+ $ row ['column_type ' ] = 'DateTimeColumn::class ' ;
146
+ break ;
147
+ case 'boolean ' :
148
+ $ row ['column_type ' ] = 'BooleanColumn::class ' ;
149
+ break ;
150
+ }
151
+ }
152
+
153
+ $ fields [] = $ row ;
154
+ }
155
+
156
+ return $ fields ;
157
+ }
158
+
159
+ private function getEntityMetadata ($ class )
160
+ {
161
+ return $ this ->doctrineHelper ->getMetadata ($ class , true );
162
+ }
163
+
164
+ /**
165
+ * Get Id from metadata.
166
+ *
167
+ * @param array $metadata
168
+ *
169
+ * @return mixed
170
+ * @throws Exception
171
+ */
172
+ private function getIdentifierFromMetadata (ClassMetadataInfo $ metadata )
173
+ {
174
+ if (count ($ metadata ->identifier ) > 1 ) {
175
+ throw new Exception ('CreateDatatableCommand::getIdentifierFromMetadata(): The Datatable generator does not support entities with multiple primary keys. ' );
176
+ }
177
+
178
+ return $ metadata ->identifier ;
179
+ }
180
+
181
+ /**
182
+ * Returns an array of fields. Fields can be both column fields and
183
+ * association fields.
184
+ *
185
+ * @param ClassMetadataInfo $metadata
186
+ *
187
+ * @return array $fields
188
+ */
189
+ private function getFieldsFromMetadata (ClassMetadataInfo $ metadata )
190
+ {
191
+ $ fields = array ();
192
+
193
+ foreach ($ metadata ->fieldMappings as $ field ) {
194
+ $ row = array ();
195
+ $ row ['property ' ] = $ field ['fieldName ' ];
196
+
197
+ switch ($ field ['type ' ]) {
198
+ case 'datetime ' :
199
+ $ row ['column_type ' ] = 'DateTimeColumn::class ' ;
200
+ break ;
201
+ case 'boolean ' :
202
+ $ row ['column_type ' ] = 'BooleanColumn::class ' ;
203
+ break ;
204
+ default :
205
+ $ row ['column_type ' ] = 'Column::class ' ;
206
+ }
207
+
208
+ $ row ['title ' ] = ucwords ($ field ['fieldName ' ]);
209
+ $ row ['data ' ] = null ;
210
+ $ fields [] = $ row ;
211
+ if (!isset ($ this ->columnTypes [$ row ['column_type ' ]])) {
212
+ $ this ->columnTypes [$ row ['column_type ' ]] = substr ($ row ['column_type ' ], 0 , -7 );
213
+ }
214
+
215
+ }
216
+
217
+ foreach ($ metadata ->associationMappings as $ relation ) {
218
+ $ targetClass = $ relation ['targetEntity ' ];
219
+ $ targetMetadata = $ this ->getEntityMetadata ($ targetClass , true );
220
+
221
+ foreach ($ targetMetadata ->fieldMappings as $ field ) {
222
+ $ row = array ();
223
+ $ row ['property ' ] = $ relation ['fieldName ' ].'. ' .$ field ['fieldName ' ];
224
+ $ row ['column_type ' ] = 'Column::class ' ;
225
+ $ row ['title ' ] = ucwords (str_replace ('. ' , ' ' , $ row ['property ' ]));
226
+ if ($ relation ['type ' ] === ClassMetadataInfo::ONE_TO_MANY || $ relation ['type ' ] === ClassMetadataInfo::MANY_TO_MANY ) {
227
+ $ row ['data ' ] = $ relation ['fieldName ' ].'[, ]. ' .$ field ['fieldName ' ];
228
+ } else {
229
+ $ row ['data ' ] = null ;
230
+ }
231
+ $ fields [] = $ row ;
232
+ }
233
+ }
234
+
235
+ return $ fields ;
236
+ }
237
+ }
0 commit comments