Completed
Push — master ( 2e4876...a75670 )
by Nicolas
04:01
created

ModuleGenerator::getProviderNamespaceReplacement()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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