|
0
|
1 |
<?php |
|
|
2 |
|
|
|
3 |
/* |
|
|
4 |
* This file is part of the Symfony package. |
|
|
5 |
* |
|
|
6 |
* (c) Fabien Potencier <fabien@symfony.com> |
|
|
7 |
* |
|
|
8 |
* For the full copyright and license information, please view the LICENSE |
|
|
9 |
* file that was distributed with this source code. |
|
|
10 |
*/ |
|
|
11 |
|
|
|
12 |
namespace Sensio\Bundle\GeneratorBundle\Command; |
|
|
13 |
|
|
|
14 |
use Symfony\Component\Console\Input\InputArgument; |
|
|
15 |
use Symfony\Component\Console\Input\InputOption; |
|
|
16 |
use Symfony\Component\Console\Input\InputInterface; |
|
|
17 |
use Symfony\Component\Console\Output\OutputInterface; |
|
|
18 |
use Symfony\Component\Console\Output\Output; |
|
|
19 |
use Symfony\Component\Console\Command\Command; |
|
|
20 |
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator; |
|
|
21 |
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineFormGenerator; |
|
|
22 |
use Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper; |
|
|
23 |
use Sensio\Bundle\GeneratorBundle\Manipulator\RoutingManipulator; |
|
|
24 |
use Doctrine\ORM\Mapping\MappingException; |
|
|
25 |
|
|
|
26 |
/** |
|
|
27 |
* Generates a CRUD for a Doctrine entity. |
|
|
28 |
* |
|
|
29 |
* @author Fabien Potencier <fabien@symfony.com> |
|
|
30 |
*/ |
|
|
31 |
class GenerateDoctrineCrudCommand extends GenerateDoctrineCommand |
|
|
32 |
{ |
|
|
33 |
private $generator; |
|
|
34 |
private $formGenerator; |
|
|
35 |
|
|
|
36 |
/** |
|
|
37 |
* @see Command |
|
|
38 |
*/ |
|
|
39 |
protected function configure() |
|
|
40 |
{ |
|
|
41 |
$this |
|
|
42 |
->setDefinition(array( |
|
|
43 |
new InputOption('entity', '', InputOption::VALUE_REQUIRED, 'The entity class name to initialize (shortcut notation)'), |
|
|
44 |
new InputOption('route-prefix', '', InputOption::VALUE_REQUIRED, 'The route prefix'), |
|
|
45 |
new InputOption('with-write', '', InputOption::VALUE_NONE, 'Whether or not to generate create, new and delete actions'), |
|
|
46 |
new InputOption('format', '', InputOption::VALUE_REQUIRED, 'Use the format for configuration files (php, xml, yml, or annotation)', 'annotation'), |
|
|
47 |
)) |
|
|
48 |
->setDescription('Generates a CRUD based on a Doctrine entity') |
|
|
49 |
->setHelp(<<<EOT |
|
|
50 |
The <info>doctrine:generate:crud</info> command generates a CRUD based on a Doctrine entity. |
|
|
51 |
|
|
|
52 |
The default command only generates the list and show actions. |
|
|
53 |
|
|
|
54 |
<info>php app/console doctrine:generate:crud --entity=AcmeBlogBundle:Post --route-prefix=post_admin</info> |
|
|
55 |
|
|
|
56 |
Using the --with-write option allows to generate the new, edit and delete actions. |
|
|
57 |
|
|
|
58 |
<info>php app/console doctrine:generate:crud --entity=AcmeBlogBundle:Post --route-prefix=post_admin --with-write</info> |
|
|
59 |
EOT |
|
|
60 |
) |
|
|
61 |
->setName('doctrine:generate:crud') |
|
|
62 |
->setAliases(array('generate:doctrine:crud')) |
|
|
63 |
; |
|
|
64 |
} |
|
|
65 |
|
|
|
66 |
/** |
|
|
67 |
* @see Command |
|
|
68 |
*/ |
|
|
69 |
protected function execute(InputInterface $input, OutputInterface $output) |
|
|
70 |
{ |
|
|
71 |
$dialog = $this->getDialogHelper(); |
|
|
72 |
|
|
|
73 |
if ($input->isInteractive()) { |
|
|
74 |
if (!$dialog->askConfirmation($output, $dialog->getQuestion('Do you confirm generation', 'yes', '?'), true)) { |
|
|
75 |
$output->writeln('<error>Command aborted</error>'); |
|
|
76 |
|
|
|
77 |
return 1; |
|
|
78 |
} |
|
|
79 |
} |
|
|
80 |
|
|
|
81 |
$entity = Validators::validateEntityName($input->getOption('entity')); |
|
|
82 |
list($bundle, $entity) = $this->parseShortcutNotation($entity); |
|
|
83 |
|
|
|
84 |
$format = Validators::validateFormat($input->getOption('format')); |
|
|
85 |
$prefix = $this->getRoutePrefix($input, $entity); |
|
|
86 |
$withWrite = $input->getOption('with-write'); |
|
|
87 |
|
|
|
88 |
$dialog->writeSection($output, 'CRUD generation'); |
|
|
89 |
|
|
|
90 |
$entityClass = $this->getContainer()->get('doctrine')->getEntityNamespace($bundle).'\\'.$entity; |
|
|
91 |
$metadata = $this->getEntityMetadata($entityClass); |
|
|
92 |
$bundle = $this->getContainer()->get('kernel')->getBundle($bundle); |
|
|
93 |
|
|
|
94 |
$generator = $this->getGenerator(); |
|
|
95 |
$generator->generate($bundle, $entity, $metadata[0], $format, $prefix, $withWrite); |
|
|
96 |
|
|
|
97 |
$output->writeln('Generating the CRUD code: <info>OK</info>'); |
|
|
98 |
|
|
|
99 |
$errors = array(); |
|
|
100 |
$runner = $dialog->getRunner($output, $errors); |
|
|
101 |
|
|
|
102 |
// form |
|
|
103 |
if ($withWrite) { |
|
|
104 |
$this->generateForm($bundle, $entity, $metadata); |
|
|
105 |
$output->writeln('Generating the Form code: <info>OK</info>'); |
|
|
106 |
} |
|
|
107 |
|
|
|
108 |
// routing |
|
|
109 |
if ('annotation' != $format) { |
|
|
110 |
$runner($this->updateRouting($dialog, $input, $output, $bundle, $format, $entity, $prefix)); |
|
|
111 |
} |
|
|
112 |
|
|
|
113 |
$dialog->writeGeneratorSummary($output, $errors); |
|
|
114 |
} |
|
|
115 |
|
|
|
116 |
protected function interact(InputInterface $input, OutputInterface $output) |
|
|
117 |
{ |
|
|
118 |
$dialog = $this->getDialogHelper(); |
|
|
119 |
$dialog->writeSection($output, 'Welcome to the Doctrine2 CRUD generator'); |
|
|
120 |
|
|
|
121 |
// namespace |
|
|
122 |
$output->writeln(array( |
|
|
123 |
'', |
|
|
124 |
'This command helps you generate CRUD controllers and templates.', |
|
|
125 |
'', |
|
|
126 |
'First, you need to give the entity for which you want to generate a CRUD.', |
|
|
127 |
'You can give an entity that does not exist yet and the wizard will help', |
|
|
128 |
'you defining it.', |
|
|
129 |
'', |
|
|
130 |
'You must use the shortcut notation like <comment>AcmeBlogBundle:Post</comment>.', |
|
|
131 |
'', |
|
|
132 |
)); |
|
|
133 |
|
|
|
134 |
$entity = $dialog->askAndValidate($output, $dialog->getQuestion('The Entity shortcut name', $input->getOption('entity')), array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateEntityName'), false, $input->getOption('entity')); |
|
|
135 |
$input->setOption('entity', $entity); |
|
|
136 |
list($bundle, $entity) = $this->parseShortcutNotation($entity); |
|
|
137 |
|
|
|
138 |
// Entity exists? |
|
|
139 |
$entityClass = $this->getContainer()->get('doctrine')->getEntityNamespace($bundle).'\\'.$entity; |
|
|
140 |
$metadata = $this->getEntityMetadata($entityClass); |
|
|
141 |
|
|
|
142 |
// write? |
|
|
143 |
$withWrite = $input->getOption('with-write') ?: false; |
|
|
144 |
$output->writeln(array( |
|
|
145 |
'', |
|
|
146 |
'By default, the generator creates two actions: list and show.', |
|
|
147 |
'You can also ask it to generate "write" actions: new, update, and delete.', |
|
|
148 |
'', |
|
|
149 |
)); |
|
|
150 |
$withWrite = $dialog->askConfirmation($output, $dialog->getQuestion('Do you want to generate the "write" actions', $withWrite ? 'yes' : 'no', '?'), $withWrite); |
|
|
151 |
$input->setOption('with-write', $withWrite); |
|
|
152 |
|
|
|
153 |
// format |
|
|
154 |
$format = $input->getOption('format'); |
|
|
155 |
$output->writeln(array( |
|
|
156 |
'', |
|
|
157 |
'Determine the format to use for the generated CRUD.', |
|
|
158 |
'', |
|
|
159 |
)); |
|
|
160 |
$format = $dialog->askAndValidate($output, $dialog->getQuestion('Configuration format (yml, xml, php, or annotation)', $format), array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateFormat'), false, $format); |
|
|
161 |
$input->setOption('format', $format); |
|
|
162 |
|
|
|
163 |
// route prefix |
|
|
164 |
$prefix = $this->getRoutePrefix($input, $entity); |
|
|
165 |
$output->writeln(array( |
|
|
166 |
'', |
|
|
167 |
'Determine the routes prefix (all the routes will be "mounted" under this', |
|
|
168 |
'prefix: /prefix/, /prefix/new, ...).', |
|
|
169 |
'', |
|
|
170 |
)); |
|
|
171 |
$prefix = $dialog->ask($output, $dialog->getQuestion('Routes prefix', '/'.$prefix), '/'.$prefix); |
|
|
172 |
$input->setOption('route-prefix', $prefix); |
|
|
173 |
|
|
|
174 |
// summary |
|
|
175 |
$output->writeln(array( |
|
|
176 |
'', |
|
|
177 |
$this->getHelper('formatter')->formatBlock('Summary before generation', 'bg=blue;fg=white', true), |
|
|
178 |
'', |
|
|
179 |
sprintf("You are going to generate a CRUD controller for \"<info>%s:%s</info>\"", $bundle, $entity), |
|
|
180 |
sprintf("using the \"<info>%s</info>\" format.", $format), |
|
|
181 |
'', |
|
|
182 |
)); |
|
|
183 |
} |
|
|
184 |
|
|
|
185 |
/** |
|
|
186 |
* Tries to generate forms if they don't exist yet and if we need write operations on entities. |
|
|
187 |
*/ |
|
|
188 |
private function generateForm($bundle, $entity, $metadata) |
|
|
189 |
{ |
|
|
190 |
try { |
|
|
191 |
$this->getFormGenerator()->generate($bundle, $entity, $metadata[0]); |
|
|
192 |
} catch (\RuntimeException $e ) { |
|
|
193 |
// form already exists |
|
|
194 |
} |
|
|
195 |
} |
|
|
196 |
|
|
|
197 |
private function updateRouting($dialog, InputInterface $input, OutputInterface $output, $bundle, $format, $entity, $prefix) |
|
|
198 |
{ |
|
|
199 |
$auto = true; |
|
|
200 |
if ($input->isInteractive()) { |
|
|
201 |
$auto = $dialog->askConfirmation($output, $dialog->getQuestion('Confirm automatic update of the Routing', 'yes', '?'), true); |
|
|
202 |
} |
|
|
203 |
|
|
|
204 |
$output->write('Importing the CRUD routes: '); |
|
|
205 |
$this->getContainer()->get('filesystem')->mkdir($bundle->getPath().'/Resources/config/'); |
|
|
206 |
$routing = new RoutingManipulator($bundle->getPath().'/Resources/config/routing.yml'); |
|
|
207 |
$ret = $auto ? $routing->addResource($bundle->getName(), $format, '/'.$prefix, 'routing/'.strtolower(str_replace('\\', '_', $entity))) : false; |
|
|
208 |
if (!$ret) { |
|
|
209 |
$help = sprintf(" <comment>resource: \"@%s/Resources/config/routing/%s.%s\"</comment>\n", $bundle->getName(), strtolower(str_replace('\\', '_', $entity)), $format); |
|
|
210 |
$help .= sprintf(" <comment>prefix: /%s</comment>\n", $prefix); |
|
|
211 |
|
|
|
212 |
return array( |
|
|
213 |
'- Import the bundle\'s routing resource in the bundle routing file', |
|
|
214 |
sprintf(' (%s).', $bundle->getPath().'/Resources/config/routing.yml'), |
|
|
215 |
'', |
|
|
216 |
sprintf(' <comment>%s:</comment>', $bundle->getName().('' !== $prefix ? '_'.str_replace('/', '_', $prefix) : '')), |
|
|
217 |
$help, |
|
|
218 |
'', |
|
|
219 |
); |
|
|
220 |
} |
|
|
221 |
} |
|
|
222 |
|
|
|
223 |
protected function getRoutePrefix(InputInterface $input, $entity) |
|
|
224 |
{ |
|
|
225 |
$prefix = $input->getOption('route-prefix') ?: strtolower(str_replace(array('\\', '/'), '_', $entity)); |
|
|
226 |
|
|
|
227 |
if ($prefix && '/' === $prefix[0]) { |
|
|
228 |
$prefix = substr($prefix, 1); |
|
|
229 |
} |
|
|
230 |
|
|
|
231 |
return $prefix; |
|
|
232 |
} |
|
|
233 |
|
|
|
234 |
protected function getGenerator() |
|
|
235 |
{ |
|
|
236 |
if (null === $this->generator) { |
|
|
237 |
$this->generator = new DoctrineCrudGenerator($this->getContainer()->get('filesystem'), __DIR__.'/../Resources/skeleton/crud'); |
|
|
238 |
} |
|
|
239 |
|
|
|
240 |
return $this->generator; |
|
|
241 |
} |
|
|
242 |
|
|
|
243 |
public function setGenerator(DoctrineCrudGenerator $generator) |
|
|
244 |
{ |
|
|
245 |
$this->generator = $generator; |
|
|
246 |
} |
|
|
247 |
|
|
|
248 |
protected function getFormGenerator() |
|
|
249 |
{ |
|
|
250 |
if (null === $this->formGenerator) { |
|
|
251 |
$this->formGenerator = new DoctrineFormGenerator($this->getContainer()->get('filesystem'), __DIR__.'/../Resources/skeleton/form');; |
|
|
252 |
} |
|
|
253 |
|
|
|
254 |
return $this->formGenerator; |
|
|
255 |
} |
|
|
256 |
|
|
|
257 |
public function setFormGenerator(DoctrineFormGenerator $formGenerator) |
|
|
258 |
{ |
|
|
259 |
$this->formGenerator = $formGenerator; |
|
|
260 |
} |
|
|
261 |
|
|
|
262 |
protected function getDialogHelper() |
|
|
263 |
{ |
|
|
264 |
$dialog = $this->getHelperSet()->get('dialog'); |
|
|
265 |
if (!$dialog || get_class($dialog) !== 'Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper') { |
|
|
266 |
$this->getHelperSet()->set($dialog = new DialogHelper()); |
|
|
267 |
} |
|
|
268 |
|
|
|
269 |
return $dialog; |
|
|
270 |
} |
|
|
271 |
} |