Completed
Push — develop ( 500347...42c100 )
by Abdelrahman
01:48
created

ModuleMakeCommand   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 171
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 10
c 0
b 0
f 0
lcom 1
cbo 2
dl 0
loc 171
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A makeDirectory() 0 8 2
A __construct() 0 6 1
B handle() 0 24 2
A generateSamples() 0 19 1
B 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
10
class ModuleMakeCommand extends Command
11
{
12
    /**
13
     * The filesystem instance.
14
     *
15
     * @var \Illuminate\Filesystem\Filesystem
16
     */
17
    protected $files;
18
19
    /**
20
     * The console command signature.
21
     *
22
     * @var string
23
     */
24
    protected $signature = 'make:module {name : The name of the module.}';
25
26
    /**
27
     * The console command description.
28
     *
29
     * @var string
30
     */
31
    protected $description = 'Create a new module structure';
32
33
    /**
34
     * The type of class being generated.
35
     *
36
     * @var string
37
     */
38
    protected $type = 'Module';
39
40
    /**
41
     * Create a new controller creator command instance.
42
     *
43
     * @param \Illuminate\Filesystem\Filesystem $files
44
     *
45
     * @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...
46
     */
47
    public function __construct(Filesystem $files)
48
    {
49
        parent::__construct();
50
51
        $this->files = $files;
52
    }
53
54
    /**
55
     * Execute the console command.
56
     *
57
     * @return bool|null
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use false|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
58
     */
59
    public function handle()
60
    {
61
        $name = $this->getNameInput();
62
63
        $path = app_path($name);
64
65
        // First we will check to see if the class already exists. If it does, we don't want
66
        // to create the class and overwrite the user's code. So, we will bail out so the
67
        // code is untouched. Otherwise, we will continue generating this class' files.
68
        if ($this->files->exists($path)) {
69
            $this->error($this->type.' already exists!');
70
71
            return false;
72
        }
73
74
        // Next, we will generate the path to the location where this class' file should get
75
        // written. Then, we will build the class and make the proper replacements on the
76
        // stub files so that it gets the correctly formatted namespace and class name.
77
        $stubs = __DIR__.'/../../../resources/stubs/module';
78
        $this->processStubs($stubs, $path);
79
        $this->generateSamples();
80
81
        $this->info($this->type.' created successfully.');
82
    }
83
84
    /**
85
     * Build the directory for the class if necessary.
86
     *
87
     * @param string $path
88
     *
89
     * @return string
90
     */
91
    protected function makeDirectory($path)
92
    {
93
        if (! $this->files->isDirectory($path)) {
94
            $this->files->makeDirectory($path, 0777, true, true);
95
        }
96
97
        return $path;
98
    }
99
100
    /**
101
     * Generate code samples.
102
     *
103
     * @return void
104
     */
105
    protected function generateSamples()
106
    {
107
        $module = str_after($this->getNameInput(), '/');
108
109
        $this->call('make:config', ['name' => 'config', '--module' => $this->getNameInput()]);
110
        $this->call('make:model', ['name' => 'Example', '--module' => $this->getNameInput()]);
111
        $this->call('make:policy', ['name' => 'ExamplePolicy', '--module' => $this->getNameInput()]);
112
        $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...
113
        $this->call('make:command', ['name' => 'ExampleCommand', '--module' => $this->getNameInput()]);
114
        $this->call('make:controller', ['name' => 'ExampleController', '--module' => $this->getNameInput()]);
115
        $this->call('make:request', ['name' => 'ExampleRequest', '--module' => $this->getNameInput()]);
116
        $this->call('make:middleware', ['name' => 'ExampleMiddleware', '--module' => $this->getNameInput()]);
117
        $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...
118
        $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...
119
120
        $this->warn('Optionally create migrations and seeds (it may take some time):');
121
        $this->warn("artisan make:migration create_{$module}_example_table --module {$this->getNameInput()}");
122
        $this->warn("artisan make:seeder ExampleSeeder --module {$this->getNameInput()}");
123
    }
124
125
    /**
126
     * Process stubs placeholders.
127
     *
128
     * @param string $stubs
129
     * @param string $path
130
     *
131
     * @return void
132
     */
133
    protected function processStubs($stubs, $path)
134
    {
135
        $this->makeDirectory($path);
136
        $this->files->copyDirectory($stubs, $path);
137
138
        $files = [
139
            ($phpunit = $path.DIRECTORY_SEPARATOR.'phpunit.xml.dist') => $this->files->get($phpunit),
140
            ($composer = $path.DIRECTORY_SEPARATOR.'composer.json') => $this->files->get($composer),
141
            ($changelog = $path.DIRECTORY_SEPARATOR.'CHANGELOG.md') => $this->files->get($changelog),
142
            ($readme = $path.DIRECTORY_SEPARATOR.'README.md') => $this->files->get($readme),
143
        ];
144
145
        $module = ucfirst(str_after($this->getNameInput(), '/'));
146
        $name = implode(' ', array_map('ucfirst', explode('/', $this->getNameInput())));
147
        $jsonNamespace = implode('\\\\', array_map('ucfirst', explode('/', $this->getNameInput())));
148
149
        foreach ($files as $key => &$file) {
150
            $file = str_replace('DummyModuleName', $name, $file);
151
            $file = str_replace('Dummy\\Module', $jsonNamespace, $file);
152
            $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...
153
154
            $file = str_replace('dummy/module', $this->getNameInput(), $file);
155
            $file = str_replace('dummy-module', str_replace('/', '-', $this->getNameInput()), $file);
156
            $file = str_replace('dummy:module', str_replace('/', ':', $this->getNameInput()), $file);
157
            $file = str_replace('dummy.module', str_replace('/', '.', $this->getNameInput()), $file);
158
159
            $this->files->put($key, $file);
160
        }
161
    }
162
163
    /**
164
     * Get the desired class name from the input.
165
     *
166
     * @throws \Exception
167
     *
168
     * @return string
169
     */
170
    protected function getNameInput()
171
    {
172
        $name = trim($this->argument('name'));
173
174
        if (mb_strpos($name, '/') === false) {
175
            throw new \Exception('Module name must consist of two segments: vendor/module');
176
        }
177
178
        return $name;
179
    }
180
}
181