Completed
Push — master ( 0e1003...1276c7 )
by Abdelrahman
61:46 queued 59:06
created

ModuleMakeCommand   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 173
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 3
dl 0
loc 173
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A handle() 0 24 2
A makeDirectory() 0 8 2
A generateSamples() 0 19 1
A processStubs() 0 29 2
A getNameInput() 0 10 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cortex\Foundation\Console\Commands;
6
7
use Illuminate\Console\Command;
8
use Illuminate\Filesystem\Filesystem;
9
use Illuminate\Console\ConfirmableTrait;
10
11
class ModuleMakeCommand extends Command
12
{
13
    use ConfirmableTrait;
14
15
    /**
16
     * The filesystem instance.
17
     *
18
     * @var \Illuminate\Filesystem\Filesystem
19
     */
20
    protected $files;
21
22
    /**
23
     * The console command signature.
24
     *
25
     * @var string
26
     */
27
    protected $signature = 'make:module {name : The name of the module.}';
28
29
    /**
30
     * The console command description.
31
     *
32
     * @var string
33
     */
34
    protected $description = 'Create a new module structure';
35
36
    /**
37
     * The type of class being generated.
38
     *
39
     * @var string
40
     */
41
    protected $type = 'Module';
42
43
    /**
44
     * Create a new controller creator command instance.
45
     *
46
     * @param \Illuminate\Filesystem\Filesystem $files
47
     *
48
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
49
     */
50
    public function __construct(Filesystem $files)
51
    {
52
        parent::__construct();
53
54
        $this->files = $files;
55
    }
56
57
    /**
58
     * Execute the console command.
59
     *
60
     * @return void
61
     */
62
    public function handle(): void
63
    {
64
        $name = $this->getNameInput();
65
66
        $path = app_path($name);
67
68
        // First we will check to see if the class already exists. If it does, we don't want
69
        // to create the class and overwrite the user's code. So, we will bail out so the
70
        // code is untouched. Otherwise, we will continue generating this class' files.
71
        if ($this->files->exists($path)) {
72
            $this->error($this->type.' already exists!');
73
74
            return;
75
        }
76
77
        // Next, we will generate the path to the location where this class' file should get
78
        // written. Then, we will build the class and make the proper replacements on the
79
        // stub files so that it gets the correctly formatted namespace and class name.
80
        $stubs = __DIR__.'/../../../resources/stubs/module';
81
        $this->processStubs($stubs, $path);
82
        $this->generateSamples();
83
84
        $this->info($this->type.' created successfully.');
85
    }
86
87
    /**
88
     * Build the directory for the class if necessary.
89
     *
90
     * @param string $path
91
     *
92
     * @return string
93
     */
94
    protected function makeDirectory($path): string
95
    {
96
        if (! $this->files->isDirectory($path)) {
97
            $this->files->makeDirectory($path, 0777, true, true);
98
        }
99
100
        return $path;
101
    }
102
103
    /**
104
     * Generate code samples.
105
     *
106
     * @return void
107
     */
108
    protected function generateSamples(): void
109
    {
110
        $module = str_after($this->getNameInput(), '/');
111
112
        $this->call('make:config', ['name' => 'config', '--module' => $this->getNameInput()]);
113
        $this->call('make:model', ['name' => 'Example', '--module' => $this->getNameInput()]);
114
        $this->call('make:policy', ['name' => 'ExamplePolicy', '--module' => $this->getNameInput()]);
115
        $this->call('make:provider', ['name' => ucfirst($module).'ServiceProvider', '--module' => $this->getNameInput()]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 122 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
116
        $this->call('make:command', ['name' => 'ExampleCommand', '--module' => $this->getNameInput()]);
117
        $this->call('make:controller', ['name' => 'ExampleController', '--module' => $this->getNameInput()]);
118
        $this->call('make:request', ['name' => 'ExampleRequest', '--module' => $this->getNameInput()]);
119
        $this->call('make:middleware', ['name' => 'ExampleMiddleware', '--module' => $this->getNameInput()]);
120
        $this->call('make:transformer', ['name' => 'ExampleTransformer', '--model' => 'Example', '--module' => $this->getNameInput()]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 135 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
121
        $this->call('make:datatable', ['name' => 'ExampleDatatable', '--model' => 'Example', '--transformer' => 'ExampleTransformer', '--module' => $this->getNameInput()]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 172 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
122
123
        $this->warn('Optionally create migrations and seeds (it may take some time):');
124
        $this->warn("artisan make:migration create_{$module}_example_table --module {$this->getNameInput()}");
125
        $this->warn("artisan make:seeder ExampleSeeder --module {$this->getNameInput()}");
126
    }
127
128
    /**
129
     * Process stubs placeholders.
130
     *
131
     * @param string $stubs
132
     * @param string $path
133
     *
134
     * @return void
135
     */
136
    protected function processStubs($stubs, $path): void
137
    {
138
        $this->makeDirectory($path);
139
        $this->files->copyDirectory($stubs, $path);
140
141
        $files = [
142
            ($phpunit = $path.DIRECTORY_SEPARATOR.'phpunit.xml.dist') => $this->files->get($phpunit),
143
            ($composer = $path.DIRECTORY_SEPARATOR.'composer.json') => $this->files->get($composer),
144
            ($changelog = $path.DIRECTORY_SEPARATOR.'CHANGELOG.md') => $this->files->get($changelog),
145
            ($readme = $path.DIRECTORY_SEPARATOR.'README.md') => $this->files->get($readme),
146
        ];
147
148
        $module = ucfirst(str_after($this->getNameInput(), '/'));
149
        $name = implode(' ', array_map('ucfirst', explode('/', $this->getNameInput())));
150
        $jsonNamespace = implode('\\\\', array_map('ucfirst', explode('/', $this->getNameInput())));
151
152
        foreach ($files as $key => &$file) {
153
            $file = str_replace('DummyModuleName', $name, $file);
154
            $file = str_replace('Dummy\\\\Module', $jsonNamespace, $file);
155
            $file = str_replace('DummyModuleServiceProvider', $jsonNamespace."\\\\Providers\\\\{$module}ServiceProvider", $file);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 129 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
156
157
            $file = str_replace('dummy/module', $this->getNameInput(), $file);
158
            $file = str_replace('dummy-module', str_replace('/', '-', $this->getNameInput()), $file);
159
            $file = str_replace('dummy:module', str_replace('/', ':', $this->getNameInput()), $file);
160
            $file = str_replace('dummy.module', str_replace('/', '.', $this->getNameInput()), $file);
161
162
            $this->files->put($key, $file);
163
        }
164
    }
165
166
    /**
167
     * Get the desired class name from the input.
168
     *
169
     * @throws \Exception
170
     *
171
     * @return string
172
     */
173
    protected function getNameInput(): string
174
    {
175
        $name = trim($this->argument('name'));
176
177
        if (mb_strpos($name, '/') === false) {
178
            throw new \Exception('Module name must consist of two segments: vendor/module');
179
        }
180
181
        return $name;
182
    }
183
}
184