Completed
Pull Request — master (#463)
by František
06:37
created

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