Passed
Push — master ( 40ce26...965fb6 )
by Arthur
22:04
created

AbstractGeneratorCommand::beforeGeneration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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