Skip to content

Commit 6a68b13

Browse files
authored
CLI Optimization (#71)
* enhance(console): Clean up implementation of Command and GeneratorCommand * enhance(console): Separate clearLine, exec, task, and title into traits * enhance(console): Better replaceClass implementation * chore(console): Remove unused Schedule class
1 parent b4ec027 commit 6a68b13

File tree

8 files changed

+151
-330
lines changed

8 files changed

+151
-330
lines changed

src/Acorn/Console/Commands/Command.php

Lines changed: 5 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
namespace Roots\Acorn\Console\Commands;
44

5-
use Symfony\Component\Process\Process;
6-
use Illuminate\Support\Str;
75
use Illuminate\Console\Command as CommandBase;
86

97
abstract class Command extends CommandBase
108
{
9+
use \Roots\Acorn\Console\Concerns\ClearLine;
10+
use \Roots\Acorn\Console\Concerns\Exec;
11+
use \Roots\Acorn\Console\Concerns\Task;
12+
use \Roots\Acorn\Console\Concerns\Title;
13+
1114
/**
1215
* The application implementation.
1316
*
@@ -22,95 +25,4 @@ public function setLaravel($laravel)
2225
{
2326
parent::setLaravel($this->app = $laravel);
2427
}
25-
26-
/**
27-
* Write a string in a title box.
28-
*
29-
* @param string $title
30-
* @return \Roots\Acorn\Console\Commands\Command
31-
*/
32-
public function title($title)
33-
{
34-
$size = strlen($title);
35-
$spaces = str_repeat(' ', $size);
36-
37-
$this->output->newLine();
38-
$this->output->writeln("<bg=blue;fg=white>{$spaces}{$spaces}{$spaces}</>");
39-
$this->output->writeln("<bg=blue;fg=white>{$spaces}{$title}{$spaces}</>");
40-
$this->output->writeln("<bg=blue;fg=white>{$spaces}{$spaces}{$spaces}</>");
41-
$this->output->newLine();
42-
43-
return $this;
44-
}
45-
46-
/**
47-
* Clear the current line in console output.
48-
*
49-
* @return \Roots\Acorn\Console\Commands\Command
50-
*/
51-
public function clearLine()
52-
{
53-
if (! $this->output->isDecorated()) {
54-
$this->output->writeln('');
55-
56-
return $this;
57-
}
58-
59-
$this->output->write("\x0D");
60-
$this->output->write("\x1B[2K");
61-
62-
return $this;
63-
}
64-
65-
/**
66-
* Execute a process and return the status.
67-
*
68-
* @param string|array $commands
69-
* @param boolean $output
70-
* @return mixed
71-
*/
72-
protected function exec($commands, $output = false)
73-
{
74-
if (! is_array($commands)) {
75-
$commands = explode(' ', $commands);
76-
}
77-
78-
$process = new Process($commands);
79-
$process->run();
80-
81-
if ($output) {
82-
return $process->getOutput();
83-
}
84-
85-
return true;
86-
}
87-
88-
/**
89-
* Run a task in the console.
90-
*
91-
* @param string $title
92-
* @param callable|null $task
93-
* @param string $status
94-
* @return mixed
95-
*/
96-
protected function task($title, $task = null, $status = '...')
97-
{
98-
$title = Str::start($title, '<fg=blue;options=bold>➡</> ');
99-
100-
if (! $task) {
101-
return $this->output->write("{$title}: <info>✔</info>");
102-
}
103-
104-
$this->output->write("{$title}: <comment>{$status}</comment>");
105-
106-
try {
107-
$status = $task() !== false;
108-
} catch (\Exception $e) {
109-
$this->clearLine()->line("{$title}: <fg=red;options=bold>x</>");
110-
111-
throw $e;
112-
}
113-
114-
$this->clearLine()->line("{$title}: " . ($status ? '<info>✔</info>' : '<fg=red;options=bold>x</>'));
115-
}
11628
}

src/Acorn/Console/Commands/GeneratorCommand.php

Lines changed: 25 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -3,130 +3,46 @@
33
namespace Roots\Acorn\Console\Commands;
44

55
use Illuminate\Support\Str;
6-
use Roots\Acorn\Filesystem\Filesystem;
7-
use Symfony\Component\Console\Input\InputArgument;
6+
use Illuminate\Console\GeneratorCommand as GeneratorCommandBase;
87

9-
abstract class GeneratorCommand extends Command
8+
abstract class GeneratorCommand extends GeneratorCommandBase
109
{
11-
/**
12-
* The filesystem instance.
13-
*
14-
* @var \Roots\Acorn\Filesystem\Filesystem
15-
*/
16-
protected $files;
10+
use \Roots\Acorn\Console\Concerns\ClearLine;
11+
use \Roots\Acorn\Console\Concerns\Exec;
12+
use \Roots\Acorn\Console\Concerns\Task;
13+
use \Roots\Acorn\Console\Concerns\Title;
1714

1815
/**
19-
* The type of class being generated.
16+
* The application implementation.
2017
*
21-
* @var string
18+
* @var \Roots\Acorn\Application
2219
*/
23-
protected $type;
20+
protected $app;
2421

2522
/**
26-
* Create a new Generator command instance.
27-
*
28-
* @param \Illuminate\Filesystem\Filesystem $files
29-
* @return void
23+
* {@inheritdoc}
3024
*/
31-
public function __construct(Filesystem $files)
25+
public function setLaravel($laravel)
3226
{
33-
parent::__construct();
34-
35-
$this->files = $files;
27+
parent::setLaravel($this->app = $laravel);
3628
}
3729

3830
/**
39-
* Get the stub file for the generator.
40-
*
41-
* @return string
31+
* {@inheritdoc}
4232
*/
43-
abstract protected function getStub();
44-
45-
/**
46-
* Execute the console command.
47-
*
48-
* @return bool|null
49-
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
50-
*/
51-
public function handle()
52-
{
53-
$name = $this->qualifyClass($this->getNameInput());
54-
55-
$path = $this->getPath($name);
56-
57-
// First we will check to see if the class already exists. If it does, we don't want
58-
// to create the class and overwrite the user's code. So, we will bail out so the
59-
// code is untouched. Otherwise, we will continue generating this class' files.
60-
if (
61-
(! $this->hasOption('force') ||
62-
! $this->option('force')) &&
63-
$this->alreadyExists($this->getNameInput())
64-
) {
65-
$this->error($this->type . ' already exists!');
66-
67-
return false;
68-
}
69-
70-
// Next, we will generate the path to the location where this class' file should get
71-
// written. Then, we will build the class and make the proper replacements on the
72-
// stub files so that it gets the correctly formatted namespace and class name.
73-
$this->makeDirectory($path);
74-
75-
$this->files->put($path, $this->buildClass($name));
76-
77-
$this->info($this->type . ' created successfully.');
78-
}
79-
80-
/**
81-
* Parse the class name and format according to the root namespace.
82-
*
83-
* @param string $name
84-
* @return string
85-
*/
86-
protected function qualifyClass($name)
33+
protected function replaceClass($stub, $name)
8734
{
88-
$name = ltrim($name, '\\/');
89-
90-
$rootNamespace = $this->rootNamespace();
91-
92-
if (Str::startsWith($name, $rootNamespace)) {
93-
return $name;
94-
}
95-
96-
$name = str_replace('/', '\\', $name);
35+
$class = str_replace($this->getNamespace($name) . '\\', '', $name);
9736

98-
return $this->qualifyClass(
99-
$this->getDefaultNamespace(trim($rootNamespace, '\\')) . '\\' . $name
37+
return str_replace(
38+
['DummySlug', 'DummyCamel', 'DummySnake'],
39+
[Str::slug($class), Str::camel($class), Str::snake($class)],
40+
parent::replaceClass($stub, $name)
10041
);
10142
}
10243

10344
/**
104-
* Get the default namespace for the class.
105-
*
106-
* @param string $rootNamespace
107-
* @return string
108-
*/
109-
protected function getDefaultNamespace($rootNamespace)
110-
{
111-
return $rootNamespace;
112-
}
113-
114-
/**
115-
* Determine if the class already exists.
116-
*
117-
* @param string $rawName
118-
* @return bool
119-
*/
120-
protected function alreadyExists($rawName)
121-
{
122-
return $this->files->exists($this->getPath($this->qualifyClass($rawName)));
123-
}
124-
125-
/**
126-
* Get the destination class path.
127-
*
128-
* @param string $name
129-
* @return string
45+
* {@inheritdoc}
13046
*/
13147
protected function getPath($name)
13248
{
@@ -136,126 +52,20 @@ protected function getPath($name)
13652
}
13753

13854
/**
139-
* Build the directory for the class if necessary.
140-
*
141-
* @param string $path
142-
* @return string
143-
*/
144-
protected function makeDirectory($path)
145-
{
146-
if (! $this->files->isDirectory(dirname($path))) {
147-
$this->files->makeDirectory(dirname($path), 0777, true, true);
148-
}
149-
150-
return $path;
151-
}
152-
153-
/**
154-
* Build the class with the given name.
155-
*
156-
* @param string $name
157-
* @return string
158-
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
159-
*/
160-
protected function buildClass($name)
161-
{
162-
$stub = $this->files->get($this->getStub());
163-
164-
return $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
165-
}
166-
167-
/**
168-
* Replace the namespace for the given stub.
169-
*
170-
* @param string $stub
171-
* @param string $name
172-
* @return $this
173-
*/
174-
protected function replaceNamespace(&$stub, $name)
175-
{
176-
$stub = str_replace(
177-
['DummyNamespace', 'DummyRootNamespace', 'NamespacedDummyUserModel'],
178-
[$this->getNamespace($name), $this->rootNamespace(), $this->userProviderModel()],
179-
$stub
180-
);
181-
182-
return $this;
183-
}
184-
185-
/**
186-
* Get the full namespace for a given class, without the class name.
187-
*
188-
* @param string $name
189-
* @return string
190-
*/
191-
protected function getNamespace($name)
192-
{
193-
return trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');
194-
}
195-
196-
/**
197-
* Replace the class name for the given stub.
198-
*
199-
* @param string $stub
200-
* @param string $name
201-
* @return string
202-
*/
203-
protected function replaceClass($stub, $name)
204-
{
205-
$class = str_replace($this->getNamespace($name) . '\\', '', $name);
206-
207-
return str_replace(
208-
['DummyClass', 'DummySlug', 'DummyCamel', 'DummySnake'],
209-
[$class, Str::slug($class), Str::camel($class), Str::snake($class)],
210-
$stub
211-
);
212-
}
213-
214-
/**
215-
* Get the desired class name from the input.
216-
*
217-
* @return string
55+
* {@inheritdoc}
21856
*/
21957
protected function getNameInput()
22058
{
221-
$name = $this->argument('name');
222-
223-
if (is_array($name)) {
224-
$name = array_pop($name);
225-
}
226-
227-
return trim($name);
228-
}
229-
230-
/**
231-
* Get the root namespace for the class.
232-
*
233-
* @return string
234-
*/
235-
protected function rootNamespace()
236-
{
237-
return $this->app->getNamespace();
59+
return trim(
60+
is_array($name = $this->argument('name')) ? array_pop($name) : $name
61+
);
23862
}
23963

24064
/**
241-
* Get the model for the default guard's user provider.
242-
*
243-
* @return void
65+
* {@inheritdoc}
24466
*/
24567
protected function userProviderModel()
24668
{
24769
//
24870
}
249-
250-
/**
251-
* Get the console command arguments.
252-
*
253-
* @return array
254-
*/
255-
protected function getArguments()
256-
{
257-
return [
258-
['name', InputArgument::REQUIRED, 'The name of the class'],
259-
];
260-
}
26171
}

0 commit comments

Comments
 (0)