1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace N98\Magento\Command\Developer\Module; |
4
|
|
|
|
5
|
|
|
use InvalidArgumentException; |
6
|
|
|
use N98\Magento\Command\AbstractMagentoCommand; |
7
|
|
|
use RuntimeException; |
8
|
|
|
use SimpleXMLElement; |
9
|
|
|
use Symfony\Component\Console\Helper\DialogHelper; |
10
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
11
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
12
|
|
|
use Symfony\Component\Console\Input\InputOption; |
13
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Update a magento module |
17
|
|
|
*/ |
18
|
|
|
class UpdateCommand extends AbstractMagentoCommand |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* @var string |
22
|
|
|
*/ |
23
|
|
|
protected $baseFolder; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var string |
27
|
|
|
*/ |
28
|
|
|
protected $moduleDirectory; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var string |
32
|
|
|
*/ |
33
|
|
|
protected $vendorNamespace; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var string |
37
|
|
|
*/ |
38
|
|
|
protected $moduleName; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var string |
42
|
|
|
*/ |
43
|
|
|
protected $codePool; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var array |
47
|
|
|
*/ |
48
|
|
|
protected $configNodes = array(); |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var bool |
52
|
|
|
*/ |
53
|
|
|
protected $testMode = false; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @param boolean $testMode |
57
|
|
|
*/ |
58
|
|
|
public function setTestMode($testMode) |
59
|
|
|
{ |
60
|
|
|
$this->testMode = $testMode; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @return boolean |
65
|
|
|
*/ |
66
|
|
|
public function getTestMode() |
67
|
|
|
{ |
68
|
|
|
return $this->testMode; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
protected function configure() |
72
|
|
|
{ |
73
|
|
|
$this |
74
|
|
|
->setName('dev:module:update') |
75
|
|
|
->addArgument('vendorNamespace', InputArgument::REQUIRED, 'Namespace (your company prefix)') |
76
|
|
|
->addArgument('moduleName', InputArgument::REQUIRED, 'Name of your module.') |
77
|
|
|
->addOption('set-version', null, InputOption::VALUE_NONE, 'Set module version in config.xml') |
78
|
|
|
->addOption('add-blocks', null, InputOption::VALUE_NONE, 'Adds blocks class to config.xml') |
79
|
|
|
->addOption('add-helpers', null, InputOption::VALUE_NONE, 'Adds helpers class to config.xml') |
80
|
|
|
->addOption('add-models', null, InputOption::VALUE_NONE, 'Adds models class to config.xml') |
81
|
|
|
->addOption( |
82
|
|
|
'add-all', |
83
|
|
|
null, |
84
|
|
|
InputOption::VALUE_NONE, |
85
|
|
|
'Adds blocks, helpers and models classes to config.xml' |
86
|
|
|
) |
87
|
|
|
->addOption( |
88
|
|
|
'add-resource-model', |
89
|
|
|
null, |
90
|
|
|
InputOption::VALUE_NONE, |
91
|
|
|
'Adds resource model class and entities to config.xml' |
92
|
|
|
) |
93
|
|
|
->addOption( |
94
|
|
|
'add-routers', |
95
|
|
|
null, |
96
|
|
|
InputOption::VALUE_NONE, |
97
|
|
|
'Adds routers for frontend or admin areas to config.xml' |
98
|
|
|
) |
99
|
|
|
->addOption( |
100
|
|
|
'add-events', |
101
|
|
|
null, |
102
|
|
|
InputOption::VALUE_NONE, |
103
|
|
|
'Adds events observer to global, frontend or adminhtml areas to config.xml' |
104
|
|
|
) |
105
|
|
|
->addOption( |
106
|
|
|
'add-layout-updates', |
107
|
|
|
null, |
108
|
|
|
InputOption::VALUE_NONE, |
109
|
|
|
'Adds layout updates to frontend or adminhtml areas to config.xml' |
110
|
|
|
) |
111
|
|
|
->addOption( |
112
|
|
|
'add-translate', |
113
|
|
|
null, |
114
|
|
|
InputOption::VALUE_NONE, |
115
|
|
|
'Adds translate configuration to frontend or adminhtml areas to config.xml' |
116
|
|
|
) |
117
|
|
|
->addOption( |
118
|
|
|
'add-default', |
119
|
|
|
null, |
120
|
|
|
InputOption::VALUE_NONE, |
121
|
|
|
'Adds default value (related to system.xml groups/fields)' |
122
|
|
|
) |
123
|
|
|
->setDescription('Update a Magento module.'); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* @param InputInterface $input |
128
|
|
|
* @param OutputInterface $output |
129
|
|
|
* |
130
|
|
|
* @return int|void |
131
|
|
|
* @throws InvalidArgumentException |
132
|
|
|
*/ |
133
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
134
|
|
|
{ |
135
|
|
|
$this->initMagento(); |
136
|
|
|
$this->initArguments($input); |
137
|
|
|
|
138
|
|
|
if ($this->hasAddResourceModelOption($input)) { |
139
|
|
|
$this->askResourceModelOptions($output); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
if ($this->hasAddRoutersOption($input)) { |
143
|
|
|
$this->askRoutersOptions($output); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
if ($this->hasAddEventsOption($input)) { |
147
|
|
|
$this->askEventsOptions($output); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
if ($this->hasAddLayoutUpdatesOptions($input)) { |
151
|
|
|
$this->askLayoutUpdatesOptions($output); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
if ($this->hasAddTranslateOption($input)) { |
155
|
|
|
$this->askTranslateOptions($output); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
if ($this->hasAddDefaultOption($input)) { |
159
|
|
|
$this->askDefaultOptions($output); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
$this->setModuleDirectory($this->getModuleDir()); |
163
|
|
|
$this->writeModuleConfig($input, $output); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @param InputInterface $input |
168
|
|
|
*/ |
169
|
|
|
protected function initArguments(InputInterface $input) |
170
|
|
|
{ |
171
|
|
|
$this->vendorNamespace = ucfirst($input->getArgument('vendorNamespace')); |
172
|
|
|
$this->moduleName = ucfirst($input->getArgument('moduleName')); |
173
|
|
|
$this->determineModuleCodePool(); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Find module codepool from module directory |
178
|
|
|
* |
179
|
|
|
* @return string |
180
|
|
|
*/ |
181
|
|
|
protected function determineModuleCodePool() |
182
|
|
|
{ |
183
|
|
|
if ($this->testMode === true) { |
184
|
|
|
$this->codePool = 'local'; |
185
|
|
|
$this->_magentoRootFolder = './' . $this->getModuleNamespace() . '/src'; |
186
|
|
|
$this->moduleDirectory = $this->_magentoRootFolder |
187
|
|
|
. '/app/code/' |
188
|
|
|
. $this->codePool |
189
|
|
|
. '/' . $this->vendorNamespace |
190
|
|
|
. '/' . $this->moduleName; |
191
|
|
|
} else { |
192
|
|
|
$this->moduleDirectory = $this->getModuleDir(); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
if (preg_match('/community/', $this->moduleDirectory)) { |
196
|
|
|
$this->codePool = 'community'; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
if (preg_match('/local/', $this->moduleDirectory)) { |
200
|
|
|
$this->codePool = 'local'; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
return $this->codePool; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* @param string $moduleDir |
208
|
|
|
* @throws RuntimeException |
209
|
|
|
*/ |
210
|
|
|
protected function setModuleDirectory($moduleDir) |
211
|
|
|
{ |
212
|
|
|
if (!file_exists($moduleDir)) { |
213
|
|
|
throw new RuntimeException( |
214
|
|
|
'Module does not exist. Use dev:module:create to create it before updating. Stop.' |
215
|
|
|
); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
$this->moduleDirectory = $moduleDir; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* @return DialogHelper |
223
|
|
|
*/ |
224
|
|
|
protected function getDialog() |
225
|
|
|
{ |
226
|
|
|
return $this->getHelper('dialog'); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Writes module config file for given options |
231
|
|
|
* |
232
|
|
|
* @param InputInterface $input |
233
|
|
|
* @param OutputInterface $output |
234
|
|
|
*/ |
235
|
|
|
protected function writeModuleConfig(InputInterface $input, OutputInterface $output) |
236
|
|
|
{ |
237
|
|
|
$configXml = $this->getConfigXml(); |
238
|
|
|
|
239
|
|
|
$this->setVersion($input, $output, $configXml); |
240
|
|
|
$this->setGlobalNode($input, $output, $configXml); |
241
|
|
|
$this->setResourceModelNode($input, $configXml); |
242
|
|
|
$this->setRoutersNode($input, $configXml); |
243
|
|
|
$this->setEventsNode($input, $configXml); |
244
|
|
|
$this->setLayoutUpdatesNode($input, $configXml); |
245
|
|
|
$this->setTranslateNode($input, $configXml); |
246
|
|
|
$this->setDefaultNode($input, $configXml); |
247
|
|
|
$this->putConfigXml($configXml); |
248
|
|
|
|
249
|
|
|
$output->writeln('<info>Edited file: <comment>' . $this->getOutFile() . '<comment></info>'); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* @param InputInterface $input |
254
|
|
|
* @param OutputInterface $output |
255
|
|
|
* @param SimpleXMLElement $configXml |
256
|
|
|
*/ |
257
|
|
|
protected function setVersion(InputInterface $input, OutputInterface $output, \SimpleXMLElement $configXml) |
258
|
|
|
{ |
259
|
|
|
if ($this->shouldSetVersion($input)) { |
260
|
|
|
$modulesNode = $configXml->modules->{$this->getModuleNamespace()}; |
261
|
|
|
$dialog = $this->getDialog(); |
262
|
|
|
$version = trim($dialog->ask($output, '<question>Enter version number:</question>')); |
263
|
|
|
$modulesNode->version = $version; |
264
|
|
|
} |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* Sets global xml config node |
269
|
|
|
* |
270
|
|
|
* @param InputInterface $input |
271
|
|
|
* @param OutputInterface $output |
272
|
|
|
* @param SimpleXMLElement $configXml |
273
|
|
|
*/ |
274
|
|
|
protected function setGlobalNode(InputInterface $input, OutputInterface $output, SimpleXMLElement $configXml) |
275
|
|
|
{ |
276
|
|
|
if ($this->shouldAddAll($input)) { |
277
|
|
|
$this->addGlobalNode($configXml, 'blocks', '_Block'); |
278
|
|
|
$this->addGlobalNode($configXml, 'helpers', '_Helper'); |
279
|
|
|
$this->addGlobalNode($configXml, 'models', '_Model'); |
280
|
|
|
$this->addResourceModelNodeIfConfirmed($output, $configXml); |
281
|
|
|
} else { |
282
|
|
|
if ($this->shouldAddBlocks($input)) { |
283
|
|
|
$this->addGlobalNode($configXml, 'blocks', '_Block'); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
if ($this->shouldAddHelpers($input)) { |
287
|
|
|
$this->addGlobalNode($configXml, 'helpers', '_Helper'); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
if ($this->shouldAddModels($input)) { |
291
|
|
|
$this->addGlobalNode($configXml, 'models', '_Model'); |
292
|
|
|
$this->addResourceModelNodeIfConfirmed($output, $configXml); |
293
|
|
|
} |
294
|
|
|
} |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* @param OutputInterface $output |
299
|
|
|
* @param SimpleXMLElement $configXml |
300
|
|
|
*/ |
301
|
|
|
protected function addResourceModelNodeIfConfirmed(OutputInterface $output, \SimpleXMLElement $configXml) |
302
|
|
|
{ |
303
|
|
|
$dialog = $this->getDialog(); |
304
|
|
|
if ($dialog->askConfirmation( |
305
|
|
|
$output, |
306
|
|
|
'<question>Would you like to also add a Resource Model(y/n)?</question>', |
307
|
|
|
false |
308
|
|
|
) |
309
|
|
|
) { |
310
|
|
|
$resourceModel = trim($dialog->ask($output, '<question>Resource Model:</question>')); |
311
|
|
|
$configXml->global->models |
312
|
|
|
->{$this->getLowercaseModuleNamespace()}->addChild('resourceModel', $resourceModel); |
313
|
|
|
} |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
/** |
317
|
|
|
* @param InputInterface $input |
318
|
|
|
* @param SimpleXMLElement $configXml |
319
|
|
|
*/ |
320
|
|
|
protected function setResourceModelNode(InputInterface $input, \SimpleXMLElement $configXml) |
321
|
|
|
{ |
322
|
|
|
if ($this->hasAddResourceModelOption($input)) { |
323
|
|
|
$this->addResourceModel($configXml); |
324
|
|
|
} |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* @param InputInterface $input |
329
|
|
|
* @param SimpleXMLElement $configXml |
330
|
|
|
*/ |
331
|
|
|
protected function setRoutersNode(InputInterface $input, \SimpleXMLElement $configXml) |
332
|
|
|
{ |
333
|
|
|
if ($this->hasAddRoutersOption($input)) { |
334
|
|
|
$this->addRouter($configXml, $this->configNodes['router_area']); |
335
|
|
|
} |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
/** |
339
|
|
|
* @param InputInterface $input |
340
|
|
|
* @param SimpleXMLElement $configXml |
341
|
|
|
*/ |
342
|
|
|
protected function setEventsNode(InputInterface $input, \SimpleXMLElement $configXml) |
343
|
|
|
{ |
344
|
|
|
if ($this->hasAddEventsOption($input)) { |
345
|
|
|
$this->addEvent($configXml, $this->configNodes['events_area'], $this->configNodes['event_name']); |
346
|
|
|
} |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* @param InputInterface $input |
351
|
|
|
* @param SimpleXMLElement $configXml |
352
|
|
|
*/ |
353
|
|
|
protected function setLayoutUpdatesNode(InputInterface $input, \SimpleXMLElement $configXml) |
354
|
|
|
{ |
355
|
|
|
if ($this->hasAddLayoutUpdatesOptions($input)) { |
356
|
|
|
$this->addLayoutUpdate( |
357
|
|
|
$configXml, |
358
|
|
|
$this->configNodes['layout_updates_area'], |
359
|
|
|
$this->configNodes['layout_update_module'] |
360
|
|
|
); |
361
|
|
|
} |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* @param InputInterface $input |
366
|
|
|
* @param SimpleXMLElement $configXml |
367
|
|
|
*/ |
368
|
|
|
protected function setTranslateNode(InputInterface $input, \SimpleXMLElement $configXml) |
369
|
|
|
{ |
370
|
|
|
if ($this->hasAddTranslateOption($input)) { |
371
|
|
|
$this->addTranslate( |
372
|
|
|
$configXml, |
373
|
|
|
$this->configNodes['translate_area'], |
374
|
|
|
$this->configNodes['translate_module'] |
375
|
|
|
); |
376
|
|
|
} |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
/** |
380
|
|
|
* @param InputInterface $input |
381
|
|
|
* @param SimpleXMLElement $configXml |
382
|
|
|
*/ |
383
|
|
|
protected function setDefaultNode(InputInterface $input, \SimpleXMLElement $configXml) |
384
|
|
|
{ |
385
|
|
|
if ($this->hasAddDefaultOption($input)) { |
386
|
|
|
$this->addDefault($configXml); |
387
|
|
|
} |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
/** |
391
|
|
|
* Gets config XML |
392
|
|
|
* |
393
|
|
|
* @return SimpleXMLElement |
394
|
|
|
*/ |
395
|
|
|
protected function getConfigXml() |
396
|
|
|
{ |
397
|
|
|
$currentConfigXml = $this->getCurrentConfigContent(); |
398
|
|
|
$simpleXml = new \SimpleXMLElement($currentConfigXml); |
399
|
|
|
|
400
|
|
|
return $simpleXml; |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
/** |
404
|
|
|
* Returns current content of /etc/config.xml |
405
|
|
|
* |
406
|
|
|
* @return string |
407
|
|
|
*/ |
408
|
|
|
protected function getCurrentConfigContent() |
409
|
|
|
{ |
410
|
|
|
$configFile = $this->getModuleDir() . '/etc/config.xml'; |
411
|
|
|
|
412
|
|
|
return file_get_contents($configFile); |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
/** |
416
|
|
|
* @return string |
417
|
|
|
*/ |
418
|
|
|
protected function getModuleDir() |
419
|
|
|
{ |
420
|
|
|
return isset($this->moduleDirectory) |
421
|
|
|
? $this->moduleDirectory |
422
|
|
|
: \Mage::getModuleDir(false, $this->getModuleNamespace()); |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
/** |
426
|
|
|
* Initiates resource nodes specific values |
427
|
|
|
*/ |
428
|
|
|
protected function initResourceModelConfigNodes() |
429
|
|
|
{ |
430
|
|
|
$this->configNodes['resource_node_name'] = $this->getLowercaseModuleNamespace() . '_resource'; |
431
|
|
|
$this->configNodes['resource_model_class'] = $this->getModuleNamespace() . '_Model_Resource'; |
432
|
|
|
$this->configNodes['resource_deprecated_mysql4_node'] = false; |
433
|
|
|
$this->configNodes['resource_entities'] = array(); |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Initiates routers config nodes specific values |
438
|
|
|
*/ |
439
|
|
|
protected function initRoutersConfigNodes() |
440
|
|
|
{ |
441
|
|
|
$this->configNodes['router_area'] = false; |
442
|
|
|
$this->configNodes['use'] = false; |
443
|
|
|
$this->configNodes['frontname'] = false; |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* Initiates events config nodes specific values |
448
|
|
|
*/ |
449
|
|
|
protected function initEventsConfigNodes() |
450
|
|
|
{ |
451
|
|
|
$this->configNodes['events_area'] = false; |
452
|
|
|
$this->configNodes['event_name'] = false; |
453
|
|
|
$this->configNodes['event_observer'] = false; |
454
|
|
|
$this->configNodes['event_observer_class'] = false; |
455
|
|
|
$this->configNodes['event_observer_method'] = false; |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
/** |
459
|
|
|
* Initiates layout updates nodes specific values |
460
|
|
|
*/ |
461
|
|
|
protected function initLayoutUpdatesConfigNodes() |
462
|
|
|
{ |
463
|
|
|
$this->configNodes['layout_updates_area'] = false; |
464
|
|
|
$this->configNodes['layout_update_module'] = false; |
465
|
|
|
$this->configNodes['layout_update_file'] = false; |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* Initiates layout updates nodes specific values |
470
|
|
|
*/ |
471
|
|
|
protected function initTranslateConfigNodes() |
472
|
|
|
{ |
473
|
|
|
$this->configNodes['translate_area'] = false; |
474
|
|
|
$this->configNodes['translate_module'] = $this->getModuleNamespace(); |
475
|
|
|
$this->configNodes['translate_files_default'] = false; |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
/** |
479
|
|
|
* Initiates resource nodes specific values |
480
|
|
|
*/ |
481
|
|
|
protected function initDefaultConfigNodes() |
482
|
|
|
{ |
483
|
|
|
$this->configNodes['default_section_name'] = false; |
484
|
|
|
$this->configNodes['default_group_name'] = false; |
485
|
|
|
$this->configNodes['default_field_name'] = false; |
486
|
|
|
$this->configNodes['default_field_value'] = false; |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
/** |
490
|
|
|
* Asks for routers node options |
491
|
|
|
* |
492
|
|
|
* @param OutputInterface $output |
493
|
|
|
* @throws RuntimeException |
494
|
|
|
*/ |
495
|
|
|
protected function askResourceModelOptions(OutputInterface $output) |
496
|
|
|
{ |
497
|
|
|
$this->initResourceModelConfigNodes(); |
498
|
|
|
$dialog = $this->getDialog(); |
499
|
|
|
|
500
|
|
|
if ($dialog->askConfirmation($output, |
501
|
|
|
'<question>Would you like to set mysql4 deprecated node(y/n)?</question>', |
502
|
|
|
false |
503
|
|
|
) |
504
|
|
|
) { |
505
|
|
|
$this->configNodes['resource_deprecated_mysql4_node'] = true; |
506
|
|
|
} |
507
|
|
|
|
508
|
|
|
$entityName = true; |
509
|
|
|
|
510
|
|
|
while ($entityName) { |
511
|
|
|
$entityName = trim($dialog->ask($output, '<question>Entity Name (leave blank to exit):</question>')); |
512
|
|
|
if (!$entityName) { |
513
|
|
|
break; |
514
|
|
|
} |
515
|
|
|
$entityTable = trim($dialog->ask($output, '<question>Entity Table:</question>')); |
516
|
|
|
$this->configNodes['resource_entities'][$entityName] = $entityTable; |
517
|
|
|
} |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
/** |
521
|
|
|
* Asks for routers node options |
522
|
|
|
* |
523
|
|
|
* @param OutputInterface $output |
524
|
|
|
* @throws RuntimeException |
525
|
|
|
*/ |
526
|
|
View Code Duplication |
protected function askRoutersOptions(OutputInterface $output) |
|
|
|
|
527
|
|
|
{ |
528
|
|
|
$this->initRoutersConfigNodes(); |
529
|
|
|
$dialog = $this->getDialog(); |
530
|
|
|
$area = trim($dialog->ask($output, '<question>Area (frontend|admin):</question>')); |
531
|
|
|
$use = trim($dialog->ask($output, '<question>Use:</question>')); |
532
|
|
|
$frontName = trim($dialog->ask($output, '<question>Frontname:</question>')); |
533
|
|
|
|
534
|
|
|
if ($area != 'frontend' && $area != 'admin') { |
535
|
|
|
throw new RuntimeException('Router area must be either "frontend" or "admin"'); |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
$this->configNodes['router_area'] = $area; |
539
|
|
|
$this->configNodes['use'] = $use; |
540
|
|
|
$this->configNodes['frontname'] = $frontName; |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
/** |
544
|
|
|
* Asks for events node options |
545
|
|
|
* |
546
|
|
|
* @param OutputInterface $output |
547
|
|
|
* @throws RuntimeException |
548
|
|
|
*/ |
549
|
|
|
protected function askEventsOptions(OutputInterface $output) |
550
|
|
|
{ |
551
|
|
|
$this->initEventsConfigNodes(); |
552
|
|
|
$dialog = $this->getDialog(); |
553
|
|
|
$area = trim($dialog->ask($output, '<question>Area (global|frontend|adminhtml):</question>')); |
554
|
|
|
$event = trim($dialog->ask($output, '<question>Event:</question>')); |
555
|
|
|
$observer = trim($dialog->ask($output, '<question>Event Observer:</question>')); |
556
|
|
|
$observerClass = trim($dialog->ask($output, '<question>Event Observer Class:</question>')); |
557
|
|
|
$observerMethod = trim($dialog->ask($output, '<question>Event Observer Method:</question>')); |
558
|
|
|
|
559
|
|
|
if ($area != 'global' && $area != 'frontend' && $area != 'adminhtml') { |
560
|
|
|
throw new RuntimeException('Event area must be either "global", "frontend" or "adminhtml"'); |
561
|
|
|
} |
562
|
|
|
|
563
|
|
|
$this->configNodes['events_area'] = $area; |
564
|
|
|
$this->configNodes['event_name'] = $event; |
565
|
|
|
$this->configNodes['event_observer'] = $observer; |
566
|
|
|
$this->configNodes['event_observer_class'] = $observerClass; |
567
|
|
|
$this->configNodes['event_observer_method'] = $observerMethod; |
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
/** |
571
|
|
|
* Asks for layout updates node options |
572
|
|
|
* |
573
|
|
|
* @param OutputInterface $output |
574
|
|
|
* @throws RuntimeException |
575
|
|
|
*/ |
576
|
|
View Code Duplication |
protected function askLayoutUpdatesOptions(OutputInterface $output) |
|
|
|
|
577
|
|
|
{ |
578
|
|
|
$this->initLayoutUpdatesConfigNodes(); |
579
|
|
|
$dialog = $this->getDialog(); |
580
|
|
|
$area = trim($dialog->ask($output, '<question>Area (frontend|adminhtml):</question>')); |
581
|
|
|
$module = trim($dialog->ask($output, '<question>Module:</question>')); |
582
|
|
|
$file = trim($dialog->ask($output, '<question>File:</question>')); |
583
|
|
|
|
584
|
|
|
if ($area != 'frontend' && $area != 'adminhtml') { |
585
|
|
|
throw new RuntimeException('Layout updates area must be either "frontend" or "adminhtml"'); |
586
|
|
|
} |
587
|
|
|
|
588
|
|
|
$this->configNodes['layout_updates_area'] = $area; |
589
|
|
|
$this->configNodes['layout_update_module'] = $module; |
590
|
|
|
$this->configNodes['layout_update_file'] = $file; |
591
|
|
|
} |
592
|
|
|
|
593
|
|
|
/** |
594
|
|
|
* Asks for translate node options |
595
|
|
|
* |
596
|
|
|
* @param OutputInterface $output |
597
|
|
|
* @throws RuntimeException |
598
|
|
|
*/ |
599
|
|
|
protected function askTranslateOptions(OutputInterface $output) |
600
|
|
|
{ |
601
|
|
|
$this->initTranslateConfigNodes(); |
602
|
|
|
$dialog = $this->getDialog(); |
603
|
|
|
$area = trim($dialog->ask($output, '<question>Area (frontend|adminhtml):</question>')); |
604
|
|
|
$file = trim($dialog->ask($output, '<question>File:</question>')); |
605
|
|
|
|
606
|
|
|
if ($area != 'frontend' && $area != 'adminhtml') { |
607
|
|
|
throw new RuntimeException('Layout updates area must be either "frontend" or "adminhtml"'); |
608
|
|
|
} |
609
|
|
|
|
610
|
|
|
$this->configNodes['translate_area'] = $area; |
611
|
|
|
$this->configNodes['translate_files_default'] = $file; |
612
|
|
|
} |
613
|
|
|
|
614
|
|
|
/** |
615
|
|
|
* Asks for default node options |
616
|
|
|
* |
617
|
|
|
* @param OutputInterface $output |
618
|
|
|
* @throws RuntimeException |
619
|
|
|
*/ |
620
|
|
|
protected function askDefaultOptions(OutputInterface $output) |
621
|
|
|
{ |
622
|
|
|
$this->initDefaultConfigNodes(); |
623
|
|
|
$dialog = $this->getDialog(); |
624
|
|
|
$sectionName = strtolower(trim($dialog->ask($output, '<question>Section Name (lowercase):</question>'))); |
625
|
|
|
$groupName = strtolower(trim($dialog->ask($output, '<question>Group Name (lowercase):</question>'))); |
626
|
|
|
$fieldName = strtolower(trim($dialog->ask($output, '<question>Field Name:</question>'))); |
627
|
|
|
$fieldValue = strtolower(trim($dialog->ask($output, '<question>Field Value:</question>'))); |
628
|
|
|
|
629
|
|
|
$this->configNodes['default_section_name'] = $sectionName; |
630
|
|
|
$this->configNodes['default_group_name'] = $groupName; |
631
|
|
|
$this->configNodes['default_field_name'] = $fieldName; |
632
|
|
|
$this->configNodes['default_field_value'] = $fieldValue; |
633
|
|
|
} |
634
|
|
|
|
635
|
|
|
/** |
636
|
|
|
* @param SimpleXMLElement $configXml |
637
|
|
|
* @param string $type e.g. "blocks" |
638
|
|
|
* @param string $classSuffix e.g. "_Block" |
639
|
|
|
*/ |
640
|
|
|
protected function addGlobalNode(\SimpleXMLElement $configXml, $type, $classSuffix) |
641
|
|
|
{ |
642
|
|
|
$this->removeChildNodeIfNotNull($configXml->global, $type); |
643
|
|
|
$global = $configXml->global ? $configXml->global : $configXml->addChild('global'); |
644
|
|
|
$globalNode = $global->addChild($type); |
645
|
|
|
$moduleNamespaceNode = $globalNode->addChild($this->getLowercaseModuleNamespace()); |
646
|
|
|
$moduleNamespaceNode->addChild('class', $this->getModuleNamespace() . $classSuffix); |
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
/** |
650
|
|
|
* @param SimpleXMLElement $simpleXml |
651
|
|
|
*/ |
652
|
|
|
protected function addResourceModel(\SimpleXMLElement $simpleXml) |
653
|
|
|
{ |
654
|
|
|
if (is_null($simpleXml->global->models)) { |
655
|
|
|
throw new RuntimeException( |
656
|
|
|
'Global models node is not set. Run --add-models before --add-resource-model command.' |
657
|
|
|
); |
658
|
|
|
} |
659
|
|
|
|
660
|
|
|
$resourceNamespace = $this->getLowercaseModuleNamespace() . '_resource'; |
661
|
|
|
$resourceModelNode = $simpleXml->global->models->$resourceNamespace ? |
662
|
|
|
$simpleXml->global->models->$resourceNamespace : $simpleXml->global->models->addChild($resourceNamespace); |
663
|
|
|
|
664
|
|
|
$simpleXml->global->models->$resourceNamespace->class |
665
|
|
|
? null : $resourceModelNode->addChild('class', $this->configNodes['resource_model_class']); |
666
|
|
|
|
667
|
|
|
if ($this->configNodes['resource_deprecated_mysql4_node'] === true) { |
668
|
|
|
$simpleXml->global->models->$resourceNamespace->deprecatedNode ? null : $resourceModelNode->addChild( |
669
|
|
|
'deprecatedNode', |
670
|
|
|
$resourceNamespace . '_eav_mysql4' |
671
|
|
|
); |
672
|
|
|
} else { |
673
|
|
|
$this->removeChildNodeIfNotNull($resourceModelNode, 'deprecatedNode'); |
674
|
|
|
} |
675
|
|
|
|
676
|
|
|
$entitiesNode = $resourceModelNode->entities |
677
|
|
|
? $resourceModelNode->entities : $resourceModelNode->addChild('entities'); |
678
|
|
|
|
679
|
|
|
foreach ($this->configNodes['resource_entities'] as $entity => $table) { |
680
|
|
|
$this->removeChildNodeIfNotNull($entitiesNode, $entity); |
681
|
|
|
$entityNode = $entitiesNode->addChild($entity); |
682
|
|
|
$entityNode->addChild('table', $table); |
683
|
|
|
} |
684
|
|
|
} |
685
|
|
|
|
686
|
|
|
/** |
687
|
|
|
* @param SimpleXMLElement $simpleXml |
688
|
|
|
* @param $area |
689
|
|
|
*/ |
690
|
|
|
protected function addRouter(\SimpleXMLElement $simpleXml, $area) |
691
|
|
|
{ |
692
|
|
|
$this->removeChildNodeIfNotNull($simpleXml->{$area}, 'routers'); |
693
|
|
|
$areaNode = $simpleXml->{$area} ? $simpleXml->{$area} : $simpleXml->addChild($area); |
694
|
|
|
$routers = $areaNode->addChild('routers'); |
695
|
|
|
$moduleNamespace = $routers->addChild($this->getLowercaseModuleNamespace()); |
696
|
|
|
$moduleNamespace->addChild('use', $this->configNodes['use']); |
697
|
|
|
$args = $moduleNamespace->addChild('args'); |
698
|
|
|
$args->addChild('module', $this->getLowercaseModuleNamespace()); |
699
|
|
|
$args->addChild('frontName', $this->configNodes['frontname']); |
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
/** |
703
|
|
|
* @param SimpleXMLElement $simpleXml |
704
|
|
|
* @param $area |
705
|
|
|
* @param $event |
706
|
|
|
*/ |
707
|
|
View Code Duplication |
protected function addEvent(\SimpleXMLElement $simpleXml, $area, $event) |
|
|
|
|
708
|
|
|
{ |
709
|
|
|
$areaNode = $simpleXml->{$area} ? $simpleXml->{$area} : $simpleXml->addChild($area); |
710
|
|
|
$eventsNode = $areaNode->events ? $areaNode->events : $areaNode->addChild('events'); |
711
|
|
|
$this->removeChildNodeIfNotNull($eventsNode, $event); |
712
|
|
|
$eventNode = $eventsNode->addChild($event); |
713
|
|
|
$observersNode = $eventNode->addChild('observers'); |
714
|
|
|
$eventObserverNode = $observersNode->addChild($this->configNodes['event_observer']); |
715
|
|
|
$eventObserverNode->addChild('class', $this->configNodes['event_observer_class']); |
716
|
|
|
$eventObserverNode->addChild('method', $this->configNodes['event_observer_method']); |
717
|
|
|
} |
718
|
|
|
|
719
|
|
|
/** |
720
|
|
|
* @param SimpleXMLElement $simpleXml |
721
|
|
|
* @param $area |
722
|
|
|
* @param $module |
723
|
|
|
*/ |
724
|
|
|
protected function addLayoutUpdate(\SimpleXMLElement $simpleXml, $area, $module) |
725
|
|
|
{ |
726
|
|
|
$areaNode = $simpleXml->{$area} ? $simpleXml->{$area} : $simpleXml->addChild($area); |
727
|
|
|
$layoutNode = $areaNode->layout ? $areaNode->layout : $areaNode->addChild('layout'); |
728
|
|
|
$updatesNode = $layoutNode->updates ? $layoutNode->updates : $layoutNode->addChild('updates'); |
729
|
|
|
$this->removeChildNodeIfNotNull($updatesNode, $module); |
730
|
|
|
$moduleNode = $updatesNode->addChild($module); |
731
|
|
|
$moduleNode->addChild('file', $this->configNodes['layout_update_file']); |
732
|
|
|
} |
733
|
|
|
|
734
|
|
|
/** |
735
|
|
|
* @param SimpleXMLElement $simpleXml |
736
|
|
|
* @param $area |
737
|
|
|
* @param $module |
738
|
|
|
*/ |
739
|
|
View Code Duplication |
protected function addTranslate(\SimpleXMLElement $simpleXml, $area, $module) |
|
|
|
|
740
|
|
|
{ |
741
|
|
|
$areaNode = $simpleXml->{$area} ? $simpleXml->{$area} : $simpleXml->addChild($area); |
742
|
|
|
$translateNode = $areaNode->translate ? $areaNode->translate : $areaNode->addChild('translate'); |
743
|
|
|
$modulesNode = $translateNode->modules ? $translateNode->modules : $translateNode->addChild('modules'); |
744
|
|
|
$this->removeChildNodeIfNotNull($modulesNode, $module); |
745
|
|
|
$moduleNode = $modulesNode->addChild($this->configNodes['translate_module']); |
746
|
|
|
$filesNode = $moduleNode->addChild('files'); |
747
|
|
|
$filesNode->addChild('default', $this->configNodes['translate_files_default']); |
748
|
|
|
} |
749
|
|
|
|
750
|
|
|
/** |
751
|
|
|
* @param SimpleXMLElement $simpleXml |
752
|
|
|
*/ |
753
|
|
|
protected function addDefault(\SimpleXMLElement $simpleXml) |
754
|
|
|
{ |
755
|
|
|
$defaultNode = $simpleXml->default ? $simpleXml->default : $simpleXml->addChild('default'); |
756
|
|
|
$sectionNode = $defaultNode->{$this->configNodes['default_section_name']} |
757
|
|
|
? $defaultNode->{$this->configNodes['default_section_name']} |
758
|
|
|
: $defaultNode->addChild($this->configNodes['default_section_name']); |
759
|
|
|
$groupNode = $sectionNode->{$this->configNodes['default_group_name']} |
760
|
|
|
? $sectionNode->{$this->configNodes['default_group_name']} |
761
|
|
|
: $sectionNode->addChild($this->configNodes['default_group_name']); |
762
|
|
|
$this->removeChildNodeIfNotNull($groupNode, $this->configNodes['default_field_name']); |
763
|
|
|
$groupNode->addChild($this->configNodes['default_field_name'], $this->configNodes['default_field_value']); |
764
|
|
|
} |
765
|
|
|
|
766
|
|
|
/** |
767
|
|
|
* @return string |
768
|
|
|
*/ |
769
|
|
|
protected function getOutFile() |
770
|
|
|
{ |
771
|
|
|
return $this->moduleDirectory . '/etc/config.xml'; |
772
|
|
|
} |
773
|
|
|
|
774
|
|
|
/** |
775
|
|
|
* @param SimpleXMLElement $configXml |
776
|
|
|
*/ |
777
|
|
|
protected function putConfigXml(SimpleXMLElement $configXml) |
778
|
|
|
{ |
779
|
|
|
$outFile = $this->getOutFile(); |
780
|
|
|
|
781
|
|
|
$xml = $configXml->asXML(); |
782
|
|
|
if (false === $xml) { |
783
|
|
|
throw new RuntimeException(sprintf('Failed to get XML from config SimpleXMLElement')); |
784
|
|
|
} |
785
|
|
|
|
786
|
|
|
file_put_contents($outFile, $this->asPrettyXml($xml)); |
787
|
|
|
} |
788
|
|
|
|
789
|
|
|
/** |
790
|
|
|
* @param InputInterface $input |
791
|
|
|
* @return mixed |
792
|
|
|
*/ |
793
|
|
|
protected function hasAddResourceModelOption(InputInterface $input) |
794
|
|
|
{ |
795
|
|
|
return $input->getOption('add-resource-model'); |
796
|
|
|
} |
797
|
|
|
|
798
|
|
|
/** |
799
|
|
|
* @param InputInterface $input |
800
|
|
|
* @return mixed |
801
|
|
|
*/ |
802
|
|
|
protected function hasAddRoutersOption(InputInterface $input) |
803
|
|
|
{ |
804
|
|
|
return $input->getOption('add-routers'); |
805
|
|
|
} |
806
|
|
|
|
807
|
|
|
/** |
808
|
|
|
* @param InputInterface $input |
809
|
|
|
* @return mixed |
810
|
|
|
*/ |
811
|
|
|
protected function hasAddEventsOption(InputInterface $input) |
812
|
|
|
{ |
813
|
|
|
return $input->getOption('add-events'); |
814
|
|
|
} |
815
|
|
|
|
816
|
|
|
/** |
817
|
|
|
* @param InputInterface $input |
818
|
|
|
* @return mixed |
819
|
|
|
*/ |
820
|
|
|
protected function hasAddLayoutUpdatesOptions(InputInterface $input) |
821
|
|
|
{ |
822
|
|
|
return $input->getOption('add-layout-updates'); |
823
|
|
|
} |
824
|
|
|
|
825
|
|
|
/** |
826
|
|
|
* @param InputInterface $input |
827
|
|
|
* @return mixed |
828
|
|
|
*/ |
829
|
|
|
protected function hasAddTranslateOption(InputInterface $input) |
830
|
|
|
{ |
831
|
|
|
return $input->getOption('add-translate'); |
832
|
|
|
} |
833
|
|
|
|
834
|
|
|
/** |
835
|
|
|
* @param InputInterface $input |
836
|
|
|
* @return mixed |
837
|
|
|
*/ |
838
|
|
|
protected function hasAddDefaultOption(InputInterface $input) |
839
|
|
|
{ |
840
|
|
|
return $input->getOption('add-default'); |
841
|
|
|
} |
842
|
|
|
|
843
|
|
|
/** |
844
|
|
|
* @param InputInterface $input |
845
|
|
|
* @return mixed |
846
|
|
|
*/ |
847
|
|
|
protected function shouldSetVersion(InputInterface $input) |
848
|
|
|
{ |
849
|
|
|
return $input->getOption('set-version'); |
850
|
|
|
} |
851
|
|
|
|
852
|
|
|
/** |
853
|
|
|
* @param InputInterface $input |
854
|
|
|
* @return mixed |
855
|
|
|
*/ |
856
|
|
|
protected function shouldAddBlocks(InputInterface $input) |
857
|
|
|
{ |
858
|
|
|
return $input->getOption('add-blocks'); |
859
|
|
|
} |
860
|
|
|
|
861
|
|
|
/** |
862
|
|
|
* @param InputInterface $input |
863
|
|
|
* @return mixed |
864
|
|
|
*/ |
865
|
|
|
protected function shouldAddHelpers(InputInterface $input) |
866
|
|
|
{ |
867
|
|
|
return $input->getOption('add-helpers'); |
868
|
|
|
} |
869
|
|
|
|
870
|
|
|
/** |
871
|
|
|
* @param InputInterface $input |
872
|
|
|
* @return mixed |
873
|
|
|
*/ |
874
|
|
|
protected function shouldAddModels(InputInterface $input) |
875
|
|
|
{ |
876
|
|
|
return $input->getOption('add-models'); |
877
|
|
|
} |
878
|
|
|
|
879
|
|
|
/** |
880
|
|
|
* @param InputInterface $input |
881
|
|
|
* @return mixed |
882
|
|
|
*/ |
883
|
|
|
protected function shouldAddAll(InputInterface $input) |
884
|
|
|
{ |
885
|
|
|
return $input->getOption('add-all'); |
886
|
|
|
} |
887
|
|
|
|
888
|
|
|
/** |
889
|
|
|
* Gets module namespace e.g. Company_Modulename |
890
|
|
|
* |
891
|
|
|
* @return string |
892
|
|
|
*/ |
893
|
|
|
protected function getModuleNamespace() |
894
|
|
|
{ |
895
|
|
|
return $this->vendorNamespace . '_' . $this->moduleName; |
896
|
|
|
} |
897
|
|
|
|
898
|
|
|
/** |
899
|
|
|
* @return string |
900
|
|
|
*/ |
901
|
|
|
protected function getLowercaseModuleNamespace() |
902
|
|
|
{ |
903
|
|
|
return strtolower($this->vendorNamespace . '_' . $this->moduleName); |
904
|
|
|
} |
905
|
|
|
|
906
|
|
|
/** |
907
|
|
|
* @return string |
908
|
|
|
*/ |
909
|
|
|
protected function getLowercaseModuleName() |
910
|
|
|
{ |
911
|
|
|
return strtolower($this->moduleName); |
912
|
|
|
} |
913
|
|
|
|
914
|
|
|
/** |
915
|
|
|
* Removes a child node if not null. |
916
|
|
|
* Deals with duplications of nodes when already in config |
917
|
|
|
* |
918
|
|
|
* @param $node |
919
|
|
|
* @param $child |
920
|
|
|
*/ |
921
|
|
|
protected function removeChildNodeIfNotNull($node, $child) |
922
|
|
|
{ |
923
|
|
|
if (!is_null($node->{$child})) { |
924
|
|
|
unset($node->{$child}); |
925
|
|
|
} |
926
|
|
|
} |
927
|
|
|
|
928
|
|
|
/** |
929
|
|
|
* Formats given string as pretty xml |
930
|
|
|
* |
931
|
|
|
* @param string $string |
932
|
|
|
* |
933
|
|
|
* @return string |
934
|
|
|
*/ |
935
|
|
|
protected function asPrettyXml($string) |
936
|
|
|
{ |
937
|
|
|
$string = preg_replace("/>\\s*</", ">\n<", $string); |
938
|
|
|
$xmlArray = explode("\n", $string); |
939
|
|
|
$currIndent = 0; |
940
|
|
|
$indent = " "; |
941
|
|
|
$string = array_shift($xmlArray) . "\n"; |
942
|
|
|
foreach ($xmlArray as $element) { |
943
|
|
|
if (preg_match('/^<([\w])+[^>\/]*>$/U', $element)) { |
944
|
|
|
$string .= str_repeat($indent, $currIndent) . $element . "\n"; |
945
|
|
|
$currIndent += 1; |
946
|
|
|
} elseif (preg_match('/^<\/.+>$/', $element)) { |
947
|
|
|
$currIndent -= 1; |
948
|
|
|
$string .= str_repeat($indent, $currIndent) . $element . "\n"; |
949
|
|
|
} else { |
950
|
|
|
$string .= str_repeat($indent, $currIndent) . $element . "\n"; |
951
|
|
|
} |
952
|
|
|
} |
953
|
|
|
|
954
|
|
|
return $string; |
955
|
|
|
} |
956
|
|
|
} |
957
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.