Passed
Push — master ( 427199...ab0a32 )
by F
01:13 queued 10s
created

ArtomatorAllCommand::handle()   C

Complexity

Conditions 12
Paths 258

Size

Total Lines 36
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 21
c 1
b 0
f 0
nc 258
nop 0
dl 0
loc 36
rs 5.4083

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PWWEB\Artomator\Commands;
4
5
use Illuminate\Support\Str;
6
use InvalidArgumentException;
7
use Illuminate\Console\GeneratorCommand;
8
use Symfony\Component\Console\Input\InputOption;
9
10
class ArtomatorAllCommand extends GeneratorCommand
11
{
12
    /**
13
     * The console command name.
14
     *
15
     * @var string
16
     */
17
    protected $name = 'artomator:all';
18
19
    /**
20
     * The console command description.
21
     *
22
     * @var string
23
     */
24
    protected $description = 'Create a new Eloquent model, factory, migration, controller and resource class';
25
26
    /**
27
     * The type of class being generated.
28
     *
29
     * @var string
30
     */
31
    protected $type = 'Model';
32
33
    /**
34
     * The array of standard included generators.
35
     *
36
     * @var string[]
37
     */
38
    protected $includes = [
39
        'model',
40
        'controller',
41
        'request',
42
        'query',
43
        'type',
44
        'migration',
45
        'seeder',
46
        'factory',
47
    ];
48
49
    /**
50
     * The schema variable.
51
     *
52
     * @var string
53
     */
54
    protected $schema;
55
56
    /**
57
     * Get the stub file for the generator.
58
     *
59
     * @return string
60
     */
61
    protected function getStub()
62
    {
63
        $stub = 'model.stub';
64
        $path = base_path() . config('artomator.stubPath');
65
        $path = $path . $stub;
66
67
        if (file_exists($path) === true) {
68
            return $path;
69
        } else {
70
            return __DIR__ . '/Stubs/' . $stub;
71
        }
72
    }
73
74
    /**
75
     * Get the default namespace for the class.
76
     *
77
     * @param string $rootNamespace The class name to return FQN for.
78
     *
79
     * @return string
80
     */
81
    protected function getDefaultNamespace($rootNamespace)
82
    {
83
        return $rootNamespace . '\Models';
84
    }
85
86
    /**
87
     * Execute the console command.
88
     *
89
     * @return boolean
90
     */
91
    public function handle()
92
    {
93
        $this->parseIncludes();
94
95
        $this->schema = $this->option('schema');
96
97
        if ($this->option('table') !== false) {
98
            $this->schema = $this->insepctTable((string) $this->option('table'));
99
        }
100
101
        if (in_array('model', $this->includes) === true && parent::handle() === false && $this->option('force') === false) {
102
            return false;
103
        }
104
105
        if (in_array('factory', $this->includes) === true) {
106
            $this->createFactory();
107
        }
108
        if (in_array('seeder', $this->includes) === true) {
109
            $this->createSeeder();
110
        }
111
        if (in_array('migration', $this->includes) === true) {
112
            $this->createMigration();
113
        }
114
        if (in_array('controller', $this->includes) === true) {
115
            $this->createController();
116
        }
117
        if (in_array('request', $this->includes) === true) {
118
            $this->createRequest();
119
        }
120
        if (in_array('query', $this->includes) === true) {
121
            $this->createQuery();
122
        }
123
        if (in_array('type', $this->includes) === true) {
124
            $this->createType();
125
        }
126
        return true;
127
    }
128
129
    /**
130
     * Inspect table with the database for schema.
131
     *
132
     * @param string $table The name of the table to insepct.
133
     *
134
     * @return string
135
     */
136
    protected function insepctTable($table)
137
    {
138
        if (\Schema::hasTable($table) !== true) {
139
            return '';
140
        }
141
        $results = [];
142
        $columns = \DB::connection()->select(\DB::raw('describe ' . $table));
143
        foreach ($columns as $column) {
144
            if ($column->Key === 'PRI') {
145
                // $primary = [
146
                //     'type' => $column->Type,
147
                //     'name' => $column->Field,
148
                // ];
149
                continue;
150
            }
151
            $results[] = [
152
                'type' => $column->Type,
153
                'name' => $column->Field,
154
                'key' => $column->Key === 'UNI' ? 'unique' : '',
155
            ];
156
        }
157
158
        $results = array_map(
159
            function ($field) {
160
                return $this->addArg($field);
161
            },
162
            $results
163
        );
164
165
        $results = implode(",", $results);
166
167
        return $results;
168
    }
169
170
    /**
171
     * Format the schema for passing to subsequent generators.
172
     *
173
     * @param array $field The field definition.
174
     *
175
     * @return string
176
     */
177
    private function addArg($field)
178
    {
179
        if ($field['key'] !== '') {
180
            $format = "%s:%s:%s";
181
        } else {
182
            $format = "%s:%s";
183
        }
184
        $syntax = sprintf($format, $field['name'], $this->normaliseType($field['type']), $field['key']);
185
        return $syntax;
186
    }
187
188
    /**
189
     * Normalise the type from the inspection to remove the additional information.
190
     *
191
     * @param string $type The field type definition.
192
     *
193
     * @return string
194
     */
195
    private function normaliseType($type)
196
    {
197
        return preg_replace("/(\\(.*\\))/is", '', $type);
198
    }
199
200
    /**
201
     * Parse the includes and excludes arguments.
202
     *
203
     * @return string[]
204
     */
205
    protected function parseIncludes()
206
    {
207
        if ($this->option('exclude') !== false) {
208
            $exclusions = explode(',', $this->option('exclude'));
0 ignored issues
show
Bug introduced by
It seems like $this->option('exclude') can also be of type string[]; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

208
            $exclusions = explode(',', /** @scrutinizer ignore-type */ $this->option('exclude'));
Loading history...
209
210
            foreach ($exclusions as $exclusion) {
211
                unset($this->includes[array_search(trim($exclusion), $this->includes)]);
212
            }
213
        }
214
        if ($this->option('include') !== false) {
215
            $inclusions = explode(',', $this->option('include'));
216
217
            foreach ($inclusions as &$inclusion) {
218
                $inclusion = trim($inclusion);
219
            }
220
            $this->includes = $inclusions;
221
        }
222
    }
223
224
    /**
225
     * Build the class with the given name.
226
     *
227
     * Remove the base controller import if we are already in base namespace.
228
     *
229
     * @param string $name The name of the model to build.
230
     *
231
     * @return string
232
     */
233
    protected function buildClass($name)
234
    {
235
        $table = Str::snake(Str::pluralStudly(str_replace('/', '', $this->argument('name'))));
236
237
        $replace = [];
238
239
        $replace = array_merge(
240
            $replace,
241
            [
242
            'DummyFullModelClass' => $this->qualifyClass($name),
243
            'DummyPackagePlaceholder' => config('app.name'),
244
            'DummySnakeCaseClass' => $table,
245
            'DummyCopyrightPlaceholder' => config('artomator.copyright'),
246
            'DummyLicensePlaceholder' => config('artomator.license'),
247
            'DummyAuthorPlaceholder' => $this->parseAuthors(config('artomator.authors')),
248
            ]
249
        );
250
251
        return str_replace(
252
            array_keys($replace),
253
            array_values($replace),
254
            parent::buildClass($name)
255
        );
256
    }
257
258
    /**
259
     * Get the formatted author(s) from the config file.
260
     *
261
     * @param string[] $authors Authors array.
262
     *
263
     * @return string Formmated string of authors.
264
     */
265
    protected function parseAuthors($authors)
266
    {
267
        if (is_array($authors) === false and is_string($authors) === false) {
0 ignored issues
show
introduced by
The condition is_array($authors) === false is always false.
Loading history...
268
            throw new InvalidArgumentException('Authors must be an array of strings or a string.');
269
        }
270
271
        $formatted = '';
272
273
        if (is_array($authors) === true) {
274
            if (is_string($authors[0]) === false) {
275
                throw new InvalidArgumentException('The array of authors must be strings.');
276
            }
277
            $formatted .= array_shift($authors);
278
279
            foreach ($authors as $author) {
280
                if (is_string($author) === false) {
281
                    throw new InvalidArgumentException('The array of authors must be strings.');
282
                }
283
                $formatted .= "\n * @author    " . $author;
284
            }
285
        } else {
286
            $formatted .= $authors;
287
        }
288
289
        return $formatted;
290
    }
291
292
    /**
293
     * Create a model factory for the model.
294
     *
295
     * @return void
296
     */
297
    protected function createFactory()
298
    {
299
        $this->info('Creating Factory');
300
        $factory = $this->argument('name');
301
302
        $this->call(
303
            'make:factory',
304
            [
305
            'name' => "{$factory}Factory",
306
            '--model' => $this->qualifyClass($this->getNameInput()),
307
            ]
308
        );
309
    }
310
311
    /**
312
     * Create a model seeder for the model.
313
     *
314
     * @return void
315
     */
316
    protected function createSeeder()
317
    {
318
        $this->info('Creating Seeder');
319
        $seeder = str_replace('/', '', $this->argument('name'));
320
321
        $this->call(
322
            'make:seeder',
323
            [
324
            'name' => "{$seeder}TableSeeder",
325
            ]
326
        );
327
    }
328
329
    /**
330
     * Create a migration file for the model.
331
     *
332
     * @return void
333
     */
334
    protected function createMigration()
335
    {
336
        $this->info('Creating Migration');
337
        $table = Str::snake(Str::pluralStudly(str_replace('/', '', $this->argument('name'))));
338
339
        if ($this->option('pivot') !== false) {
340
            $table = Str::singular($table);
341
        }
342
343
        if ($this->schema !== '') {
344
            $this->call(
345
                'make:migration:schema',
346
                [
347
                'name' => "create_{$table}_table",
348
                '--schema' => $this->schema,
349
                ]
350
            );
351
        } else {
352
            $this->call(
353
                'make:migration',
354
                [
355
                'name' => "create_{$table}_table",
356
                '--create' => $table,
357
                ]
358
            );
359
        }
360
    }
361
362
    /**
363
     * Create a controller for the model.
364
     *
365
     * @return void
366
     */
367
    protected function createController()
368
    {
369
        $this->info('Creating Controller');
370
        $controller = $this->argument('name');
371
372
        $modelName = $this->getNameInput();
373
374
        $this->call(
375
            'artomator:controller',
376
            [
377
            'name' => "{$controller}Controller",
378
            '--model' => $modelName,
379
            '--schema' => $this->schema,
380
            ]
381
        );
382
    }
383
384
    /**
385
     * Create a request for the model.
386
     *
387
     * @return void
388
     */
389
    protected function createRequest()
390
    {
391
        $this->info('Creating Request');
392
393
        $this->call(
394
            'artomator:request',
395
            [
396
            'name' => $this->getNameInput(),
397
            '--model' => $this->qualifyClass($this->getNameInput()),
398
            ]
399
        );
400
    }
401
402
    /**
403
     * Create a query for the model.
404
     *
405
     * @return void
406
     */
407
    protected function createQuery()
408
    {
409
        $this->info('Creating Query');
410
        $query = Str::pluralStudly((string) $this->argument('name'));
411
412
        $modelName = $this->getNameInput();
413
414
        $this->call(
415
            'artomator:query',
416
            [
417
            'name' => "{$query}Query",
418
            '--model' => $modelName,
419
            '--schema' => $this->schema,
420
            ]
421
        );
422
    }
423
424
    /**
425
     * Create a type for the model.
426
     *
427
     * @return void
428
     */
429
    protected function createType()
430
    {
431
        $this->info('Creating Type');
432
        $type = $this->argument('name');
433
434
        $modelName = $this->getNameInput();
435
436
        $this->call(
437
            'artomator:type',
438
            [
439
            'name' => "{$type}Type",
440
            '--model' => $modelName,
441
            '--schema' => $this->schema,
442
            ]
443
        );
444
    }
445
446
    /**
447
     * Get the console command options.
448
     *
449
     * @return array
450
     */
451
    protected function getOptions()
452
    {
453
        return [
454
            ['force', null, InputOption::VALUE_NONE, 'Create the class even if the model already exists'],
455
            ['schema', 's', InputOption::VALUE_OPTIONAL, 'Optional schema to be attached to the migration', null],
456
            ['pivot', 'p', InputOption::VALUE_NONE, 'Indicates if the generated model should be a custom intermediate table model'],
457
            ['include', 'i', InputOption::VALUE_OPTIONAL, 'Specify which "Generators" to run'],
458
            ['exclude', 'e', InputOption::VALUE_OPTIONAL, 'Specify which "Genertors" to exclude'],
459
            ['table', 't', InputOption::VALUE_OPTIONAL, 'Specify which table to inspect'],
460
        ];
461
    }
462
}
463