Completed
Push — master ( 1fab66...7a7060 )
by Nicolas
02:25
created

ModuleGenerator::getRoutesLocationReplacement()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
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\Repository;
10
use Nwidart\Modules\Support\Stub;
11
12
class ModuleGenerator extends Generator
13
{
14
    /**
15
     * The module name will created.
16
     *
17
     * @var string
18
     */
19
    protected $name;
20
21
    /**
22
     * The laravel config instance.
23
     *
24
     * @var Config
25
     */
26
    protected $config;
27
28
    /**
29
     * The laravel filesystem instance.
30
     *
31
     * @var Filesystem
32
     */
33
    protected $filesystem;
34
35
    /**
36
     * The laravel console instance.
37
     *
38
     * @var Console
39
     */
40
    protected $console;
41
42
    /**
43
     * The pingpong module instance.
44
     *
45
     * @var Module
46
     */
47
    protected $module;
48
49
    /**
50
     * Force status.
51
     *
52
     * @var bool
53
     */
54
    protected $force = false;
55
56
    /**
57
     * Generate a plain module.
58
     *
59
     * @var bool
60
     */
61
    protected $plain = false;
62
63
    /**
64
     * The constructor.
65
     *
66
     * @param $name
67
     * @param Repository $module
68
     * @param Config     $config
69
     * @param Filesystem $filesystem
70
     * @param Console    $console
71
     */
72 72
    public function __construct(
73
        $name,
74
        Repository $module = null,
75
        Config $config = null,
76
        Filesystem $filesystem = null,
77
        Console $console = null
78
    ) {
79 72
        $this->name = $name;
80 72
        $this->config = $config;
81 72
        $this->filesystem = $filesystem;
82 72
        $this->console = $console;
83 72
        $this->module = $module;
0 ignored issues
show
Documentation Bug introduced by
It seems like $module can also be of type object<Nwidart\Modules\Repository>. However, the property $module is declared as type object<Nwidart\Modules\Generators\Module>. 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...
84 72
    }
85
86
    /**
87
     * Set plain flag.
88
     *
89
     * @param bool $plain
90
     *
91
     * @return $this
92
     */
93 72
    public function setPlain($plain)
94
    {
95 72
        $this->plain = $plain;
96
97 72
        return $this;
98
    }
99
100
    /**
101
     * Get the name of module will created. By default in studly case.
102
     *
103
     * @return string
104
     */
105 72
    public function getName()
106
    {
107 72
        return Str::studly($this->name);
108
    }
109
110
    /**
111
     * Get the laravel config instance.
112
     *
113
     * @return Config
114
     */
115
    public function getConfig()
116
    {
117
        return $this->config;
118
    }
119
120
    /**
121
     * Set the laravel config instance.
122
     *
123
     * @param Config $config
124
     *
125
     * @return $this
126
     */
127 72
    public function setConfig($config)
128
    {
129 72
        $this->config = $config;
130
131 72
        return $this;
132
    }
133
134
    /**
135
     * Get the laravel filesystem instance.
136
     *
137
     * @return Filesystem
138
     */
139
    public function getFilesystem()
140
    {
141
        return $this->filesystem;
142
    }
143
144
    /**
145
     * Set the laravel filesystem instance.
146
     *
147
     * @param Filesystem $filesystem
148
     *
149
     * @return $this
150
     */
151 72
    public function setFilesystem($filesystem)
152
    {
153 72
        $this->filesystem = $filesystem;
154
155 72
        return $this;
156
    }
157
158
    /**
159
     * Get the laravel console instance.
160
     *
161
     * @return Console
162
     */
163
    public function getConsole()
164
    {
165
        return $this->console;
166
    }
167
168
    /**
169
     * Set the laravel console instance.
170
     *
171
     * @param Console $console
172
     *
173
     * @return $this
174
     */
175 72
    public function setConsole($console)
176
    {
177 72
        $this->console = $console;
178
179 72
        return $this;
180
    }
181
182
    /**
183
     * Get the pingpong module instance.
184
     *
185
     * @return Module
186
     */
187
    public function getModule()
188
    {
189
        return $this->module;
190
    }
191
192
    /**
193
     * Set the pingpong module instance.
194
     *
195
     * @param mixed $module
196
     *
197
     * @return $this
198
     */
199 72
    public function setModule($module)
200
    {
201 72
        $this->module = $module;
202
203 72
        return $this;
204
    }
205
206
    /**
207
     * Get the list of folders will created.
208
     *
209
     * @return array
210
     */
211 72
    public function getFolders()
212
    {
213 72
        return array_values($this->module->config('paths.generator'));
214
    }
215
216
    /**
217
     * Get the list of files will created.
218
     *
219
     * @return array
220
     */
221 65
    public function getFiles()
222
    {
223 65
        return $this->module->config('stubs.files');
224
    }
225
226
    /**
227
     * Set force status.
228
     *
229
     * @param bool|int $force
230
     *
231
     * @return $this
232
     */
233 72
    public function setForce($force)
234
    {
235 72
        $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...
236
237 72
        return $this;
238
    }
239
240
    /**
241
     * Generate the module.
242
     */
243 72
    public function generate()
244
    {
245 72
        $name = $this->getName();
246
247 72
        if ($this->module->has($name)) {
248 2
            if ($this->force) {
249 1
                $this->module->delete($name);
250
            } else {
251 1
                $this->console->error("Module [{$name}] already exist!");
252
253 1
                return;
254
            }
255
        }
256
257 72
        $this->generateFolders();
258
259 72
        $this->generateModuleJsonFile();
260
261 72
        if ($this->plain !== true) {
262 65
            $this->generateFiles();
263 65
            $this->generateResources();
264
        }
265
266 72
        if ($this->plain === true) {
267 7
            $this->cleanModuleJsonFile();
268
        }
269
270 72
        $this->console->info("Module [{$name}] created successfully.");
271 72
    }
272
273
    /**
274
     * Generate the folders.
275
     */
276 72
    public function generateFolders()
277
    {
278 72
        foreach ($this->getFolders() as $folder) {
279 72
            if ($folder === false) {
280 1
                return;
281
            }
282
283 71
            $path = $this->module->getModulePath($this->getName()) . '/' . $folder;
284
285 71
            $this->filesystem->makeDirectory($path, 0755, true);
286
287 71
            $this->generateGitKeep($path);
288
        }
289 71
    }
290
291
    /**
292
     * Generate git keep to the specified path.
293
     *
294
     * @param string $path
295
     */
296 71
    public function generateGitKeep($path)
297
    {
298 71
        $this->filesystem->put($path . '/.gitkeep', '');
299 71
    }
300
301
    /**
302
     * Generate the files.
303
     */
304 65
    public function generateFiles()
305
    {
306 65
        foreach ($this->getFiles() as $stub => $file) {
307 65
            $path = $this->module->getModulePath($this->getName()) . $file;
308
309 65 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...
310 65
                $this->filesystem->makeDirectory($dir, 0775, true);
311
            }
312
313 65
            $this->filesystem->put($path, $this->getStubContents($stub));
314
315 65
            $this->console->info("Created : {$path}");
316
        }
317 65
    }
