Skip to content

Commit 8da4a36

Browse files
author
Admin
committed
auto-fill columns from db
fix singular and plural for multiword resources
1 parent 5b41f1d commit 8da4a36

12 files changed

+193
-51
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ Library for [laravel-crud-wizard-free](https://github.com/macropay-solutions/lar
2020

2121
## Usage
2222

23-
``` php artisan make:api-resource {resourceName} {--decorated}```
23+
``` php artisan make:api-resource {resourceName} {--decorated} {--table=} {connectionName?}```
2424

25-
This will create a template for **controller**, **service** and **model** (optionally, with the --decorated flag it will create also a **decorator** and **middleware**) and will print instructions on what is left to be done manually.
25+
This will create a template for **controller**, **service** and **model (with prepopulated fillable from DB)** (optionally, with the --decorated flag it will create also a **decorator** and **middleware**) and will print instructions on what is left to be done manually.
26+
If connection is not the default one, it can be specified in the command argument.
27+
If table is not the plural snake cased resourceName, then it can be specified in the table argument.
28+
Run just **php artisan make:api-resource** for interactive mode that will try to guess the tableName and use default connectionName (except --decorated).
2629

2730
Example:
2831
```

src/Console/MakeLaravelCrudWizard.php

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use MacropaySolutions\LaravelCrudWizardGenerator\Services\MakeMiddlewareService;
99
use MacropaySolutions\LaravelCrudWizardGenerator\Services\MakeModelService;
1010
use MacropaySolutions\LaravelCrudWizardGenerator\Services\MakeServiceService;
11+
use Symfony\Component\Console\Input\InputInterface;
12+
use Symfony\Component\Console\Output\OutputInterface;
1113

1214
class MakeLaravelCrudWizard extends Command
1315
{
@@ -16,7 +18,7 @@ class MakeLaravelCrudWizard extends Command
1618
*
1719
* @var string
1820
*/
19-
protected $signature = 'make:api-resource {resourceName} {--decorated}';
21+
protected $signature = 'make:api-resource {resourceName} {--decorated} {--table=} {connectionName?}';
2022

2123
/**
2224
* The console command description.
@@ -25,6 +27,11 @@ class MakeLaravelCrudWizard extends Command
2527
*/
2628
protected $description = 'Make a resource template for laravel-crud-wizard';
2729

30+
private bool $ignoreError = false;
31+
private ?string $resourceName = null;
32+
private ?string $connection = null;
33+
private ?string $table = null;
34+
2835
public function __construct(
2936
protected MakeControllerService $makeControllerService,
3037
protected MakeModelService $makeModelService,
@@ -38,18 +45,68 @@ public function __construct(
3845
/**
3946
* Execute the console command.
4047
*/
41-
public function handle(): void
48+
public function handle(int $try = 0): void
4249
{
43-
$resourceName = $this->argument('resourceName');
44-
$this->makeModelService->makeCompleteModelFile($resourceName, $ns = $this->laravel->getNamespace());
45-
$this->makeServiceService->makeCompleteServiceFile($resourceName, $ns);
46-
$this->makeControllerService->makeCompleteControllerFile($resourceName, $ns);
50+
$this->resourceName ??= $this->argument('resourceName');
51+
$this->connection ??= $this->argument('connectionName');
52+
$this->table ??= $this->option('table');
53+
$columns = [];
54+
55+
try {
56+
$columns = $this->makeModelService->makeCompleteModelFile(
57+
$this->resourceName,
58+
$ns = $this->laravel->getNamespace(),
59+
$this->connection,
60+
$this->table,
61+
$this->ignoreError
62+
);
63+
} catch (\Throwable $e) {
64+
$this->resourceName ??= $this->ask('resourceName ?');
65+
$this->table ??= $this->ask('tableName ?');
66+
67+
if ($try === 2) {
68+
$this->connection ??= $this->ask('connectionName (blank for default) ?');
69+
}
70+
71+
if ($try <= 2) {
72+
$this->handle(++$try);
73+
74+
return;
75+
}
76+
77+
$this->error($e->getMessage());
78+
79+
if (!$this->ignoreError) {
80+
if ('n' === $this->ask($e->getMessage() . ', do you want to continue y/n?', 'n')) {
81+
return;
82+
}
83+
84+
$this->ignoreError = true;
85+
$this->handle(2);
86+
87+
return;
88+
}
89+
}
90+
91+
$this->makeServiceService->makeCompleteServiceFile($this->resourceName, $ns);
92+
$this->makeControllerService->makeCompleteControllerFile(
93+
$this->resourceName,
94+
$ns,
95+
\array_diff($columns, ['created_at', 'updated_at', 'id'])
96+
);
4797

4898
if (!$this->option('decorated')) {
4999
return;
50100
}
51101

52-
$this->makeDecoratorService->makeCompleteDecoratorFile($resourceName, $ns);
53-
$this->makeMiddlewareService->makeCompleteMiddlewareFile($resourceName, $ns);
102+
$this->makeDecoratorService->makeCompleteDecoratorFile($this->resourceName, $ns, $columns);
103+
$this->makeMiddlewareService->makeCompleteMiddlewareFile($this->resourceName, $ns);
104+
}
105+
106+
protected function interact(InputInterface $input, OutputInterface $output): void
107+
{
108+
if (!\is_string($input->getArgument('resourceName'))) {
109+
$input->setArgument('resourceName', $this->ask('resourceName ?'));
110+
}
54111
}
55112
}

src/Services/MakeControllerService.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,37 @@ public function __construct(
2020
$this->output = $consoleOutput;
2121
}
2222

23-
public function makeCompleteControllerFile(string $resourceName, string $laravelNamespace): void
23+
public function makeCompleteControllerFile(string $resourceName, string $laravelNamespace, array $columns): void
2424
{
2525
$this->createControllerFile(
26-
$this->replaceContentControllerStub($resourceName, $laravelNamespace),
26+
$this->replaceContentControllerStub($resourceName, $laravelNamespace, $columns),
2727
$resourceName
2828
);
2929
}
3030

31-
protected function replaceContentControllerStub(string $resourceName, string $laravelNamespace): string
32-
{
31+
protected function replaceContentControllerStub(
32+
string $resourceName,
33+
string $laravelNamespace,
34+
array $columns
35+
): string {
3336
return \str_replace([
3437
'DummyNamespace',
3538
'DummyService',
3639
'DummyClass',
40+
'DummyMapCreate',
41+
'DummyMapUpdate',
3742
], [
3843
\trim($laravelNamespace, '\\'),
39-
($plural = \ucfirst(Str::camel(Str::plural($resourceName)))) . 'Service',
44+
($plural = $this->pathsAndNamespacesService->pluralUcFirstCamelCase($resourceName)) . 'Service',
4045
$plural . 'Controller',
46+
' ' . \implode(",\n ", \array_map(
47+
fn(string $val): string => "'" . $val . "' => 'required'",
48+
$columns
49+
)),
50+
' ' . \implode(",\n ", \array_map(
51+
fn(string $val): string => "'" . $val . "' => 'sometimes|required'",
52+
$columns
53+
))
4154
], File::get($this->pathsAndNamespacesService->getControllerStubPath()));
4255
}
4356

src/Services/MakeDecoratorService.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,30 @@ public function __construct(
1818
$this->output = $consoleOutput;
1919
}
2020

21-
public function makeCompleteDecoratorFile(string $resourceName, string $laravelNamespace): void
21+
public function makeCompleteDecoratorFile(string $resourceName, string $laravelNamespace, array $columns): void
2222
{
23-
$this->createDecoratorFile($this->replaceContentDecoratorStub($resourceName, $laravelNamespace), $resourceName);
23+
$this->createDecoratorFile(
24+
$this->replaceContentDecoratorStub($resourceName, $laravelNamespace, $columns),
25+
$resourceName
26+
);
2427
}
2528

26-
protected function replaceContentDecoratorStub(string $resourceName, string $laravelNamespace): string
27-
{
29+
protected function replaceContentDecoratorStub(
30+
string $resourceName,
31+
string $laravelNamespace,
32+
array $columns
33+
): string {
2834
return \str_replace([
2935
'DummyNamespace',
3036
'DummyClass',
37+
'DummyMap',
3138
], [
3239
\trim($laravelNamespace, '\\'),
33-
\ucfirst(Str::camel(Str::singular($resourceName))) . 'Decorator',
40+
$this->pathsAndNamespacesService->singularUcFirstCamelCase($resourceName) . 'Decorator',
41+
' ' . \implode(",\n ", \array_map(
42+
fn(string $val): string => "'" . $val . "' => '" . Str::camel($val) . "'",
43+
$columns
44+
))
3445
], File::get($this->pathsAndNamespacesService->getDecoratorStubPath()));
3546
}
3647

src/Services/MakeMiddlewareService.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use Illuminate\Console\Concerns\InteractsWithIO;
66
use Illuminate\Contracts\Foundation\Application;
77
use Illuminate\Support\Facades\File;
8-
use Illuminate\Support\Str;
98
use Symfony\Component\Console\Output\ConsoleOutput;
109

1110
class MakeMiddlewareService
@@ -36,8 +35,8 @@ protected function replaceContentMiddlewareStub(string $resourceName, string $la
3635
'DummyClass',
3736
], [
3837
\trim($laravelNamespace, '\\'),
39-
\ucfirst(Str::camel(Str::singular($resourceName))),
40-
\ucfirst(Str::camel(Str::plural($resourceName))) . 'Middleware',
38+
$this->pathsAndNamespacesService->singularUcFirstCamelCase($resourceName),
39+
$this->pathsAndNamespacesService->pluralUcFirstCamelCase($resourceName) . 'Middleware',
4140
], File::get($this->pathsAndNamespacesService->getMiddlewareStubPath()));
4241
}
4342

src/Services/MakeModelService.php

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,75 @@ class MakeModelService
1111
{
1212
use InteractsWithIO;
1313

14+
private array $columns = [];
15+
1416
public function __construct(
1517
protected PathsAndNamespacesService $pathsAndNamespacesService,
1618
ConsoleOutput $consoleOutput,
1719
) {
1820
$this->output = $consoleOutput;
1921
}
2022

21-
public function makeCompleteModelFile(string $resourceName, string $laravelNamespace): void
22-
{
23-
$this->createModelFile($resourceName, $this->replaceContentModelStub($laravelNamespace, $resourceName));
23+
/**
24+
* @throws \Throwable
25+
*/
26+
public function makeCompleteModelFile(
27+
string $resourceName,
28+
string $laravelNamespace,
29+
?string $connection,
30+
?string $table,
31+
bool $ignoreError,
32+
): array {
33+
$this->createModelFile(
34+
$resourceName,
35+
$this->replaceContentModelStub($laravelNamespace, $resourceName, $connection, $table, $ignoreError)
36+
);
37+
38+
return $this->columns;
2439
}
2540

26-
protected function replaceContentModelStub(string $laravelNamespace, string $resourceName): string
27-
{
41+
/**
42+
* @throws \Throwable
43+
*/
44+
protected function replaceContentModelStub(
45+
string $laravelNamespace,
46+
string $resourceName,
47+
?string $connection,
48+
?string $table,
49+
bool $ignoreError,
50+
): string {
51+
$table ??= Str::snake(Str::camel($resourceName));
52+
53+
try {
54+
$fillable = ' ' . \implode(",\n ", \array_map(
55+
fn(string $val): string => "'" . $val . "'",
56+
$this->columns =
57+
\Illuminate\Support\Facades\Schema::connection($connection ?? \config('database.default'))
58+
->getColumnListing($table)
59+
));
60+
} catch (\Throwable $e) {
61+
$this->error($e->getMessage());
62+
$fillable = "\n 'created_at',\n 'updated_at',";
63+
}
64+
65+
if (!$ignoreError && $fillable === ' ') {
66+
throw new \Exception('Could not auto-populate fillable');
67+
}
68+
2869
return \str_replace([
2970
'DummyNamespace',
3071
'DummyResourceName',
3172
'DummyTableName',
3273
'DummyClass',
74+
'DummyFillable',
75+
'DummyConnection',
3376
], [
3477
\trim($laravelNamespace, '\\'),
35-
Str::snake(Str::plural($resourceName), '-'),
36-
Str::snake(Str::plural($resourceName)),
37-
\ucfirst(Str::camel(Str::singular($resourceName))),
78+
$resourceName,
79+
$table,
80+
$this->pathsAndNamespacesService->singularUcFirstCamelCase($resourceName),
81+
$fillable,
82+
(string)$connection !== '' ? ' protected $connection = \'' . $connection . '\';' : '',
3883
], File::get($this->pathsAndNamespacesService->getModelStubPath()));
3984
}
4085

src/Services/MakeServiceService.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Illuminate\Console\Concerns\InteractsWithIO;
66
use Illuminate\Support\Facades\File;
7-
use Illuminate\Support\Str;
87
use Symfony\Component\Console\Output\ConsoleOutput;
98

109
class MakeServiceService
@@ -31,8 +30,8 @@ protected function replaceContentServiceStub(string $resourceName, string $larav
3130
'DummyClass',
3231
], [
3332
\trim($laravelNamespace, '\\'),
34-
\ucfirst(Str::camel(Str::singular($resourceName))),
35-
\ucfirst(Str::camel(Str::plural($resourceName))) . 'Service',
33+
$this->pathsAndNamespacesService->singularUcFirstCamelCase($resourceName),
34+
$this->pathsAndNamespacesService->pluralUcFirstCamelCase($resourceName) . 'Service',
3635
], File::get($this->pathsAndNamespacesService->getServiceStubPath()));
3736
}
3837

src/Services/PathsAndNamespacesService.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function getRealpathBaseModel(): string
4949
public function getRealpathBaseCustomModel(string $resourceName): string
5050
{
5151
return $this->getRealpathBaseModel() . DIRECTORY_SEPARATOR .
52-
\ucfirst(Str::camel(Str::singular($resourceName))) . '.php';
52+
$this->singularUcFirstCamelCase($resourceName) . '.php';
5353
}
5454

5555
public function getRealpathBaseService(): string
@@ -60,7 +60,7 @@ public function getRealpathBaseService(): string
6060
public function getRealpathBaseCustomService(string $resourceName): string
6161
{
6262
return $this->getRealpathBaseService() . DIRECTORY_SEPARATOR .
63-
\ucfirst(Str::camel(Str::plural($resourceName))) . 'Service.php';
63+
$this->pluralUcFirstCamelCase($resourceName) . 'Service.php';
6464
}
6565

6666
public function getRealpathBaseController(): string
@@ -71,7 +71,7 @@ public function getRealpathBaseController(): string
7171
public function getRealpathBaseCustomController(string $resourceName): string
7272
{
7373
return $this->getRealpathBaseController() . DIRECTORY_SEPARATOR .
74-
\ucfirst(Str::camel(Str::plural($resourceName))) . 'Controller.php';
74+
$this->pluralUcFirstCamelCase($resourceName) . 'Controller.php';
7575
}
7676

7777
public function getRealpathBaseDecorator(): string
@@ -82,7 +82,7 @@ public function getRealpathBaseDecorator(): string
8282
public function getRealpathBaseCustomDecorator(string $resourceName): string
8383
{
8484
return $this->getRealpathBaseDecorator() . DIRECTORY_SEPARATOR .
85-
\ucfirst(Str::camel(Str::singular($resourceName))) . 'Decorator.php';
85+
$this->singularUcFirstCamelCase($resourceName) . 'Decorator.php';
8686
}
8787

8888
public function getRealpathBaseMiddleware(): string
@@ -94,6 +94,23 @@ public function getRealpathBaseMiddleware(): string
9494
public function getRealpathBaseCustomMiddleware(string $resourceName): string
9595
{
9696
return $this->getRealpathBaseMiddleware() . DIRECTORY_SEPARATOR .
97-
\ucfirst(Str::camel(Str::plural($resourceName))) . 'Middleware.php';
97+
$this->pluralUcFirstCamelCase($resourceName) . 'Middleware.php';
98+
}
99+
100+
public function singularUcFirstCamelCase(string $resourceName): string
101+
{
102+
static $result;
103+
104+
return $result[$resourceName] ??= \ucfirst(Str::camel(\implode(
105+
'-',
106+
\array_map(fn(string $value): string => Str::singular($value), \explode('-', $resourceName))
107+
)));
108+
}
109+
110+
public function pluralUcFirstCamelCase(string $resourceName): string
111+
{
112+
static $result;
113+
114+
return $result[$resourceName] ??= \ucfirst(Str::camel($resourceName));
98115
}
99116
}

0 commit comments

Comments
 (0)