1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Microboard\Commands; |
4
|
|
|
|
5
|
|
|
use Illuminate\Contracts\Filesystem\FileNotFoundException; |
6
|
|
|
use Illuminate\Support\Arr; |
7
|
|
|
use Illuminate\Support\Str; |
8
|
|
|
use Facades\Microboard\Factory; |
9
|
|
|
use Microboard\Models\Role; |
10
|
|
|
|
11
|
|
|
class ResourceCommand extends WorkingWithStubs |
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* The name and signature of the console command. |
15
|
|
|
* |
16
|
|
|
* @var string |
17
|
|
|
*/ |
18
|
|
|
protected $signature = 'microboard:resource |
19
|
|
|
{model : The name of resource class} |
20
|
|
|
{--views-directory=admin} |
21
|
|
|
{--view-namespace=} |
22
|
|
|
{--abilities=}'; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* The console command description. |
26
|
|
|
* |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
protected $description = 'Command description'; |
30
|
|
|
|
31
|
|
|
protected $abilities = [ |
32
|
|
|
'viewAny', 'view', 'create', 'update', 'delete' |
33
|
|
|
]; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Execute the console command. |
37
|
|
|
* |
38
|
|
|
* @return mixed |
39
|
|
|
*/ |
40
|
|
|
public function handle() |
41
|
|
|
{ |
42
|
|
|
$model = $this->qualifyClass($this->getNameInput()); |
43
|
|
|
$this->setVariables($model); |
44
|
|
|
|
45
|
|
|
// Create permissions for this resource. |
46
|
|
|
if ($this->hasOption('abilities')) { |
47
|
|
|
$this->abilities = explode(',', $this->option('abilities')); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
Factory::createResourcesPermissionsFor(Role::first(), [ |
51
|
|
|
$this->variables['%RESOURCE_NAME_PLURAL%'] => $this->abilities |
52
|
|
|
]); |
53
|
|
|
|
54
|
|
|
try { |
55
|
|
|
$this->createPolicy(); |
56
|
|
|
$this->createLanguageFiles(); |
57
|
|
|
$this->createDatatable(); |
58
|
|
|
$this->createController(); |
59
|
|
|
$this->createFormRequests(); |
60
|
|
|
$this->createResourceViews(); |
61
|
|
|
} catch (FileNotFoundException $e) { |
62
|
|
|
$this->error($e->getMessage()); |
63
|
|
|
} |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Get the desired class name from the input. |
68
|
|
|
* |
69
|
|
|
* @return string |
70
|
|
|
*/ |
71
|
|
|
protected function getNameInput() |
72
|
|
|
{ |
73
|
|
|
return trim($this->argument('model')); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Set model variables |
78
|
|
|
* |
79
|
|
|
* @var string $model |
80
|
|
|
*/ |
81
|
|
|
public function setVariables($model) |
82
|
|
|
{ |
83
|
|
|
$base_name = class_basename($model); |
84
|
|
|
|
85
|
|
|
$this->variables = [ |
86
|
|
|
'%NAMESPACE%' => $this->rootNamespace(), |
87
|
|
|
'%RESOURCE_MODEL%' => $model, |
88
|
|
|
'%RESOURCE_MODEL_BASE%' => class_basename($model), |
89
|
|
|
'%RESOURCE_NAME_PLURAL%' => (string)Str::of($base_name)->snake()->plural(), |
90
|
|
|
'%RESOURCE_NAME_SINGULAR%' => (string)Str::of($base_name)->snake()->singular(), |
91
|
|
|
'%VIEW_NAMESPACE%' => $this->option('view-namespace'), |
92
|
|
|
'%VIEW_DIRECTORY%' => $this->option('views-directory') . '/' . ((string)Str::of($base_name)->snake()->plural()) . '/', |
93
|
|
|
'%BLADE_VIEW_DIRECTORY%' => ($this->hasOption('views-directory') ? ($this->option('views-directory') . '.') : '') . |
94
|
|
|
((string)Str::of($base_name)->snake()->plural()), |
95
|
|
|
]; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Create resource views |
100
|
|
|
* |
101
|
|
|
* @throws FileNotFoundException |
102
|
|
|
*/ |
103
|
|
|
private function createResourceViews() |
104
|
|
|
{ |
105
|
|
|
$directory = 'resources/views/' . $this->variables['%VIEW_DIRECTORY%']; |
106
|
|
|
|
107
|
|
View Code Duplication |
foreach (['index', 'show', 'edit', 'create'] as $view) { |
|
|
|
|
108
|
|
|
$this->createFromStub( |
109
|
|
|
__DIR__ . '/../../stubs/resource/' . $view . '.stub', |
110
|
|
|
$directory, |
111
|
|
|
$view . '.blade.php', |
112
|
|
|
array_merge($this->variables, ['%COLUMNS%' => $this->buildShowViewColumns()]) |
113
|
|
|
); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
$this->createFromStub( |
117
|
|
|
__DIR__ . '/../../stubs/resource/form.stub', |
118
|
|
|
$directory, |
119
|
|
|
'form.blade.php', |
120
|
|
|
array_merge($this->variables, ['%COLUMNS%' => $this->buildFormInputs()]) |
121
|
|
|
); |
122
|
|
|
|
123
|
|
|
$this->info(sprintf( |
124
|
|
|
'Resource views created successfully, [%s]', |
125
|
|
|
$directory |
126
|
|
|
)); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Create lang file for this model |
131
|
|
|
* |
132
|
|
|
* TODO:: Support multiple languages |
133
|
|
|
*/ |
134
|
|
View Code Duplication |
private function createLanguageFiles() |
|
|
|
|
135
|
|
|
{ |
136
|
|
|
$this->createFromStub( |
137
|
|
|
__DIR__ . '/../../stubs/resource.stub', |
138
|
|
|
$directory = 'resources/lang/' . (config('app.locale')), |
139
|
|
|
$file = $this->variables['%RESOURCE_NAME_PLURAL%'] . '.php', |
140
|
|
|
array_merge($this->variables, ['%COLUMNS%' => $this->buildLanguageFilesColumns()]) |
141
|
|
|
); |
142
|
|
|
|
143
|
|
|
$this->info(sprintf( |
144
|
|
|
'Resource languages file created successfully, [%s/%s]', |
145
|
|
|
$directory, $file |
146
|
|
|
)); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Create datatable class |
151
|
|
|
*/ |
152
|
|
View Code Duplication |
private function createDatatable() |
|
|
|
|
153
|
|
|
{ |
154
|
|
|
$this->createFromStub( |
155
|
|
|
__DIR__ . '/../../stubs/resource-datatable.stub', |
156
|
|
|
$directory = 'app/DataTables/', |
157
|
|
|
$file = Str::studly($this->variables['%RESOURCE_NAME_SINGULAR%'] . 'DataTable') . '.php', |
158
|
|
|
array_merge($this->variables, ['%COLUMNS%' => $this->buildDatatableColumns()]) |
159
|
|
|
); |
160
|
|
|
|
161
|
|
|
$this->info(sprintf( |
162
|
|
|
'Datatable class created successfully, [%s%s]', |
163
|
|
|
$directory, $file |
164
|
|
|
)); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Create controller class |
169
|
|
|
*/ |
170
|
|
|
private function createController() |
171
|
|
|
{ |
172
|
|
|
$this->createFromStub( |
173
|
|
|
__DIR__ . '/../../stubs/resource-controller.stub', |
174
|
|
|
$directory = 'app/Http/Controllers/', |
175
|
|
|
$file = Str::studly($this->variables['%RESOURCE_NAME_SINGULAR%'] . 'Controller') . '.php', |
176
|
|
|
$this->variables |
177
|
|
|
); |
178
|
|
|
|
179
|
|
|
$this->info(sprintf( |
180
|
|
|
'Controller created successfully, [%s%s]', |
181
|
|
|
$directory, $file |
182
|
|
|
)); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Create form request classes |
187
|
|
|
*/ |
188
|
|
|
private function createFormRequests() |
189
|
|
|
{ |
190
|
|
|
$directory = 'app/Http/Requests/' . $this->variables['%RESOURCE_MODEL_BASE%'] . '/'; |
191
|
|
|
|
192
|
|
View Code Duplication |
foreach (['store', 'update'] as $method) { |
|
|
|
|
193
|
|
|
$this->createFromStub( |
194
|
|
|
__DIR__ . '/../../stubs/' . $method . '-resource-form-request.stub', |
195
|
|
|
$directory, |
196
|
|
|
Str::studly($method . 'FormRequest') . '.php', |
197
|
|
|
array_merge($this->variables, ['%COLUMNS%' => $this->buildFormRequestColumns()]) |
198
|
|
|
); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
$this->info(sprintf( |
202
|
|
|
'Form requests created successfully, [%s]', |
203
|
|
|
$directory |
204
|
|
|
)); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* Create policy class |
209
|
|
|
*/ |
210
|
|
|
private function createPolicy() |
211
|
|
|
{ |
212
|
|
|
$this->createFromStub( |
213
|
|
|
__DIR__ . '/../../stubs/resource-policy.stub', |
214
|
|
|
$directory = 'app/Policies/', |
215
|
|
|
$file = Str::studly($this->variables['%RESOURCE_MODEL_BASE%'] . 'Policy') . '.php', |
216
|
|
|
$this->variables |
217
|
|
|
); |
218
|
|
|
|
219
|
|
|
$this->info(sprintf( |
220
|
|
|
'Form requests created successfully, [%s%s]', |
221
|
|
|
$directory, $file |
222
|
|
|
)); |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* get fillable columns from given model |
227
|
|
|
* |
228
|
|
|
* @return array |
229
|
|
|
*/ |
230
|
|
|
private function getModelColumns() |
231
|
|
|
{ |
232
|
|
|
return (new $this->variables['%RESOURCE_MODEL%'])->getFillable(); |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* build resource's columns as html from form-input.stub |
237
|
|
|
* |
238
|
|
|
* @return string |
239
|
|
|
* |
240
|
|
|
* @throws FileNotFoundException |
241
|
|
|
*/ |
242
|
|
|
private function buildFormInputs() |
243
|
|
|
{ |
244
|
|
|
$columns = ''; |
245
|
|
|
|
246
|
|
|
foreach ($this->getModelColumns() as $column) { |
247
|
|
|
if (in_array($column, (new $this->variables['%RESOURCE_MODEL%'])->getHidden())) { |
248
|
|
|
continue; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
$this->variables['%COLUMN_NAME%'] = $column; |
252
|
|
|
|
253
|
|
|
$variables = Arr::only($this->variables, [ |
254
|
|
|
'%RESOURCE_NAME_SINGULAR%', '%VIEW_NAMESPACE%', '%RESOURCE_NAME_PLURAL%', '%COLUMN_NAME%' |
255
|
|
|
]); |
256
|
|
|
|
257
|
|
|
$columns .= str_replace( |
258
|
|
|
array_keys($variables), |
259
|
|
|
array_values($variables), |
260
|
|
|
$this->files->get(__DIR__ . '/../../stubs/resource/form-input.stub') |
261
|
|
|
); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
return $columns; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* build resource's columns as html table's tr |
269
|
|
|
* |
270
|
|
|
* @return string |
271
|
|
|
*/ |
272
|
|
|
private function buildShowViewColumns() |
273
|
|
|
{ |
274
|
|
|
$transPrefix = $this->variables['%VIEW_NAMESPACE%'] . $this->variables['%RESOURCE_NAME_PLURAL%']; |
275
|
|
|
$columns = ''; |
276
|
|
|
|
277
|
|
|
foreach ($this->getModelColumns() as $column) { |
278
|
|
|
if (in_array($column, (new $this->variables['%RESOURCE_MODEL%'])->getHidden())) { |
279
|
|
|
continue; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
$columns .= "\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style=\"width: 25%;\">@lang('{$transPrefix}.fields.{$column}')</th>" . |
283
|
|
|
"\n\t\t\t\t\t\t\t\t<td>{{ \${$this->variables['%RESOURCE_NAME_SINGULAR%']}->{$column} }}</td>". |
284
|
|
|
"\n\t\t\t\t\t\t\t</tr>"; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
return $columns; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
/** |
291
|
|
|
* build resource's columns as key => [validations] |
292
|
|
|
* TODO:: Guess the input validations |
293
|
|
|
* |
294
|
|
|
* @return string |
295
|
|
|
*/ |
296
|
|
|
private function buildFormRequestColumns() |
297
|
|
|
{ |
298
|
|
|
$columns = ''; |
299
|
|
|
|
300
|
|
|
foreach ($this->getModelColumns() as $column) { |
301
|
|
|
$columns .= "\n\t\t\t'{$column}' => ['required'],"; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
return $columns; |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* build resource's columns as DataTables's Column::make() api |
309
|
|
|
* |
310
|
|
|
* @return string |
311
|
|
|
*/ |
312
|
|
|
private function buildDatatableColumns() |
313
|
|
|
{ |
314
|
|
|
$transPrefix = $this->variables['%VIEW_NAMESPACE%'] . $this->variables['%RESOURCE_NAME_PLURAL%']; |
315
|
|
|
$columns = "\n\t\t\tColumn::make('id')->title(trans('{$transPrefix}.fields.id'))->width('1%'),"; |
316
|
|
|
|
317
|
|
|
foreach ($this->getModelColumns() as $column) { |
318
|
|
|
if (in_array($column, (new $this->variables['%RESOURCE_MODEL%'])->getHidden())) { |
319
|
|
|
continue; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
$columns .= "\n\t\t\tColumn::make('{$column}')->title(trans('{$transPrefix}.fields.{$column}')),"; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
return $columns; |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
/** |
329
|
|
|
* build resource's columns as key => Value |
330
|
|
|
* |
331
|
|
|
* @return string |
332
|
|
|
*/ |
333
|
|
|
private function buildLanguageFilesColumns() |
334
|
|
|
{ |
335
|
|
|
$columns = ''; |
336
|
|
|
|
337
|
|
|
foreach ($this->getModelColumns() as $column) { |
338
|
|
|
if (in_array($column, (new $this->variables['%RESOURCE_MODEL%'])->getHidden())) { |
339
|
|
|
continue; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
$title = Str::of($column)->title()->replace('_', ' '); |
343
|
|
|
$columns .= "\n\t\t'{$column}' => '{$title}',"; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
return $columns; |
347
|
|
|
} |
348
|
|
|
} |
349
|
|
|
|
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.