1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace N98\Magento\Command\Developer\Module; |
4
|
|
|
|
5
|
|
|
use InvalidArgumentException; |
6
|
|
|
use N98\Magento\Command\AbstractMagentoCommand; |
7
|
|
|
use N98\Util\Console\Helper\TwigHelper; |
8
|
|
|
use RuntimeException; |
9
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
10
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
11
|
|
|
use Symfony\Component\Console\Input\InputOption; |
12
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Create a magento module skeleton |
16
|
|
|
*/ |
17
|
|
|
class CreateCommand extends AbstractMagentoCommand |
18
|
|
|
{ |
19
|
|
|
/** |
20
|
|
|
* @var array |
21
|
|
|
*/ |
22
|
|
|
protected $twigVars = array(); |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @var string |
26
|
|
|
*/ |
27
|
|
|
protected $baseFolder; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var string |
31
|
|
|
*/ |
32
|
|
|
protected $moduleDirectory; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var string |
36
|
|
|
*/ |
37
|
|
|
protected $vendorNamespace; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var string |
41
|
|
|
*/ |
42
|
|
|
protected $moduleName; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
protected $codePool; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @var bool |
51
|
|
|
*/ |
52
|
|
|
protected $modmanMode = false; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @var OutputInterface |
56
|
|
|
*/ |
57
|
|
|
private $output; |
58
|
|
|
|
59
|
|
|
protected function configure() |
60
|
|
|
{ |
61
|
|
|
$this |
62
|
|
|
->setName('dev:module:create') |
63
|
|
|
->addArgument('vendorNamespace', InputArgument::REQUIRED, 'Namespace (your company prefix)') |
64
|
|
|
->addArgument('moduleName', InputArgument::REQUIRED, 'Name of your module.') |
65
|
|
|
->addArgument('codePool', InputArgument::OPTIONAL, 'Codepool (local, community)', 'local') |
66
|
|
|
->addOption('add-controllers', null, InputOption::VALUE_NONE, 'Adds controllers') |
67
|
|
|
->addOption('add-blocks', null, InputOption::VALUE_NONE, 'Adds blocks') |
68
|
|
|
->addOption('add-helpers', null, InputOption::VALUE_NONE, 'Adds helpers') |
69
|
|
|
->addOption('add-models', null, InputOption::VALUE_NONE, 'Adds models') |
70
|
|
|
->addOption('add-setup', null, InputOption::VALUE_NONE, 'Adds SQL setup') |
71
|
|
|
->addOption('add-all', null, InputOption::VALUE_NONE, 'Adds blocks, helpers and models') |
72
|
|
|
->addOption('modman', null, InputOption::VALUE_NONE, 'Create all files in folder with a modman file.') |
73
|
|
|
->addOption('add-readme', null, InputOption::VALUE_NONE, 'Adds a readme.md file to generated module') |
74
|
|
|
->addOption('add-composer', null, InputOption::VALUE_NONE, 'Adds a composer.json file to generated module') |
75
|
|
|
->addOption('author-name', null, InputOption::VALUE_OPTIONAL, 'Author for readme.md or composer.json') |
76
|
|
|
->addOption('author-email', null, InputOption::VALUE_OPTIONAL, 'Author for readme.md or composer.json') |
77
|
|
|
->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Description for readme.md or composer.json') |
78
|
|
|
->setDescription('Create and register a new magento module.'); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* @param InputInterface $input |
83
|
|
|
* @param OutputInterface $output |
84
|
|
|
* |
85
|
|
|
* @return int|void |
86
|
|
|
* @throws InvalidArgumentException |
87
|
|
|
*/ |
88
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
89
|
|
|
{ |
90
|
|
|
$this->output = $output; |
91
|
|
|
|
92
|
|
|
$this->modmanMode = $input->getOption('modman'); |
93
|
|
|
if ($input->getOption('add-all')) { |
94
|
|
|
$input->setOption('add-controllers', true); |
95
|
|
|
$input->setOption('add-blocks', true); |
96
|
|
|
$input->setOption('add-helpers', true); |
97
|
|
|
$input->setOption('add-models', true); |
98
|
|
|
$input->setOption('add-setup', true); |
99
|
|
|
$input->setOption('add-readme', true); |
100
|
|
|
$input->setOption('add-composer', true); |
101
|
|
|
} |
102
|
|
|
if (!$this->modmanMode) { |
103
|
|
|
$this->detectMagento($output); |
104
|
|
|
} |
105
|
|
|
$this->baseFolder = __DIR__ . '/../../../../../../res/module/create'; |
106
|
|
|
|
107
|
|
|
$this->vendorNamespace = ucfirst($input->getArgument('vendorNamespace')); |
108
|
|
|
$this->moduleName = ucfirst($input->getArgument('moduleName')); |
109
|
|
|
$this->codePool = $input->getArgument('codePool'); |
110
|
|
|
if (!in_array($this->codePool, array('local', 'community'))) { |
111
|
|
|
throw new InvalidArgumentException('Code pool must "community" or "local"'); |
112
|
|
|
} |
113
|
|
|
$this->initView($input); |
114
|
|
|
$this->createModuleDirectories($input, $output); |
115
|
|
|
$this->writeEtcModules($output); |
116
|
|
|
$this->writeModuleConfig($output); |
117
|
|
|
$this->writeReadme($input, $output); |
118
|
|
|
if ($this->modmanMode) { |
119
|
|
|
$this->writeModmanFile($output); |
120
|
|
|
} |
121
|
|
|
$this->writeComposerConfig($input, $output); |
122
|
|
|
$this->addAdditionalFiles($output); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
protected function initView(InputInterface $input) |
126
|
|
|
{ |
127
|
|
|
$this->twigVars = array( |
128
|
|
|
'vendorNamespace' => $this->vendorNamespace, |
129
|
|
|
'moduleName' => $this->moduleName, |
130
|
|
|
'codePool' => $this->codePool, |
131
|
|
|
'createControllers' => $input->getOption('add-controllers'), |
132
|
|
|
'createBlocks' => $input->getOption('add-blocks'), |
133
|
|
|
'createModels' => $input->getOption('add-models'), |
134
|
|
|
'createHelpers' => $input->getOption('add-helpers'), |
135
|
|
|
'createSetup' => $input->getOption('add-setup'), |
136
|
|
|
'authorName' => $input->getOption('author-name'), |
137
|
|
|
'authorEmail' => $input->getOption('author-email'), |
138
|
|
|
'description' => $input->getOption('description'), |
139
|
|
|
); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* @param InputInterface $input |
144
|
|
|
* @param OutputInterface $output |
145
|
|
|
*/ |
146
|
|
|
protected function createModuleDirectories(InputInterface $input, OutputInterface $output) |
147
|
|
|
{ |
148
|
|
|
if ($this->modmanMode) { |
149
|
|
|
$modManDir = $this->vendorNamespace . '_' . $this->moduleName . '/src'; |
150
|
|
|
if (file_exists($modManDir)) { |
151
|
|
|
throw new RuntimeException('Module already exists. Stop.'); |
152
|
|
|
} |
153
|
|
|
mkdir($modManDir, 0777, true); |
154
|
|
|
$this->_magentoRootFolder = './' . $modManDir; |
155
|
|
|
mkdir($this->_magentoRootFolder . '/app/etc/modules', 0777, true); |
156
|
|
|
} |
157
|
|
|
$moduleDir = sprintf( |
158
|
|
|
'%s/app/code/%s/%s/%s', |
159
|
|
|
$this->_magentoRootFolder, |
160
|
|
|
$this->codePool, |
161
|
|
|
$this->vendorNamespace, |
162
|
|
|
$this->moduleName |
163
|
|
|
); |
164
|
|
|
|
165
|
|
|
if (file_exists($moduleDir)) { |
166
|
|
|
throw new RuntimeException('Module already exists. Stop.'); |
167
|
|
|
} |
168
|
|
|
$this->moduleDirectory = $moduleDir; |
169
|
|
|
mkdir($this->moduleDirectory, 0777, true); |
170
|
|
|
$output->writeln('<info>Created directory: <comment>' . $this->moduleDirectory . '<comment></info>'); |
171
|
|
|
|
172
|
|
|
// Add etc folder |
173
|
|
|
$this->createModuleDirectory('etc'); |
174
|
|
|
|
175
|
|
|
// Add controllers folder |
176
|
|
|
if ($input->getOption('add-controllers')) { |
177
|
|
|
$this->createModuleDirectory('controllers'); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
// Add blocks folder |
181
|
|
|
if ($input->getOption('add-blocks')) { |
182
|
|
|
$this->createModuleDirectory('Block'); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
// Add helpers folder |
186
|
|
|
if ($input->getOption('add-helpers')) { |
187
|
|
|
$this->createModuleDirectory('Helper'); |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
// Add models folder |
191
|
|
|
if ($input->getOption('add-models')) { |
192
|
|
|
$this->createModuleDirectory('Model'); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
// Create SQL and Data folder |
196
|
|
|
if ($input->getOption('add-setup')) { |
197
|
|
|
$sqlSetupFolder = $this->moduleDirectory . '/sql/' . strtolower($this->vendorNamespace) . '_' . |
198
|
|
|
strtolower($this->moduleName) . '_setup'; |
199
|
|
|
mkdir($sqlSetupFolder, 0777, true); |
200
|
|
|
$output->writeln('<info>Created directory: <comment>' . $sqlSetupFolder . '<comment></info>'); |
201
|
|
|
|
202
|
|
|
$dataSetupFolder = $this->moduleDirectory . '/data/' . strtolower($this->vendorNamespace) . '_' . |
203
|
|
|
strtolower($this->moduleName) . '_setup'; |
204
|
|
|
mkdir($dataSetupFolder, 0777, true); |
205
|
|
|
$output->writeln('<info>Created directory: <comment>' . $dataSetupFolder . '<comment></info>'); |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* @param string $directory |
211
|
|
|
*/ |
212
|
|
|
private function createModuleDirectory($directory) |
213
|
|
|
{ |
214
|
|
|
$path = $this->moduleDirectory . '/' . $directory; |
215
|
|
|
mkdir($path); |
216
|
|
|
$this->output->writeln('<info>Created directory: <comment>' . $path . '<comment></info>'); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
protected function writeEtcModules(OutputInterface $output) |
220
|
|
|
{ |
221
|
|
|
$outFile = sprintf( |
222
|
|
|
'%s/app/etc/modules/%s_%s.xml', |
223
|
|
|
$this->_magentoRootFolder, |
224
|
|
|
$this->vendorNamespace, |
225
|
|
|
$this->moduleName |
226
|
|
|
); |
227
|
|
|
|
228
|
|
|
/** @var $helper TwigHelper */ |
229
|
|
|
$helper = $this->getHelper('twig'); |
230
|
|
|
$buffer = $helper->render('dev/module/create/app/etc/modules/definition.twig', $this->twigVars); |
231
|
|
|
$size = file_put_contents($outFile, $buffer); |
232
|
|
|
|
233
|
|
|
$output->writeln('<info>Created file: <comment>' . $outFile . '<comment> (' . $size . ' bytes)</info>'); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
View Code Duplication |
protected function writeModuleConfig(OutputInterface $output) |
|
|
|
|
237
|
|
|
{ |
238
|
|
|
$outFile = $this->moduleDirectory . '/etc/config.xml'; |
239
|
|
|
file_put_contents( |
240
|
|
|
$outFile, |
241
|
|
|
$this->getHelper('twig')->render('dev/module/create/app/etc/modules/config.twig', $this->twigVars) |
242
|
|
|
); |
243
|
|
|
|
244
|
|
|
$output->writeln('<info>Created file: <comment>' . $outFile . '<comment></info>'); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
View Code Duplication |
protected function writeModmanFile(OutputInterface $output) |
|
|
|
|
248
|
|
|
{ |
249
|
|
|
$outFile = $this->_magentoRootFolder . '/../modman'; |
250
|
|
|
file_put_contents( |
251
|
|
|
$outFile, |
252
|
|
|
$this->getHelper('twig')->render('dev/module/create/modman.twig', $this->twigVars) |
253
|
|
|
); |
254
|
|
|
$output->writeln('<info>Created file: <comment>' . $outFile . '<comment></info>'); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* Write standard readme |
259
|
|
|
* |
260
|
|
|
* TODO: Make author name / company URL and more configurable |
261
|
|
|
* |
262
|
|
|
* @see https://raw.github.com/sprankhub/Magento-Extension-Sample-Readme/master/readme.markdown |
263
|
|
|
* |
264
|
|
|
* @param InputInterface $input |
265
|
|
|
* @param OutputInterface $output |
266
|
|
|
*/ |
267
|
|
View Code Duplication |
protected function writeReadme($input, $output) |
|
|
|
|
268
|
|
|
{ |
269
|
|
|
if (!$input->getOption('add-readme')) { |
270
|
|
|
return; |
271
|
|
|
} |
272
|
|
|
if ($this->modmanMode) { |
273
|
|
|
$outFile = $this->_magentoRootFolder . '/../readme.md'; |
274
|
|
|
} else { |
275
|
|
|
$outFile = $this->moduleDirectory . '/etc/readme.md'; |
276
|
|
|
} |
277
|
|
|
file_put_contents( |
278
|
|
|
$outFile, |
279
|
|
|
$this->getHelper('twig')->render('dev/module/create/app/etc/modules/readme.twig', $this->twigVars) |
280
|
|
|
); |
281
|
|
|
$output->writeln('<info>Created file: <comment>' . $outFile . '<comment></info>'); |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Write composer.json |
286
|
|
|
* |
287
|
|
|
* @param InputInterface $input |
288
|
|
|
* @param OutputInterface $output |
289
|
|
|
*/ |
290
|
|
View Code Duplication |
protected function writeComposerConfig(InputInterface $input, OutputInterface $output) |
|
|
|
|
291
|
|
|
{ |
292
|
|
|
if (!$input->getOption('add-composer')) { |
293
|
|
|
return; |
294
|
|
|
} |
295
|
|
|
if ($this->modmanMode) { |
296
|
|
|
$outFile = $this->_magentoRootFolder . '/../composer.json'; |
297
|
|
|
} else { |
298
|
|
|
$outFile = $this->moduleDirectory . '/etc/composer.json'; |
299
|
|
|
} |
300
|
|
|
file_put_contents( |
301
|
|
|
$outFile, |
302
|
|
|
$this->getHelper('twig')->render('dev/module/create/composer.twig', $this->twigVars) |
303
|
|
|
); |
304
|
|
|
$output->writeln('<info>Created file: <comment>' . $outFile . '<comment></info>'); |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
protected function addAdditionalFiles(OutputInterface $output) |
308
|
|
|
{ |
309
|
|
|
$config = $this->getCommandConfig(); |
310
|
|
|
if (isset($config['additionalFiles']) && is_array($config['additionalFiles'])) { |
311
|
|
|
foreach ($config['additionalFiles'] as $template => $outFileTemplate) { |
312
|
|
|
$outFile = $this->getOutfile($outFileTemplate); |
313
|
|
|
$outFileDir = dirname($outFile); |
314
|
|
|
if (!is_dir($outFileDir)) { |
315
|
|
|
mkdir($outFileDir, 0777, true); |
316
|
|
|
} |
317
|
|
|
file_put_contents($outFile, $this->getHelper('twig')->render($template, $this->twigVars)); |
318
|
|
|
$output->writeln('<info>Created file: <comment>' . $outFile . '<comment></info>'); |
319
|
|
|
} |
320
|
|
|
} |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* @param string $filename |
325
|
|
|
* @return string |
326
|
|
|
*/ |
327
|
|
|
private function getOutfile($filename) |
328
|
|
|
{ |
329
|
|
|
$paths = array( |
330
|
|
|
'rootDir' => $this->_magentoRootFolder, |
331
|
|
|
'moduleDir' => $this->moduleDirectory, |
332
|
|
|
); |
333
|
|
|
|
334
|
|
|
/** @var $twig TwigHelper */ |
335
|
|
|
$twig = $this->getHelper('twig'); |
336
|
|
|
return $twig->renderString($filename, array_merge($this->twigVars, $paths)); |
337
|
|
|
} |
338
|
|
|
} |
339
|
|
|
|
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.