Passed
Push — master ( 624a9a...4c85b9 )
by Arthur
36:47
created

AbstractGeneratorCommand   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 260
Duplicated Lines 0 %

Test Coverage

Coverage 85.26%

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 260
ccs 81
cts 95
cp 0.8526
rs 9.6
c 0
b 0
f 0
wmc 35

23 Methods

Rating   Name   Duplication   Size   Complexity  
A afterGeneration() 0 2 1
A beforeGeneration() 0 2 1
A getFilteredPath() 0 3 1
A getDestinationFilePath() 0 3 1
A handle() 0 23 4
A getModule() 0 3 1
A isOverwriteable() 0 3 1
A getOption() 0 3 1
A getOptions() 0 5 1
A handleOptions() 0 9 4
A getOriginalArgumentInput() 0 6 1
A __call() 0 5 2
A stubName() 0 3 1
A handleOverwriteOption() 0 6 2
A getModuleName() 0 8 2
A handleModuleArgument() 0 3 1
A getArguments() 0 6 1
A getCleanName() 0 4 1
A handleArguments() 0 9 4
A getGeneratorName() 0 3 1
A defaultStubOptions() 0 8 1
A getOriginalOptionInput() 0 6 1
A getArgument() 0 3 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: arthur
5
 * Date: 09.03.19
6
 * Time: 17:15.
7
 */