318
319
    /**
320
     * Generate some resources.
321
     */
322 65
    public function generateResources()
323
    {
324 65
        $this->console->call('module:make-seed', [
325 65
            'name' => $this->getName(),
326 65
            'module' => $this->getName(),
327
            '--master' => true,
328
        ]);
329
330 65
        $this->console->call('module:make-provider', [
331 65
            'name' => $this->getName() . 'ServiceProvider',
332 65
            'module' => $this->getName(),
333
            '--master' => true,
334
        ]);
335
336 65
        $this->console->call('module:make-controller', [
337 65
            'controller' => $this->getName() . 'Controller',
338 65
            'module' => $this->getName(),
339
        ]);
340 65
    }
341
342
    /**
343
     * Get the contents of the specified stub file by given stub name.
344
     *
345
     * @param $stub
346
     *
347
     * @return string
348
     */
349 72
    protected function getStubContents($stub)
350
    {
351 72
        return (new Stub(
352 72
            '/' . $stub . '.stub',
353 72
            $this->getReplacement($stub)
354
        )
355 72
        )->render();
356
    }
357
358
    /**
359
     * get the list for the replacements.
360
     */
361
    public function getReplacements()
362
    {
363
        return $this->module->config('stubs.replacements');
364
    }
365
366
    /**
367
     * Get array replacement for the specified stub.
368
     *
369
     * @param $stub
370
     *
371
     * @return array
372
     */
