Completed
Pull Request — master (#666)
by reallyli
02:28
created

ModuleGenerator::setForce()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Nwidart\Modules\Generators;
4
5
use Illuminate\Config\Repository as Config;
6
use Illuminate\Console\Command as Console;
7
use Illuminate\Filesystem\Filesystem;
8
use Illuminate\Support\Str;
9
use Nwidart\Modules\FileRepository;
10
use Nwidart\Modules\Support\Config\GenerateConfigReader;
11
use Nwidart\Modules\Support\Stub;
12
13
class ModuleGenerator extends Generator
14
{
15
    /**
16
     * The module name will created.
17
     *
18
     * @var string
19
     */
20
    protected $name;
21
22
    /**
23
     * The laravel config instance.
24
     *
25
     * @var Config
26
     */
27
    protected $config;
28
29
    /**
30
     * The laravel filesystem instance.
31
     *
32
     * @var Filesystem
33
     */
34
    protected $filesystem;
35
36
    /**
37
     * The laravel console instance.
38
     *
39
     * @var Console
40
     */
41
    protected $console;
42
43
    /**
44
     * The pingpong module instance.
45
     *
46
     * @var \Nwidart\Modules\Module
47
     */
48
    protected $module;
49
50
    /**
51
     * Force status.
52
     *
53
     * @var bool
54
     */
55
    protected $force = false;
56
57
    /**
58
     * Generate a plain module.
59
     *
60
     * @var bool
61
     */
62
    protected $plain = false;
63
64
    /**
65
     * Generate a api module.
66
     *
67
     * @var bool
68
     */
69
    protected $api = false;
70
71
    /**
72
     * The constructor.
73
     * @param $name
74
     * @param FileRepository $module
75
     * @param Config     $config
76
     * @param Filesystem $filesystem
77
     * @param Console    $console
78
     */
79
    public function __construct(
80
        $name,
81
        FileRepository $module = null,
82
        Config $config = null,
83
        Filesystem $filesystem = null,
84
        Console $console = null
85
    ) {
86
        $this->name = $name;
87
        $this->config = $config;
88
        $this->filesystem = $filesystem;
89
        $this->console = $console;
90
        $this->module = $module;
91
    }
92
93
    /**
94
     * Set plain flag.
95
     *
96
     * @param bool $plain
97
     *
98
     * @return $this
99
     */
100
    public function setPlain($plain)
101
    {
102
        $this->plain = $plain;
103
104
        return $this;
105
    }
106
107
    /**
108
     * Get the name of module will created. By default in studly case.
109
     *
110
     * @return string
111
     */
112
    public function getName()
113
    {
114
        return Str::studly($this->name);
115
    }
116
117
    /**
118
     * Get the laravel config instance.
119
     *
120
     * @return Config
121
     */
122
    public function getConfig()
123
    {
124
        return $this->config;
125
    }
126
127
    /**
128
     * Set the laravel config instance.
129
     *
130
     * @param Config $config
131
     *
132
     * @return $this
133
     */
134
    public function setConfig($config)
135
    {
136
        $this->config = $config;
137
138
        return $this;
139
    }
140
141
    /**
142
     * Get the laravel filesystem instance.
143
     *
144
     * @return Filesystem
145
     */
146
    public function getFilesystem()
147
    {
148
        return $this->filesystem;
149
    }
150
151
    /**
152
     * Set the laravel filesystem instance.
153
     *
154
     * @param Filesystem $filesystem
155
     *
156
     * @return $this
157
     */
158
    public function setFilesystem($filesystem)
159
    {
160
        $this->filesystem = $filesystem;
161
162
        return $this;
163
    }
164
165
    /**
166
     * Get the laravel console instance.
167
     *
168
     * @return Console
169
     */
170
    public function getConsole()
171
    {
172
        return $this->console;
173
    }
174
175
    /**
176
     * Set the laravel console instance.
177
     *
178
     * @param Console $console
179
     *
180
     * @return $this
181
     */
182
    public function setConsole($console)
183
    {
184
        $this->console = $console;
185
186
        return $this;
187
    }
188
189
    /**
190
     * Get the module instance.
191
     *
192
     * @return \Nwidart\Modules\Module
193
     */
194
    public function getModule()
195
    {
196
        return $this->module;
197
    }
198
199
    /**
200
     * Set the pingpong module instance.
201
     *
202
     * @param mixed $module
203
     *
204
     * @return $this
205
     */
206
    public function setModule($module)
207
    {
208
        $this->module = $module;
209
210
        return $this;
211
    }
212
213
    /**
214
     * Get the list of folders will created.
215
     *
216
     * @return array
217
     */
218
    public function getFolders()
219
    {
220
        return $this->module->config('paths.generator');
221
    }
222
223
    /**
224
     * Get the list of files will created.
225
     *
226
     * @return array
227
     */
228
    public function getFiles()
229
    {
230
        return $this->module->config('stubs.files');
231
    }
232
233
    /**
234
     * Set force status.
235
     *
236
     * @param bool|int $force
237
     *
238
     * @return $this
239
     */
240
    public function setForce($force)
241
    {
242
        $this->force = $force;
0 ignored issues
show
Documentation Bug introduced by
It seems like $force can also be of type integer. However, the property $force is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
243
244
        return $this;
245
    }
246
247
    /**
248
     * Set Api Flog.
249
     *
250
     * @param bool $api
251
     *
252
     * @return $this
253
     */
254
    public function setApi($api)
255
    {
256
        $this->api = $api;
257
258
        return $this;
259
    }
260
261
    /**
262
     * Generate the module.
263
     */
264
    public function generate()
265
    {
266
        $name = $this->getName();
267
268
        if ($this->module->has($name)) {
269
            if ($this->force) {
270
                $this->module->delete($name);
271
            } else {
272
                $this->console->error("Module [{$name}] already exist!");
273
274
                return;
275
            }
276
        }
277
278
        $this->generateFolders();
279
280
        $this->generateModuleJsonFile();
281
282
        if ($this->plain !== true) {
283
            $this->generateFiles();
284
            $this->generateResources();
285
        }
286
287
        if ($this->plain === true) {
288
            $this->cleanModuleJsonFile();
289
        }
290
291
        $this->console->info("Module [{$name}] created successfully.");
292
    }
293
294
    /**
295
     * Generate the folders.
296
     */
297
    public function generateFolders()
298
    {
299
        foreach ($this->getFolders() as $key => $folder) {
300
            $folder = GenerateConfigReader::read($key);
301
302
            if ($folder->generate() === false) {
303
                continue;
304
            }
305
306
            $path = $this->module->getModulePath($this->getName()) . '/' . $folder->getPath();
307
308
            $this->filesystem->makeDirectory($path, 0755, true);
309
            if (config('modules.stubs.gitkeep')) {
310
                $this->generateGitKeep($path);
311
            }
312
        }
313
    }
314
315
    /**
316
     * Generate git keep to the specified path.
317
     *
318
     * @param string $path
319
     */
320
    public function generateGitKeep($path)
321
    {
322
        $this->filesystem->put($path . '/.gitkeep', '');
323
    }
324
325
    /**
326
     * Generate the files.
327
     */
328
    public function generateFiles()
329
    {
330
        foreach ($this->getFiles() as $stub => $file) {
331
            if ($this->api === true) {
332
                if (in_array($stub, ['routes/web', 'views/index', 'views/master', 'assets/js/app', 'assets/sass/app', 'webpack'])) {
333
                    continue;
334
                }
335
            }
336
337
            $path = $this->module->getModulePath($this->getName()) . $file;
338
339 View Code Duplication
            if (!$this->filesystem->isDirectory($dir = dirname($path))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
340
                $this->filesystem->makeDirectory($dir, 0775, true);
341
            }
342
343
            $this->filesystem->put($path, $this->getStubContents($stub));
344
345
            $this->console->info("Created : {$path}");
346
        }
347
    }
348
349
    /**
350
     * Generate some resources.
351
     */
352
    public function generateResources()
353
    {
354
        $this->console->call('module:make-seed', $this->getMakeSeedArguments());
355
356
        $this->console->call('module:make-provider', $this->getMakeProviderArguments());
357
358
        $this->console->call('module:route-provider', $this->getMakeRouteProviderArguments());
359
360
        $this->console->call('module:make-controller', $this->getMakeControllerArguments());
361
    }
362
363
    /**
364
     * get Make Route Provider Arguments
365
     *
366
     * @since 2018/11/16
367
     * @return array
368
     */
369
    protected function getMakeRouteProviderArguments()
370
    {
371
        $arguments = [
372
            'module' => $this->getName(),
373
        ];
374
        if ($this->api === true) {
375
            $arguments['--api'] = true;
376
        }
377
378
        return $arguments;
379
    }
380
381
    /**
382
     * get Make Provider Arguments
383
     *
384
     * @since 2018/11/16
385
     * @return array
386
     */
387
    protected function getMakeProviderArguments()
388
    {
389
        $arguments = [
390
            'name' => $this->getName() . 'ServiceProvider',
391
            'module' => $this->getName(),
392
            '--master' => true,
393
        ];
394
        if ($this->api === true) {
395
            $arguments['--api'] = true;
396
        }
397
398
        return $arguments;
399
    }
400
401
    /**
402
     * get Make Controller Arguments
403
     *
404
     * @since 2018/11/16
405
     * @return array
406
     */
407
    protected function getMakeControllerArguments()
408
    {
409
        $arguments = [
410
            'controller' => $this->getName() . 'Controller',
411
            'module' => $this->getName(),
412
        ];
413
        if ($this->api === true) {
414
            $arguments['--plain'] = true;
415
        }
416
417
        return $arguments;
418
    }
419
420
    /**
421
     * get Make Seed Arguments
422
     *
423
     * @since 2018/11/16
424
     * @return array
425
     */
426
    protected function getMakeSeedArguments()
427
    {
428
        return  [
429
           'name' => $this->getName(),
430
           'module' => $this->getName(),
431
           '--master' => true,
432
       ];
433
    }
434
435
    /**
436
     * Get the contents of the specified stub file by given stub name.
437
     *
438
     * @param $stub
439
     *
440
     * @return string
441
     */
442
    protected function getStubContents($stub)
443
    {
444
        return (new Stub(
445
            '/' . $stub . '.stub',
446
            $this->getReplacement($stub)
447
        )
448
        )->render();
449
    }
450
451
    /**
452
     * get the list for the replacements.
453
     */
454
    public function getReplacements()
455
    {
456
        return $this->module->config('stubs.replacements');
457
    }
458
459
    /**
460
     * Get array replacement for the specified stub.
461
     *
462
     * @param $stub
463
     *
464
     * @return array
465
     */
466
    protected function getReplacement($stub)
467
    {
468
        $replacements = $this->module->config('stubs.replacements');
469
470
        if (!isset($replacements[$stub])) {
471
            return [];
472
        }
473
474
        $keys = $replacements[$stub];
475
476
        $replaces = [];
477
478
        foreach ($keys as $key) {
479
            if (method_exists($this, $method = 'get' . ucfirst(studly_case(strtolower($key))) . 'Replacement')) {
480
                $replaces[$key] = $this->$method();
481
            } else {
482
                $replaces[$key] = null;
483
            }
484
        }
485
486
        return $replaces;
487
    }
488
489
    /**
490
     * Generate the module.json file
491
     */
492
    private function generateModuleJsonFile()
493
    {
494
        $path = $this->module->getModulePath($this->getName()) . 'module.json';
495
496 View Code Duplication
        if (!$this->filesystem->isDirectory($dir = dirname($path))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
497
            $this->filesystem->makeDirectory($dir, 0775, true);
498
        }
499
500
        $this->filesystem->put($path, $this->getStubContents('json'));
501
502
        $this->console->info("Created : {$path}");
503
    }
504
505
    /**
506
     * Remove the default service provider that was added in the module.json file
507
     * This is needed when a --plain module was created
508
     */
509
    private function cleanModuleJsonFile()
510
    {
511
        $path = $this->module->getModulePath($this->getName()) . 'module.json';
512
513
        $content = $this->filesystem->get($path);
514
        $namespace = $this->getModuleNamespaceReplacement();
515
        $studlyName = $this->getStudlyNameReplacement();
516
517
        $provider = '"' . $namespace . '\\\\' . $studlyName . '\\\\Providers\\\\' . $studlyName . 'ServiceProvider"';
518
519
        $content = str_replace($provider, '', $content);
520
521
        $this->filesystem->put($path, $content);
522
    }
523
524
    /**
525
     * Get the module name in lower case.
526
     *
527
     * @return string
528
     */
529
    protected function getLowerNameReplacement()
530
    {
531
        return strtolower($this->getName());
532
    }
533
534
    /**
535
     * Get the module name in studly case.
536
     *
537
     * @return string
538
     */
539
    protected function getStudlyNameReplacement()
540
    {
541
        return $this->getName();
542
    }
543
544
    /**
545
     * Get replacement for $VENDOR$.
546
     *
547
     * @return string
548
     */
549
    protected function getVendorReplacement()
550
    {
551
        return $this->module->config('composer.vendor');
552
    }
553
554
    /**
555
     * Get replacement for $MODULE_NAMESPACE$.
556
     *
557
     * @return string
558
     */
559
    protected function getModuleNamespaceReplacement()
560
    {
561
        return str_replace('\\', '\\\\', $this->module->config('namespace'));
562
    }
563
564
    /**
565
     * Get replacement for $AUTHOR_NAME$.
566
     *
567
     * @return string
568
     */
569
    protected function getAuthorNameReplacement()
570
    {
571
        return $this->module->config('composer.author.name');
572
    }
573
574
    /**
575
     * Get replacement for $AUTHOR_EMAIL$.
576
     *
577
     * @return string
578
     */
579
    protected function getAuthorEmailReplacement()
580
    {
581
        return $this->module->config('composer.author.email');
582
    }
583
}
584