1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace App\Modules\Core\Console\Commands; |
4
|
|
|
|
5
|
|
|
use Illuminate\Support\Str; |
6
|
|
|
use Illuminate\Console\Command; |
7
|
|
|
use Illuminate\Filesystem\Filesystem; |
8
|
|
|
use Caffeinated\Modules\RepositoryManager; |
9
|
|
|
use Symfony\Component\Console\Helper\ProgressBar; |
10
|
|
|
|
11
|
|
|
class MakeModuleCommand extends Command |
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* The name and signature of the console command. |
15
|
|
|
* |
16
|
|
|
* @var string |
17
|
|
|
*/ |
18
|
|
|
protected $signature = 'generate:module |
19
|
|
|
{slug : The slug of the module}'; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* The console command description. |
23
|
|
|
* |
24
|
|
|
* @var string |
25
|
|
|
*/ |
26
|
|
|
protected $description = 'Create a new module'; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* The modules instance. |
30
|
|
|
* |
31
|
|
|
* @var RepositoryManager |
32
|
|
|
*/ |
33
|
|
|
protected $module; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* The filesystem instance. |
37
|
|
|
* |
38
|
|
|
* @var Filesystem |
39
|
|
|
*/ |
40
|
|
|
protected $files; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Array to store the configuration details. |
44
|
|
|
* |
45
|
|
|
* @var array |
46
|
|
|
*/ |
47
|
|
|
protected $container; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Array of folder mappings. |
51
|
|
|
* |
52
|
|
|
* @var Array |
53
|
|
|
*/ |
54
|
|
|
protected $mapping = [ |
55
|
|
|
'Database/Factories' => 'Database/Factories', |
56
|
|
|
'Database/Migrations' => 'Database/Migrations', |
57
|
|
|
'Database/Seeds' => 'Database/Seeds', |
58
|
|
|
'Http/Controllers' => 'Http/Controllers', |
59
|
|
|
'Http/Requests' => 'Http/Requests', |
60
|
|
|
'Http/Resources' => 'Http/Resources', |
61
|
|
|
'ModelObservers' => 'ModelObservers', |
62
|
|
|
'Providers' => 'Providers', |
63
|
|
|
'Repositories' => 'Repositories', |
64
|
|
|
'Routes' => 'Routes' |
65
|
|
|
]; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Create a new command instance. |
69
|
|
|
* |
70
|
|
|
* @param Filesystem $files |
71
|
|
|
* @param RepositoryManager $module |
72
|
|
|
*/ |
73
|
|
|
public function __construct(Filesystem $files, RepositoryManager $module) |
74
|
|
|
{ |
75
|
|
|
parent::__construct(); |
76
|
|
|
|
77
|
|
|
$this->files = $files; |
78
|
|
|
$this->module = $module; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Execute the console command. |
83
|
|
|
* |
84
|
|
|
* @return mixed |
85
|
|
|
*/ |
86
|
|
|
public function handle() |
87
|
|
|
{ |
88
|
|
|
$this->container['slug'] = Str::slug($this->argument('slug')); |
|
|
|
|
89
|
|
|
$this->container['name'] = Str::studly($this->container['slug']); |
90
|
|
|
$this->container['version'] = '1.0'; |
91
|
|
|
$this->container['description'] = 'This is the description for the ' . $this->container['name'] . ' module.'; |
92
|
|
|
$this->container['location'] = config('modules.default_location'); |
93
|
|
|
$this->container['provider'] = config("modules.locations.{$this->container['location']}.provider"); |
94
|
|
|
$this->container['basename'] = Str::studly($this->container['slug']); |
95
|
|
|
$this->container['namespace'] = config("modules.locations.{$this->container['location']}.namespace").$this->container['basename']; |
96
|
|
|
|
97
|
|
|
return $this->generate(); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Generate the module. |
102
|
|
|
*/ |
103
|
|
|
protected function generate() |
104
|
|
|
{ |
105
|
|
|
$steps = [ |
106
|
|
|
'Generating module...' => 'generateModule', |
107
|
|
|
'Optimizing module cache...' => 'optimizeModules', |
108
|
|
|
'Generating migrations...' => 'generateMigration', |
109
|
|
|
]; |
110
|
|
|
|
111
|
|
|
$progress = new ProgressBar($this->output, count($steps)); |
112
|
|
|
$progress->start(); |
113
|
|
|
|
114
|
|
|
foreach ($steps as $message => $function) { |
115
|
|
|
$progress->setMessage($message); |
116
|
|
|
|
117
|
|
|
$this->$function(); |
118
|
|
|
|
119
|
|
|
$progress->advance(); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
$progress->finish(); |
123
|
|
|
|
124
|
|
|
event($this->container['slug'] . '.module.made'); |
125
|
|
|
|
126
|
|
|
$this->info("\nModule generated successfully."); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Generate defined module folders. |
131
|
|
|
*/ |
132
|
|
|
protected function generateModule() |
133
|
|
|
{ |
134
|
|
|
$location = $this->container['location']; |
135
|
|
|
$root = module_path(null, '', $location); |
136
|
|
|
$manifest = config("modules.locations.$location.manifest") ?: 'module.json'; |
137
|
|
|
$provider = config("modules.locations.$location.provider") ?: 'ModuleServiceProvider'; |
138
|
|
|
|
139
|
|
|
if (!$this->files->isDirectory($root)) { |
140
|
|
|
$this->files->makeDirectory($root); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
$directory = module_path(null, $this->container['basename'], $location); |
144
|
|
|
$source = __DIR__ . '/Stubs/Module'; |
145
|
|
|
|
146
|
|
|
$this->files->makeDirectory($directory); |
147
|
|
|
|
148
|
|
|
$sourceFiles = $this->files->allFiles($source, true); |
149
|
|
|
|
150
|
|
|
if (!empty($this->mapping)) { |
151
|
|
|
$search = array_keys($this->mapping); |
152
|
|
|
$replace = array_values($this->mapping); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
foreach ($sourceFiles as $file) { |
156
|
|
|
$contents = $this->replacePlaceholders($file->getContents()); |
157
|
|
|
$subPath = $file->getRelativePathname(); |
158
|
|
|
|
159
|
|
|
if (!empty($this->mapping)) { |
160
|
|
|
$subPath = str_replace($search, $replace, $subPath); |
|
|
|
|
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
$filePath = $directory . '/' . $subPath; |
164
|
|
|
|
165
|
|
|
// if the file is module.json, replace it with the custom manifest file name |
166
|
|
|
if ($file->getFilename() === 'module.json' && $manifest) { |
167
|
|
|
$filePath = str_replace('module.json', $manifest, $filePath); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
// if the file is ModuleServiceProvider.php, replace it with the custom provider file name |
171
|
|
|
if ($file->getFilename() === 'ModuleServiceProvider.php') { |
172
|
|
|
$filePath = str_replace('ModuleServiceProvider', $provider, $filePath); |
173
|
|
|
} |
174
|
|
|
$filePath = $this->replacePlaceholders($filePath); |
175
|
|
|
|
176
|
|
|
$dir = dirname($filePath); |
177
|
|
|
|
178
|
|
|
if (! $this->files->isDirectory($dir)) { |
179
|
|
|
$this->files->makeDirectory($dir, 0755, true); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
$this->files->put($filePath, $contents); |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
protected function replacePlaceholders($contents) |
187
|
|
|
{ |
188
|
|
|
$modelName = \Str::camel($this->container['slug']); |
189
|
|
|
$modelNameSingular = \Str::singular($modelName); |
190
|
|
|
|
191
|
|
|
$find = [ |
192
|
|
|
'DummyFactory', |
193
|
|
|
'DummyModelName', |
194
|
|
|
'DummyModuleSlug', |
195
|
|
|
'DummyModule', |
196
|
|
|
'DummyModel', |
197
|
|
|
'DummyDatabaseSeeder', |
198
|
|
|
'DummyTableSeeder', |
199
|
|
|
'DummyController', |
200
|
|
|
'DummyRepository', |
201
|
|
|
'InsertDummy', |
202
|
|
|
'UpdateDummy', |
203
|
|
|
'DummyResource', |
204
|
|
|
'DummyObserver', |
205
|
|
|
'DummyTableName', |
206
|
|
|
'DummyRoutePrefix', |
207
|
|
|
]; |
208
|
|
|
|
209
|
|
|
$replace = [ |
210
|
|
|
ucfirst($modelNameSingular) . 'Factory', |
211
|
|
|
$modelNameSingular, |
212
|
|
|
$this->container['slug'], |
213
|
|
|
ucfirst($modelName), |
214
|
|
|
ucfirst($modelNameSingular), |
215
|
|
|
ucfirst($modelName) . 'DatabaseSeeder', |
216
|
|
|
ucfirst($modelName) . 'TableSeeder', |
217
|
|
|
ucfirst($modelNameSingular) . 'Controller', |
218
|
|
|
ucfirst($modelNameSingular) . 'Repository', |
219
|
|
|
'Insert' . ucfirst($modelNameSingular), |
220
|
|
|
'Update' . ucfirst($modelNameSingular), |
221
|
|
|
ucfirst($modelNameSingular), |
222
|
|
|
ucfirst($modelNameSingular) . 'Observer', |
223
|
|
|
$modelName, |
224
|
|
|
$modelName, |
225
|
|
|
]; |
226
|
|
|
|
227
|
|
|
return str_replace($find, $replace, $contents); |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* Reset module cache of enabled and disabled modules. |
232
|
|
|
*/ |
233
|
|
|
protected function optimizeModules() |
234
|
|
|
{ |
235
|
|
|
return $this->callSilent('module:optimize'); |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* Generate table migrations. |
240
|
|
|
*/ |
241
|
|
|
protected function generateMigration() |
242
|
|
|
{ |
243
|
|
|
$modelName = $this->container['slug']; |
244
|
|
|
return $this->callSilent('make:module:migration', ['slug' => $modelName, 'name' => 'create_' . $modelName . '_table']); |
245
|
|
|
} |
246
|
|
|
} |
247
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.