Passed
Push — develop ( 9b8c4e...79e7ae )
by Andrea Marco
03:34 queued 14s
created

EnumMakeCommand::cases()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 3
rs 10
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>
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<\UnitEnum> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<\UnitEnum>.
Loading history...
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
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<\UnitEnum> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<\UnitEnum>.
Loading history...
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