373 72
    protected function getReplacement($stub)
374
    {
375 72
        $replacements = $this->module->config('stubs.replacements');
376
377 72
        if (!isset($replacements[$stub])) {
378
            return [];
379
        }
380
381 72
        $keys = $replacements[$stub];
382
383 72
        $replaces = [];
384
385 72
        foreach ($keys as $key) {
386 72
            if (method_exists($this, $method = 'get' . ucfirst(studly_case(strtolower($key))) . 'Replacement')) {
387 72
                $replaces[$key] = $this->$method();
388
            } else {
389 72
                $replaces[$key] = null;
390
            }
391
        }
392
393 72
        return $replaces;
394
    }
395
396
    /**
397
     * Generate the module.json file
398
     */
399 72
    private function generateModuleJsonFile()
400
    {
401 72
        $path = $this->module->getModulePath($this->getName()) . 'module.json';
402
403 72 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...
404 1
            $this->filesystem->makeDirectory($dir, 0775, true);
405
        }
406
407 72
        $this->filesystem->put($path, $this->getStubContents('json'));
408
409 72
        $this->console->info("Created : {$path}");
410 72
    }
411
412
    /**
413
     * Remove the default service provider that was added in the module.json file
414
     * This is needed when a --plain module was created
415
     */
416 7
    private function cleanModuleJsonFile()
417
    {
418 7
        $path = $this->module->getModulePath($this->getName()) . 'module.json';
419
420 7
        $content = $this->filesystem->get($path);
421 7
        $namespace = $this->getModuleNamespaceReplacement();
422 7
        $studlyName = $this->getStudlyNameReplacement();
423
424 7
        $provider = '"' . $namespace . '\\\\' . $studlyName . '\\\\Providers\\\\' . $studlyName . 'ServiceProvider"';
425
426 7
        $content = str_replace($provider, '', $content);
427
428 7
        $this->filesystem->put($path, $content);
429 7
    }
430
431
    /**
432
     * Get the module name in lower case.
433
     *
434
     * @return string
435
     */
436 72
    protected function getLowerNameReplacement()
437
    {
438 72
        return strtolower($this->getName());
439
    }
440
441
    /**
442
     * Get the module name in studly case.
443
     *
444
     * @return string
445
     */
446 72
    protected function getStudlyNameReplacement()
447
    {
448 72
        return $this->getName();
449
    }
450
451
    /**
452
     * Get replacement for $VENDOR$.
453
     *
454
     * @return string
455
     */
456 65
    protected function getVendorReplacement()
457
    {
458 65
        return $this->module->config('composer.vendor');
459
    }
460
461
    /**
462
     * Get replacement for $MODULE_NAMESPACE$.
463
     *
464
     * @return string
465
     */
466 72
    protected function getModuleNamespaceReplacement()
467
    {
468 72
        return str_replace('\\', '\\\\', $this->module->config('namespace'));
469
    }
470
471
    /**
472
     * Get replacement for $AUTHOR_NAME$.
473
     *
474
     * @return string
475
     */
476 65
    protected function getAuthorNameReplacement()
477
    {
478 65
        return $this->module->config('composer.author.name');
479
    }
480
481
    /**
482
     * Get replacement for $AUTHOR_EMAIL$.
483
     *
484
     * @return string
485
     */
486 65
    protected function getAuthorEmailReplacement()
487
    {
488 65
        return $this->module->config('composer.author.email');
489
    }
490
491 65
    protected function getRoutesLocationReplacement()
492
    {
493 65
        return '/' . $this->module->config('stubs.files.routes');
494
    }
495
}
496