1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Acacha\Llum\Console; |
4
|
|
|
|
5
|
|
|
use Illuminate\Config\Repository; |
6
|
|
|
use Symfony\Component\Console\Command\Command; |
7
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
8
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
9
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
10
|
|
|
use Symfony\Component\Process\Process; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class LlumCommand. |
14
|
|
|
*/ |
15
|
|
|
abstract class LlumCommand extends Command |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* The output interface. |
19
|
|
|
* |
20
|
|
|
* @var OutputInterface |
21
|
|
|
*/ |
22
|
|
|
protected $output; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Command name. |
26
|
|
|
* |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
protected $commandName; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Command description. |
33
|
|
|
* |
34
|
|
|
* @var string |
35
|
|
|
*/ |
36
|
|
|
protected $commandDescription; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Command argument. |
40
|
|
|
* |
41
|
|
|
* @var string |
42
|
|
|
*/ |
43
|
|
|
protected $argument; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Argument type. |
47
|
|
|
* |
48
|
|
|
* @var int |
49
|
|
|
*/ |
50
|
|
|
protected $argumentType = InputArgument::REQUIRED; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Command argument description. |
54
|
|
|
* |
55
|
|
|
* @var string |
56
|
|
|
*/ |
57
|
|
|
protected $argumentDescription; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Method to execute. |
61
|
|
|
* |
62
|
|
|
* @var string |
63
|
|
|
*/ |
64
|
|
|
protected $method; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Laravel config file (config/app.php). |
68
|
|
|
* |
69
|
|
|
* @var string |
70
|
|
|
*/ |
71
|
|
|
protected $laravel_config_file; |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Path to config folder. |
75
|
|
|
* |
76
|
|
|
* @var string |
77
|
|
|
*/ |
78
|
|
|
protected $configPath; |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Avoids using bash using stubs instead to modify config/app.php file. |
82
|
|
|
* |
83
|
|
|
* @var bool |
84
|
|
|
*/ |
85
|
|
|
protected $noBash = false; |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Config repository. |
89
|
|
|
* |
90
|
|
|
* @var Repository |
91
|
|
|
*/ |
92
|
|
|
protected $config; |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* LlumCommand constructor. |
96
|
|
|
*/ |
97
|
|
|
public function __construct() |
98
|
|
|
{ |
99
|
|
|
parent::__construct(); |
100
|
|
|
$this->configPath = __DIR__.'/../config/'; |
101
|
|
|
$this->laravel_config_file = getcwd().'/config/app.php'; |
102
|
|
|
$this->config = $this->obtainConfig(); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* Check if port is in use. |
107
|
|
|
* |
108
|
|
|
* @param int $port |
109
|
|
|
* @param string $host |
110
|
|
|
* @param int $timeout |
111
|
|
|
* |
112
|
|
|
* @return bool |
113
|
|
|
*/ |
114
|
|
|
protected function check_port($port = 8000, $host = '127.0.0.1', $timeout = 3) |
115
|
|
|
{ |
116
|
|
|
$fp = @fsockopen($host, $port, $errno, $errstr, $timeout); |
117
|
|
|
if (! $fp) { |
118
|
|
|
return true; |
119
|
|
|
} else { |
120
|
|
|
fclose($fp); |
121
|
|
|
|
122
|
|
|
return false; |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Install /config/app.php file using bash script. |
128
|
|
|
*/ |
129
|
|
|
protected function installConfigAppFileWithBash() |
130
|
|
|
{ |
131
|
|
|
passthru(__DIR__.'/../bash_scripts/iluminar.sh '.$this->laravel_config_file); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Install /stubs/app.php into /config/app.php. |
136
|
|
|
*/ |
137
|
|
|
protected function installConfigAppFileWithStubs() |
138
|
|
|
{ |
139
|
|
|
copy(__DIR__.'/stubs/app.php', $this->laravel_config_file); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* Check if Laravel config file exists. |
144
|
|
|
* |
145
|
|
|
* @return bool |
146
|
|
|
*/ |
147
|
|
|
protected function checkIfLaravelConfigFileExists() |
148
|
|
|
{ |
149
|
|
|
return file_exists($this->laravel_config_file); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Install llum custom config/app.php file. |
154
|
|
|
* |
155
|
|
|
* @return int |
156
|
|
|
*/ |
157
|
|
|
protected function installConfigAppFile() |
158
|
|
|
{ |
159
|
|
|
if (! $this->checkIfLaravelConfigFileExists()) { |
160
|
|
|
$this->output->writeln('<error>File '.$this->laravel_config_file.' doesn\'t exists'); |
161
|
|
|
|
162
|
|
|
return -1; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
if ($this->configAppFileAlreadyInstalled()) { |
166
|
|
|
$this->output->writeln('<info>File '.$this->laravel_config_file.' already supports llum.</info>'); |
167
|
|
|
|
168
|
|
|
return 0; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
if ($this->isNoBashActive()) { |
172
|
|
|
$this->installConfigAppFileWithStubs(); |
173
|
|
|
$this->output->writeln('<info>File '.$this->laravel_config_file.' overwrited correctly with and stub.</info>'); |
174
|
|
|
} else { |
175
|
|
|
$this->installConfigAppFileWithBash(); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
return 0; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* Check if config/app.php stub file is already installed. |
183
|
|
|
* |
184
|
|
|
* @return bool |
185
|
|
|
*/ |
186
|
|
|
protected function configAppFileAlreadyInstalled() |
187
|
|
|
{ |
188
|
|
|
if (strpos(file_get_contents($this->laravel_config_file), '#llum_providers') !== false) { |
189
|
|
|
return true; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
return false; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Add Laravel IDE Helper provider to config/app.php file. |
197
|
|
|
* |
198
|
|
|
* @return int|null |
199
|
|
|
*/ |
200
|
|
|
protected function addLaravelIdeHelperProvider() |
201
|
|
|
{ |
202
|
|
|
return $this->addProvider('Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class'); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Add provider to config/app.php file. |
207
|
|
|
* |
208
|
|
|
* @param $provider |
209
|
|
|
* |
210
|
|
|
* @return int|null |
211
|
|
|
*/ |
212
|
|
|
private function addProvider($provider) |
213
|
|
|
{ |
214
|
|
|
return $this->addTextIntoMountPoint('#llum_providers', $provider); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* Add alias to config/app.php file. |
219
|
|
|
* |
220
|
|
|
* @param string $alias |
221
|
|
|
* |
222
|
|
|
* @return int|null |
223
|
|
|
*/ |
224
|
|
|
private function addAlias($alias) |
225
|
|
|
{ |
226
|
|
|
return $this->addTextIntoMountPoint('#llum_aliases', $alias); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Insert text into file using mountpoint. Mountpoint is maintained at file. |
231
|
|
|
* |
232
|
|
|
* @param string $mountpoint |
233
|
|
|
* @param $textToAdd |
234
|
|
|
* |
235
|
|
|
* @return int|null |
236
|
|
|
*/ |
237
|
|
|
private function addTextIntoMountPoint($mountpoint, $textToAdd) |
238
|
|
|
{ |
239
|
|
|
passthru( |
240
|
|
|
'sed -i \'s/.*'.$mountpoint.'.*/ \ \ \ \ \ \ \ '.$this->scapeSingleQuotes(preg_quote($textToAdd)).',\n \ \ \ \ \ \ \ '.$mountpoint.'/\' '.$this->laravel_config_file, $error); |
241
|
|
|
|
242
|
|
|
return $error; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* scape single quotes for sed using \x27. |
247
|
|
|
* |
248
|
|
|
* @param string $str |
249
|
|
|
* |
250
|
|
|
* @return string |
251
|
|
|
*/ |
252
|
|
|
private function scapeSingleQuotes($str) |
253
|
|
|
{ |
254
|
|
|
return str_replace("'", '\\x27', $str); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* Require composer package. |
259
|
|
|
* |
260
|
|
|
* @param $package |
261
|
|
|
*/ |
262
|
|
|
private function requireComposerPackage($package) |
263
|
|
|
{ |
264
|
|
|
$composer = $this->findComposer(); |
265
|
|
|
|
266
|
|
|
$process = new Process($composer.' require '.$package.'', null, null, null, null); |
267
|
|
|
$this->output->writeln('<info>Running composer require '.$package.'</info>'); |
268
|
|
|
$process->run(function ($type, $line) { |
269
|
|
|
$this->output->write($line); |
270
|
|
|
}); |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* Get the composer command for the environment. |
275
|
|
|
* |
276
|
|
|
* @return string |
277
|
|
|
*/ |
278
|
|
|
private function findComposer() |
279
|
|
|
{ |
280
|
|
|
if (file_exists(getcwd().'/composer.phar')) { |
281
|
|
|
return '"'.PHP_BINARY.'" composer.phar"'; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
return 'composer'; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Installs provider in laravel config/app.php file. |
289
|
|
|
* |
290
|
|
|
* @param $provider |
291
|
|
|
*/ |
292
|
|
|
protected function provider($provider) |
293
|
|
|
{ |
294
|
|
|
if ($this->installConfigAppFile() == -1) { |
295
|
|
|
return; |
296
|
|
|
} |
297
|
|
|
$this->addProvider($provider); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* Installs alias/facade in laravel config/app.php file. |
302
|
|
|
* |
303
|
|
|
* @param $aliasName |
304
|
|
|
* @param $aliasClass |
305
|
|
|
*/ |
306
|
|
|
protected function alias($aliasName, $aliasClass) |
307
|
|
|
{ |
308
|
|
|
if ($this->installConfigAppFile() == -1) { |
309
|
|
|
return; |
310
|
|
|
} |
311
|
|
|
$this->addAlias("'".$aliasName."' => ".$aliasClass); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* get package from config. |
316
|
|
|
* |
317
|
|
|
* @param $name |
318
|
|
|
* |
319
|
|
|
* @return array |
320
|
|
|
*/ |
321
|
|
|
private function getPackageFromConfig($name) |
322
|
|
|
{ |
323
|
|
|
//Check if package name is a composer package name |
324
|
|
|
if (str_contains($name, '/')) { |
325
|
|
|
return $this->config->get($this->getPackageNameByComposerName($name)); |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
return $this->config->get($name); |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* Add providers to Laravel config file. |
333
|
|
|
* |
334
|
|
|
* @param $providers |
335
|
|
|
*/ |
336
|
|
|
protected function addProviders($providers) |
337
|
|
|
{ |
338
|
|
|
foreach ($providers as $provider) { |
339
|
|
|
$this->output->writeln('<info>Adding '.$provider.' to Laravel config app.php file</info>'); |
340
|
|
|
$this->addProvider($provider); |
341
|
|
|
} |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Add aliases to Laravel config file. |
346
|
|
|
* |
347
|
|
|
* @param $aliases |
348
|
|
|
*/ |
349
|
|
|
protected function addAliases($aliases) |
350
|
|
|
{ |
351
|
|
|
foreach ($aliases as $alias => $aliasClass) { |
352
|
|
|
$this->output->writeln('<info>Adding '.$aliasClass.' to Laravel config app.php file</info>'); |
353
|
|
|
$this->addAlias("'$alias' => ".$aliasClass); |
354
|
|
|
} |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
/** |
358
|
|
|
* Installs laravel package form config/packages.php file. |
359
|
|
|
* |
360
|
|
|
* @param string $name |
361
|
|
|
* @return int -1 if error occurred |
362
|
|
|
*/ |
363
|
|
|
protected function package($name) |
364
|
|
|
{ |
365
|
|
|
$package = $this->getPackageFromConfig($name); |
366
|
|
|
|
367
|
|
|
if ($package == null) { |
368
|
|
|
$this->showPackageNotFoundError($name); |
369
|
|
|
|
370
|
|
|
return -1; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
list($name, $providers, $aliases, $after) = array_fill(0, 4, null); |
374
|
|
|
extract($package, EXTR_IF_EXISTS); |
375
|
|
|
|
376
|
|
|
$this->requireComposerPackage($name); |
377
|
|
|
|
378
|
|
|
if ($this->installConfigAppFile() == -1) { |
379
|
|
|
return -1; |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
$this->addProviders($providers); |
383
|
|
|
|
384
|
|
|
$this->addAliases($aliases); |
385
|
|
|
|
386
|
|
|
if ($after != null) { |
387
|
|
|
passthru($after); |
388
|
|
|
} |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* Get config repository. |
393
|
|
|
* |
394
|
|
|
* @return Repository |
395
|
|
|
*/ |
396
|
|
|
protected function obtainConfig() |
397
|
|
|
{ |
398
|
|
|
return new Repository(require $this->configPath.'packages.php'); |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
/** |
402
|
|
|
* @param InputInterface $input |
403
|
|
|
* @param OutputInterface $output |
404
|
|
|
*/ |
405
|
|
|
protected function initialize(InputInterface $input, OutputInterface $output) |
406
|
|
|
{ |
407
|
|
|
parent::initialize($input, $output); |
408
|
|
|
if ($input->hasOption('no-bash')) { |
409
|
|
|
$this->noBash = $input->getOption('no-bash'); |
410
|
|
|
} |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
/** |
414
|
|
|
* Check is --no-bash option is active. |
415
|
|
|
* |
416
|
|
|
* @return bool |
417
|
|
|
*/ |
418
|
|
|
private function isNoBashActive() |
419
|
|
|
{ |
420
|
|
|
return $this->noBash; |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* Get package name by composer package name. |
425
|
|
|
* |
426
|
|
|
* @param $composerPackageName |
427
|
|
|
* |
428
|
|
|
* @return string |
429
|
|
|
*/ |
430
|
|
|
private function getPackageNameByComposerName($composerPackageName) |
431
|
|
|
{ |
432
|
|
|
foreach ($this->config->all() as $key => $configItem) { |
433
|
|
|
if ($configItem[ 'name' ] == $composerPackageName) { |
434
|
|
|
return $key; |
435
|
|
|
} |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
return; |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
/** |
442
|
|
|
* Show package not found error. |
443
|
|
|
* |
444
|
|
|
* @param $name |
445
|
|
|
*/ |
446
|
|
|
protected function showPackageNotFoundError($name) |
447
|
|
|
{ |
448
|
|
|
$this->output->writeln('<error>Package '.$name.' not found in file '.$this->configPath.'packages.php</error>'); |
449
|
|
|
|
450
|
|
|
return; |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
/** |
454
|
|
|
* Configure the command options. |
455
|
|
|
* |
456
|
|
|
* @param ConsoleCommand $command |
457
|
|
|
*/ |
458
|
|
|
protected function configureCommand(ConsoleCommand $command) |
459
|
|
|
{ |
460
|
|
|
$this->ignoreValidationErrors(); |
461
|
|
|
|
462
|
|
|
$this->setName($command->name()) |
|
|
|
|
463
|
|
|
->setDescription($command->description()); |
|
|
|
|
464
|
|
|
if ($command->argument() != null) { |
465
|
|
|
$this->addArgument($command->argument()[ 'name' ], |
466
|
|
|
$command->argument()[ 'type' ], |
467
|
|
|
$command->argument()[ 'description' ] |
468
|
|
|
); |
469
|
|
|
} |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* Execute the command. |
474
|
|
|
* |
475
|
|
|
* @param InputInterface $input |
476
|
|
|
* @param OutputInterface $output |
477
|
|
|
* |
478
|
|
|
* @return int|null|void |
479
|
|
|
*/ |
480
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
481
|
|
|
{ |
482
|
|
|
$this->output = $output; |
483
|
|
|
$method = $this->method; |
484
|
|
|
if ($this->argument != null) { |
485
|
|
|
$argument = $input->getArgument($this->argument); |
486
|
|
|
$this->$method($argument); |
487
|
|
|
|
488
|
|
|
return; |
489
|
|
|
} |
490
|
|
|
|
491
|
|
|
$this->$method(); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
/** |
495
|
|
|
* Configure the command options. |
496
|
|
|
*/ |
497
|
|
|
protected function configure() |
498
|
|
|
{ |
499
|
|
|
$command = new ConsoleCommand(); |
500
|
|
|
|
501
|
|
|
$command->name($this->commandName) |
|
|
|
|
502
|
|
|
->description($this->commandDescription); |
503
|
|
|
|
504
|
|
|
if ($this->argument != null) { |
505
|
|
|
$command->argument([ |
506
|
|
|
'name' => $this->argument, |
507
|
|
|
'description' => $this->argumentDescription, |
508
|
|
|
'type' => $this->argumentType, |
509
|
|
|
]); |
510
|
|
|
} |
511
|
|
|
$this->configureCommand($command); |
512
|
|
|
} |
513
|
|
|
} |
514
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.