1
|
|
|
<?php |
2
|
|
|
namespace keeko\tools\command; |
3
|
|
|
|
4
|
|
|
use keeko\framework\schema\ActionSchema; |
5
|
|
|
use keeko\framework\utils\NameUtils; |
6
|
|
|
use keeko\tools\generator\domain\DomainGenerator; |
7
|
|
|
use keeko\tools\generator\domain\DomainTraitGenerator; |
8
|
|
|
use keeko\tools\generator\domain\ReadOnlyDomainTraitGenerator; |
9
|
|
|
use keeko\tools\helpers\QuestionHelperTrait; |
10
|
|
|
use keeko\tools\utils\NamespaceResolver; |
11
|
|
|
use phootwork\lang\Text; |
12
|
|
|
use Propel\Generator\Model\Table; |
13
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
14
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
15
|
|
|
use Symfony\Component\Console\Input\InputOption; |
16
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
17
|
|
|
use Symfony\Component\Console\Question\ConfirmationQuestion; |
18
|
|
|
use Symfony\Component\Console\Question\Question; |
19
|
|
|
|
20
|
|
|
class GenerateDomainCommand extends AbstractGenerateCommand { |
21
|
|
|
|
22
|
|
|
use QuestionHelperTrait; |
23
|
|
|
|
24
|
|
|
private $twig; |
25
|
|
|
|
26
|
|
|
protected function configure() { |
27
|
|
|
$this |
28
|
|
|
->setName('generate:domain') |
29
|
|
|
->setDescription('Generates a domain object') |
30
|
|
|
->addArgument( |
31
|
|
|
'name', |
32
|
|
|
InputArgument::OPTIONAL, |
33
|
|
|
'The name of the action, which should be generated. Typically in the form %nomen%-%verb% (e.g. user-create)' |
34
|
|
|
) |
35
|
|
|
->addOption( |
36
|
|
|
'classname', |
37
|
|
|
'c', |
38
|
|
|
InputOption::VALUE_OPTIONAL, |
39
|
|
|
'The main class name (If ommited, class name will be guessed from action name)', |
40
|
|
|
null |
41
|
|
|
) |
42
|
|
|
->addOption( |
43
|
|
|
'model', |
44
|
|
|
'm', |
45
|
|
|
InputOption::VALUE_OPTIONAL, |
46
|
|
|
'The model for which the actions should be generated, when there is no name argument (if ommited all models will be generated)' |
47
|
|
|
) |
48
|
|
|
; |
49
|
|
|
|
50
|
|
|
$this->configureGenerateOptions(); |
51
|
|
|
|
52
|
|
|
parent::configure(); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
protected function initialize(InputInterface $input, OutputInterface $output) { |
56
|
|
|
parent::initialize($input, $output); |
57
|
|
|
|
58
|
|
|
$loader = new \Twig_Loader_Filesystem($this->service->getConfig()->getTemplateRoot() . '/domain'); |
59
|
|
|
$this->twig = new \Twig_Environment($loader); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Checks whether actions can be generated at all by reading composer.json and verify |
64
|
|
|
* all required information are available |
65
|
|
|
*/ |
66
|
|
|
private function preCheck() { |
67
|
|
|
$module = $this->packageService->getModule(); |
68
|
|
|
if ($module === null) { |
69
|
|
|
throw new \DomainException('No module definition found in composer.json - please run `keeko init`.'); |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
protected function interact(InputInterface $input, OutputInterface $output) { |
74
|
|
|
$this->preCheck(); |
75
|
|
|
|
76
|
|
|
// check if the dialog can be skipped |
77
|
|
|
$name = $input->getArgument('name'); |
78
|
|
|
$model = $input->getOption('model'); |
79
|
|
|
|
80
|
|
|
if ($model !== null) { |
81
|
|
|
return; |
82
|
|
|
} else if ($name !== null) { |
83
|
|
|
$generateModel = false; |
84
|
|
|
} else { |
85
|
|
|
$modelQuestion = new ConfirmationQuestion('Do you want to generate a domain object based off a model?'); |
86
|
|
|
$generateModel = $this->askConfirmation($modelQuestion); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
// ask questions for a model |
90
|
|
|
if ($generateModel) { |
91
|
|
|
$schema = str_replace(getcwd(), '', $this->modelService->getSchema()); |
92
|
|
|
$allQuestion = new ConfirmationQuestion(sprintf('For all models in the schema (%s)?', $schema)); |
93
|
|
|
$allModels = $this->askConfirmation($allQuestion); |
94
|
|
|
|
95
|
|
|
if (!$allModels) { |
96
|
|
|
$modelQuestion = new Question('Which model'); |
97
|
|
|
$modelQuestion->setAutocompleterValues($this->modelService->getModelNames()); |
98
|
|
|
$model = $this->askQuestion($modelQuestion); |
99
|
|
|
$input->setOption('model', $model); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
// ask question for a name |
103
|
|
|
} else if (!$generateModel) { |
|
|
|
|
104
|
|
|
// TODO: What to do here? |
|
|
|
|
105
|
|
|
// $action = $this->getAction($name); |
106
|
|
|
|
107
|
|
|
// // ask for classname |
|
|
|
|
108
|
|
|
// $pkgClass = $action->getClass(); |
109
|
|
|
// $classname = $input->getOption('classname'); |
110
|
|
|
// if ($classname === null) { |
111
|
|
|
// if (!empty($pkgClass)) { |
112
|
|
|
// $classname = $pkgClass; |
113
|
|
|
// } else { |
114
|
|
|
// $classname = $this->guessClassname($name); |
115
|
|
|
// } |
116
|
|
|
// } |
117
|
|
|
// $classname = $this->askQuestion(new Question('Classname', $classname)); |
118
|
|
|
// $input->setOption('classname', $classname); |
119
|
|
|
|
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) { |
124
|
|
|
$this->preCheck(); |
125
|
|
|
|
126
|
|
|
// 1. find out which action(s) to generate |
127
|
|
|
// 2. generate the information in the package |
128
|
|
|
// 3. generate the code for the action |
129
|
|
|
|
130
|
|
|
$name = $input->getArgument('name'); |
131
|
|
|
$model = $input->getOption('model'); |
132
|
|
|
|
133
|
|
|
// only a specific domain |
134
|
|
|
if ($name) { |
|
|
|
|
135
|
|
|
// $this->generateAction($name); |
|
|
|
|
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
// create action(s) from a model |
139
|
|
|
else if ($model) { |
140
|
|
|
$this->generateModel($model); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
// anyway, generate all |
144
|
|
|
else { |
145
|
|
|
foreach ($this->modelService->getModels() as $model) { |
146
|
|
|
$modelName = $model->getOriginCommonName(); |
147
|
|
|
$input->setOption('model', $modelName); |
148
|
|
|
$this->generateModel($modelName); |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
private function generateModel($modelName) { |
154
|
|
|
$this->logger->info('Generate Domain from Model: ' . $modelName); |
155
|
|
|
$model = $this->modelService->getModel($modelName); |
156
|
|
|
|
157
|
|
|
// generate class |
158
|
|
|
$generator = new DomainGenerator($this->service); |
159
|
|
|
$class = $generator->generate($model); |
|
|
|
|
160
|
|
|
$this->codegenService->dumpStruct($class, true); |
161
|
|
|
|
162
|
|
|
// generate trait |
163
|
|
|
$generator = $model->isReadOnly() |
164
|
|
|
? new ReadOnlyDomainTraitGenerator($this->service) |
165
|
|
|
: new DomainTraitGenerator($this->service); |
166
|
|
|
$trait = $generator->generate($model); |
|
|
|
|
167
|
|
|
$this->codegenService->dumpStruct($trait, true); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Generates a domain with trait for the given model |
172
|
|
|
* |
173
|
|
|
* @TODO: Externalize this into its own command and call the command from here |
174
|
|
|
* |
175
|
|
|
* @param Table $model |
176
|
|
|
*/ |
177
|
|
|
private function generateDomain(Table $model) { |
178
|
|
|
// generate class |
179
|
|
|
$generator = new DomainGenerator($this->service); |
180
|
|
|
$class = $generator->generate($model); |
181
|
|
|
$this->codegenService->dumpStruct($class, true); |
182
|
|
|
|
183
|
|
|
// generate trait |
184
|
|
|
$generator = $model->isReadOnly() |
185
|
|
|
? new ReadOnlyDomainTraitGenerator($this->service) |
186
|
|
|
: new DomainTraitGenerator($this->service); |
187
|
|
|
$trait = $generator->generate($model); |
188
|
|
|
$this->codegenService->dumpStruct($trait, true); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
// /** |
192
|
|
|
// * Generates an action. |
193
|
|
|
// * |
194
|
|
|
// * @param string $actionName |
195
|
|
|
// * @param ActionSchema $action the action node from composer.json |
196
|
|
|
// */ |
197
|
|
|
// private function generateAction($actionName) { |
198
|
|
|
// $this->logger->info('Generate Action: ' . $actionName); |
199
|
|
|
// $input = $this->io->getInput(); |
200
|
|
|
|
201
|
|
|
// // get action and create it if it doesn't exist |
|
|
|
|
202
|
|
|
// $action = $this->getAction($actionName); |
203
|
|
|
|
204
|
|
|
// if (($title = $input->getOption('title')) !== null) { |
|
|
|
|
205
|
|
|
// $action->setTitle($title); |
206
|
|
|
// } |
207
|
|
|
|
208
|
|
|
// if (Text::create($action->getTitle())->isEmpty()) { |
|
|
|
|
209
|
|
|
// throw new \RuntimeException(sprintf('Cannot create action %s, because I am missing a title for it', $actionName)); |
210
|
|
|
// } |
211
|
|
|
|
212
|
|
|
// if (($classname = $input->getOption('classname')) !== null) { |
|
|
|
|
213
|
|
|
// $action->setClass($classname); |
214
|
|
|
// } |
215
|
|
|
|
216
|
|
|
// // guess classname if there is none set yet |
|
|
|
|
217
|
|
|
// if (Text::create($action->getClass())->isEmpty()) { |
218
|
|
|
// $action->setClass($this->guessClassname($actionName)); |
219
|
|
|
// } |
220
|
|
|
|
221
|
|
|
// // guess title if there is none set yet |
|
|
|
|
222
|
|
|
// if (Text::create($action->getTitle())->isEmpty() |
223
|
|
|
// && $this->modelService->isModelAction($action) |
224
|
|
|
// && $this->modelService->isCrudAction($action)) { |
225
|
|
|
// $modelName = $this->modelService->getModelNameByAction($action); |
226
|
|
|
// $type = $this->modelService->getOperationByAction($action); |
227
|
|
|
// $action->setTitle($this->getActionTitle($modelName, $type)); |
228
|
|
|
// } |
229
|
|
|
|
230
|
|
|
// // set acl |
|
|
|
|
231
|
|
|
// $action->setAcl($this->getAcl($action)); |
232
|
|
|
|
233
|
|
|
// // generate code |
|
|
|
|
234
|
|
|
// $this->generateCode($action); |
235
|
|
|
// } |
236
|
|
|
|
237
|
|
|
// private function guessClassname($name) { |
|
|
|
|
238
|
|
|
// $namespace = NamespaceResolver::getNamespace('src/action', $this->package); |
239
|
|
|
// return $namespace . '\\' . NameUtils::toStudlyCase($name) . 'Action'; |
240
|
|
|
// } |
241
|
|
|
|
242
|
|
|
} |
243
|
|
|
|
This check looks for the bodies of
if
statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.These
if
bodies can be removed. If you have an empty if but statements in theelse
branch, consider inverting the condition.could be turned into
This is much more concise to read.