1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Cerbero\LaravelEnum\Commands; |
6
|
|
|
|
7
|
|
|
use Cerbero\Enum\Enums\Backed; |
8
|
|
|
use Cerbero\LaravelEnum\Services\Generator; |
9
|
|
|
use Illuminate\Console\Command; |
10
|
|
|
use Symfony\Component\Console\Exception\InvalidArgumentException; |
11
|
|
|
|
12
|
|
|
use function Cerbero\LaravelEnum\output; |
13
|
|
|
use function Cerbero\LaravelEnum\runAnnotate; |
14
|
|
|
use function Cerbero\LaravelEnum\runTs; |
15
|
|
|
use function Laravel\Prompts\select; |
16
|
|
|
use function Laravel\Prompts\text; |
17
|
|
|
use function Laravel\Prompts\textarea; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* The console command to create enums. |
21
|
|
|
*/ |
22
|
|
|
final class EnumMakeCommand extends Command |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* The console command description. |
26
|
|
|
* |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
protected $description = 'Create a new enum'; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* The name and signature of the console command. |
33
|
|
|
* |
34
|
|
|
* @var string |
35
|
|
|
*/ |
36
|
|
|
protected $signature = 'enum:make |
37
|
|
|
{enum? : The namespace of the enum} |
38
|
|
|
{cases?* : The names of the enum cases} |
39
|
|
|
{--b|backed= : How cases should be backed} |
40
|
|
|
{--f|force : Whether the existing enum should be overwritten} |
41
|
|
|
{--t|typescript : Whether the TypeScript enum should be created too}'; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Handle the command. |
45
|
|
|
*/ |
46
|
6 |
|
public function handle(): int |
47
|
|
|
{ |
48
|
6 |
|
$enum = $this->enum(); |
49
|
6 |
|
$force = !! $this->option('force'); |
50
|
|
|
|
51
|
6 |
|
if (enum_exists($enum) && ! $force) { |
52
|
1 |
|
$this->info("The enum {$enum} already exists."); |
53
|
|
|
|
54
|
1 |
|
return self::SUCCESS; |
55
|
|
|
} |
56
|
|
|
|
57
|
5 |
|
if (! $backed = $this->backed()) { |
58
|
1 |
|
$this->error('The option --backed supports only ' . implode(', ', Backed::names())); |
59
|
|
|
|
60
|
1 |
|
return self::FAILURE; |
61
|
|
|
} |
62
|
|
|
|
63
|
4 |
|
return $this->generate($enum, $backed); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Retrieve the enum namespace. |
68
|
|
|
* |
69
|
|
|
* @return class-string<\UnitEnum> |
|
|
|
|
70
|
|
|
*/ |
71
|
6 |
|
private function enum(): string |
72
|
|
|
{ |
73
|
|
|
/** @var string $raw */ |
74
|
6 |
|
$raw = $this->argument('enum') ?: text('The namespace of the enum', 'App\Enums\Permissions', required: true); |
75
|
|
|
|
76
|
|
|
/** @var class-string<\UnitEnum> */ |
77
|
6 |
|
return strtr($raw, '/', '\\'); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Retrieve the selected backed case, if any. |
82
|
|
|
* |
83
|
|
|
* @throws InvalidArgumentException |
84
|
|
|
*/ |
85
|
5 |
|
private function backed(): ?Backed |
86
|
|
|
{ |
87
|
5 |
|
if ($this->argument('enum') === null) { |
88
|
|
|
/** @phpstan-ignore argument.templateType */ |
89
|
1 |
|
$options = Backed::pluck('label', 'name'); |
90
|
|
|
/** @var array<string, string> $options */ |
91
|
1 |
|
$name = select('How cases should be backed', $options); |
92
|
|
|
|
93
|
|
|
/** @var string $name */ |
94
|
1 |
|
return Backed::from($name); |
95
|
|
|
} |
96
|
|
|
|
97
|
4 |
|
if (is_null($name = $this->option('backed'))) { |
98
|
1 |
|
return Backed::pure; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** @var string $name */ |
102
|
3 |
|
return Backed::tryFrom($name); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* Generate the enum. |
107
|
|
|
* |
108
|
|
|
* @param class-string<\UnitEnum> $enum |
|
|
|
|
109
|
|
|
*/ |
110
|
4 |
|
private function generate(string $enum, Backed $backed): int |
111
|
|
|
{ |
112
|
4 |
|
$generator = new Generator($enum, $this->cases($backed), $backed); |
113
|
4 |
|
$force = !! $this->option('force'); |
114
|
4 |
|
$typeScript = !! $this->option('typescript'); |
115
|
|
|
|
116
|
4 |
|
$succeeded = output($this->output, $enum, function () use ($generator, $enum, $force, $typeScript) { |
117
|
4 |
|
return $generator->generate($force) |
118
|
4 |
|
&& runAnnotate($enum, $force) |
119
|
4 |
|
&& ($typeScript ? runTs($enum, $force) : true); |
120
|
4 |
|
}); |
121
|
|
|
|
122
|
4 |
|
return $succeeded ? self::SUCCESS : self::FAILURE; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Retrieve the cases, optionally backed. |
127
|
|
|
* |
128
|
|
|
* @return string[] |
129
|
|
|
*/ |
130
|
4 |
|
private function cases(Backed $backed): array |
131
|
|
|
{ |
132
|
4 |
|
$placeholder = $backed->is(Backed::custom) ? "Case1=value1\nCase2=value2" : "Case1\nCase2"; |
133
|
|
|
|
134
|
|
|
/** @var list<string> */ |
135
|
4 |
|
return $this->argument('cases') |
136
|
4 |
|
?: explode(PHP_EOL, trim(textarea('The cases (one per line)', $placeholder, required: true))); |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
|