Passed
Push — feature/second-release ( e64b84...683aeb )
by Andrea Marco
02:47
created

EnumMakeCommand::backed()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 13
ccs 7
cts 7
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) {
0 ignored issues
show
Bug introduced by
The function enum_exists was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
        if (/** @scrutinizer ignore-call */ enum_exists($enum) && ! $force) {
Loading history...
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
        $generator = new Generator($enum, $this->cases($backed), $backed);
64 4
        $typeScript = !! $this->option('typescript');
65
66 4
        $succeeded = output($this->output, $enum, function() use ($generator, $enum, $force, $typeScript) {
67 4
            return $generator->generate($force)
68 4
                && runAnnotate($enum, $force)
69 4
                && ($typeScript ? runTs($enum, $force) : true);
70 4
        });
71
72 4
        return $succeeded ? self::SUCCESS : self::FAILURE;
73
    }
74
75
    /**
76
     * Retrieve the enum namespace.
77
     *
78
     * @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...
79
     */
80 6
    private function enum(): string
81
    {
82 6
        $raw = $this->argument('enum') ?: text('The namespace of the enum', 'App\Enums\Permissions', required: true);
83
84 6
        return strtr((string) $raw, '/', '\\');
85
    }
86
87
    /**
88
     * Retrieve the selected backed case, if any.
89
     *
90
     * @throws InvalidArgumentException
91
     */
92 5
    private function backed(): ?Backed
93
    {
94 5
        if ($this->argument('enum') === null) {
95 1
            $name = select('How cases should be backed', Backed::pluck('label', 'name'));
96
97 1
            return Backed::from($name);
98
        }
99
100 4
        if (is_null($name = $this->option('backed'))) {
0 ignored issues
show
introduced by
The condition is_null($name = $this->option('backed')) is always false.
Loading history...
101 1
            return Backed::pure;
102
        }
103
104 3
        return Backed::tryFrom($name);
105
    }
106
107
    /**
108
     * Retrieve the cases, optionally backed.
109
     *
110
     * @return string[]
111
     */
112 4
    private function cases(Backed $backed): array
113
    {
114 4
        $placeholder = $backed->is(Backed::custom) ? "Case1=value1\nCase2=value2" : "Case1\nCase2";
115
116
        /** @var list<string> $cases */
117 4
        return $this->argument('cases')
118 4
            ?: explode(PHP_EOL, trim(textarea('The cases (one per line)', $placeholder, required: true)));
119
    }
120
}
121