8
9
namespace Foundation\Generator\Abstracts;
10
11
use Foundation\Core\Larapi;
12
use Foundation\Core\Module;
13
use Foundation\Exceptions\Exception;
14
use Foundation\Generator\Support\Stub;
15
use Illuminate\Console\Command;
16
use Illuminate\Contracts\Filesystem\FileExistsException;
17
use Illuminate\Support\Str;
18
use ReflectionClass;
19
use Symfony\Component\Console\Input\InputArgument;
20
use Symfony\Component\Console\Input\InputOption;
21
22
abstract class AbstractGeneratorCommand extends Command
23
{
24
    /**
25
     * The name of the generated resource.
26
     *
27
     * @var string
28
     */
29
    protected $generatorName;
30
31
    /**
32
     * The stub name.
33
     *
34
     * @var string
35
     */
36
    protected $stub;
37
38
    /**
39
     * The file path.
40
     *
41
     * @var string
42
     */
43
    protected $filePath;
44
45
    /**
46
     * The event that will fire when the file is created.
47
     *
48
     * @var string
49
     */
50
    protected $event;
51
52
53
    /**
54
     * The data that is inputted from the options.
55
     *
56
     * @var array
57
     */
58
    protected $optionData = [];
59
60
    /**
61
     * The data that is inputted from the arguments.
62
     *
63
     * @var array
64
     */
65
    protected $argumentData = [];
66
67 26
    public function handle()
68
    {
69 26
        $this->handleArguments();
70 26
        $this->handleOptions();
71
72 26
        $path = $this->getFilteredPath();
73
74 26
        if (file_exists($path) && !$this->isOverwriteable()) {
75
            $this->error("File : {$path} already exists.");
76
            throw new FileExistsException();
77
        }
78
79 26
        $stub = new Stub($this->stubName(), array_merge($this->defaultStubOptions(), $this->stubOptions()));
80
81 26
        $this->beforeGeneration();
82
83 26
        if ($this->event === null)
84
            throw new Exception("No Generator event specified on " . static::class);
85
86 26
        event(new $this->event($path, $stub));
87 26
        $this->info("Created : {$path}");
88
89 26
        $this->afterGeneration();
90 26
    }
91
92 26
    private function getFilteredPath(): string
93
    {
94 26
        return str_replace('\\', '/', $this->getDestinationFilePath());
95
    }
96
97
    /**
98
     * @return string
99
     */
100 24
    protected function getDestinationFilePath(): string
101
    {
102 24
        return $this->getModule()->getPath() . $this->filePath . '/' . $this->getFileName();
103
    }
104
105
    /**
106
     * @return string
107
     */
108
    protected abstract function getFileName(): string;
109
110 5
    protected function isOverwriteable(): bool
111
    {
112 5
        return $this->getOption('overwrite');
113
    }
114
115 26
    protected function getModule(): Module
116
    {
117 26
        return Larapi::getModule($this->getModuleName());
118
    }
119
120 26
    protected function beforeGeneration(): void
121
    {
122 26
    }
123
124 22
    protected function afterGeneration(): void
125
    {
126 22
    }
127
128
    abstract protected function stubOptions(): array;
129
130 26
    protected final function defaultStubOptions(): array
131
    {
132
        return [
133 26
            "LOWER_MODULE" => strtolower($this->getModuleName()),
134 26
            "MODULE" => $this->getModuleName(),
135 26
            "PLURAL_MODULE" => Str::plural($this->getModuleName()),
136 26
            "PLURAL_LOWER_MODULE" => strtolower(Str::plural($this->getModuleName())),
137 26
            "CLEAN_NAME" => $this->getCleanName()
138
        ];
139
    }
140
141
    /**
142
     * Get the console command options.
143
     *
144
     * @return array
145
     */
146 113
    final protected function getOptions()
147
    {
148 113
        $options = $this->setOptions();
149 113
        $options[] = ['overwrite', null, InputOption::VALUE_NONE, 'Overwrite this file if it already exists?'];
150 113
        return $options;
151
    }
152
153
154 26
    protected function getCleanName(): string
155
    {
156 26
        $className = str_replace('.php', '', $this->getFileName());
157 26
        return str_ireplace(strtolower($this->getGeneratorName()), '', $className);
158
    }
159
160
    /**
161
     * Get the console command arguments.
162
     *
163
     * @return array
164
     */
165 113
    final protected function getArguments()
166
    {
167 113
        return array_merge([
168 113
            ['module', InputArgument::OPTIONAL, 'The name of module will be used.'],
169
        ],
170 113
            $this->setArguments());
171
    }
172
173
    /**
174
     * Set the console command arguments.
175
     *
176
     * @return array
177
     */
178
    protected abstract function setArguments(): array;
179
180
    /**
181
     * Set the console command options.
182
     *
183
     * @return array
184
     */
185
    protected abstract function setOptions(): array;
186
187
188 113
    protected function getGeneratorName(): string
189
    {
190 113
        return $this->generatorName ?? 'class';
191
    }
192
193
    /**
194
     * Get the stub file name.
195
     * @return string
196
     */
197 19
    protected function stubName()
198
    {
199 19
        return $this->stub;
200
    }
201
202 26
    protected function handleOptions()
203
    {
204 26
        foreach ($this->getOptions() as $option) {
205 26
            $method = 'handle' . ucfirst(strtolower($option[0])) . 'Option';
206 26
            $originalInput = $this->getOriginalOptionInput();
207 26
            if (isset($originalInput[$option[0]])) {
208 26
                $this->optionData[$option[0]] = $originalInput[$option[0]];
209
            } else {
210 1
                $this->optionData[$option[0]] = method_exists($this, $method) ? $this->$method($option[1], $option[2], $option[3], $option[4] ?? null) : $this->option($option[0]);
211
            }
212
        }
213 26
    }
214
215
    protected function handleModuleArgument()
216
    {
217
        return $this->anticipate('For what module would you like to generate a ' . $this->getGeneratorName() . '.', Larapi::getModuleNames());
218
    }
219
220 26
    protected function getModuleName()
221
    {
222 26
        $moduleName = $this->getArgument('module');
223 26
        if ($moduleName === null) {
224
            $this->error('module not specified');
225
            throw new \Exception('Name of module not specified.');
226
        }
227 26
        return $moduleName;
228
    }
229
230 26
    protected function handleArguments()
231
    {
232 26
        foreach ($this->getArguments() as $argument) {
233 26
            $method = 'handle' . ucfirst(strtolower($argument[0])) . 'Argument';
234 26
            $originalInput = $this->getOriginalArgumentInput();
235 26
            if (isset($originalInput[$argument[0]])) {
236 26
                $this->argumentData[$argument[0]] = $originalInput[$argument[0]];
237
            } else {
238
                $this->argumentData[$argument[0]] = method_exists($this, $method) ? $this->$method($argument[1], $argument[2], $argument[3] ?? null) : $this->option($argument[0]);
239
            }
240
        }
241 26
    }
242
243 26
    protected function getArgument(string $argument)
244
    {
245 26
        return $this->argumentData[$argument];
246
    }
247
248 11
    protected function getOption(string $name)
249
    {
250 11
        return $this->optionData[$name];
251
    }
252
253 26
    private function getOriginalOptionInput()
254
    {
255 26
        $reflection = new ReflectionClass($this->input);
256 26
        $property = $reflection->getProperty('options');
257 26
        $property->setAccessible(true);
258 26
        return $property->getValue($this->input);
259
    }
260
261 26
    private function getOriginalArgumentInput()
262
    {
263 26
        $reflection = new ReflectionClass($this->input);
264 26
        $property = $reflection->getProperty('arguments');
265 26
        $property->setAccessible(true);
266 26
        return $property->getValue($this->input);
267
    }
268
269
    public function __call($method, $parameters)
270
    {
271
        $key = str_replace('get', '', $method);
272
        if (array_key_exists(strtolower($method), $this->optionData))
273
            return $this->optionData[$key];
274
    }
275
276 1
    protected function handleOverwriteOption($shortcut, $type, $question, $default)
277
    {
278 1
        if (file_exists($this->getFilteredPath())) {
279
            return $this->confirm('The file exists already. Would you like to overwrite it?', false);
280
        }
281 1
        return false;
282
    }
283
}
284