Issues (18)

src/Concerns/EnumTraits.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace BiiiiiigMonster\LaravelEnum\Concerns;
4
5
use BackedEnum;
6
use BiiiiiigMonster\LaravelEnum\Attributes\DefaultCase;
7
use BiiiiiigMonster\LaravelEnum\Contracts\Localizable;
8
use BiiiiiigMonster\LaravelEnum\Exceptions\MetaValueError;
9
use BiiiiiigMonster\LaravelEnum\Exceptions\UndefinedCaseException;
10
use Illuminate\Support\Arr;
11
use Illuminate\Support\Collection;
12
use ReflectionEnumUnitCase;
13
use UnitEnum;
14
use ValueError;
15
16
/**
17
 * @mixin UnitEnum
18
 */
19
trait EnumTraits
20
{
21
    public static function names(): array
22
    {
23
        return array_column(static::cases(), 'name');
24
    }
25
26
    public static function values(): array
27
    {
28
        if (! is_subclass_of(static::class, BackedEnum::class)) {
29
            return static::names();
30
        }
31
32
        return array_column(static::cases(), 'value');
33
    }
34
35
    public static function options(): array
36
    {
37
        $keys = collect(static::cases())
38
            ->map(fn (UnitEnum $case) => /** @var static $case */ $case());
39
40
        $values = collect(static::cases())
41
            ->map(fn (UnitEnum $case) => /** @var static $case */ $case->label());
42
43
        return $keys->combine($values)->all();
44
    }
45
46
    public static function tables(): array
47
    {
48
        $tables = collect(static::cases())
49
            ->map(fn (UnitEnum $case) => /** @var static $case */ $case->rows());
50
51
        $allKeys = $tables->collapse()->map(fn () => null);
52
53
        return $tables
54
            ->map(fn ($map) => $allKeys->merge($map)->all())
55
            ->all();
56
    }
57
58
    public static function from($name): static
59
    {
60
        return static::fromName((string) $name);
61
    }
62
63
    public static function tryFrom($name): ?static
0 ignored issues
show
A parse error occurred: Syntax error, unexpected T_STATIC on line 63 at column 44
Loading history...
64
    {
65
        return static::tryFromName((string) $name);
66
    }
67
68
    public static function fromName(string $name): static
69
    {
70
        return static::tryFromName($name) ?? throw new ValueError(
71
            '"'.$name.'" is not a valid name for enum "'.static::class.'"'
72
        );
73
    }
74
75
    public static function tryFromName(string $name): ?static
76
    {
77
        return collect(static::cases())
78
            ->first(fn (UnitEnum $case) => $case->name === $name);
79
    }
80
81
    public static function fromMeta(mixed $value, string $method = null): static
82
    {
83
        return static::tryFromMeta($value, $method)
84
            ?? throw new MetaValueError(static::class, $value, $method);
85
    }
86
87
    public static function tryFromMeta(mixed $value, string $method = null): ?static
88
    {
89
        if ($value instanceof Meta) {
90
            $method = $value::method();
91
            $value = $value->value;
92
        }
93
94
        return collect(static::cases())
95
            ->first(fn (UnitEnum $case) =>
96
                /** @var static $case */
97
                collect($case->metas())
98
                    ->contains(fn (Meta $attr) => $attr::method() === $method
99
                        && $attr->value === $value)
100
            );
101
    }
102
103
    public static function random(): ?static
104
    {
105
        if (empty($cases = static::cases())) {
106
            return null;
107
        }
108
109
        return Arr::random($cases);
110
    }
111
112
    public static function default(): ?static
113
    {
114
        return collect(static::cases())
115
            ->first(fn (UnitEnum $case) => /** @var static $case */ $case->isDefault());
116
    }
117
118
    /**
119
     * @return Meta[]
120
     */
121
    public function metas(): array
122
    {
123
        $metas = [];
124
125
        $rfe = new ReflectionEnumUnitCase($this, $this->name);
126
        foreach ($rfe->getAttributes() as $attribute) {
127
            $instance = $attribute->newInstance();
128
            if ($instance instanceof Meta) {
129
                $metas[] = $instance;
130
            }
131
        }
132
133
        return $metas;
134
    }
135
136
    public function rows(): array
137
    {
138
        return collect($this->metas())
139
            ->flatMap(fn (Meta $meta) => [$meta::method() => $meta->value])
140
            ->merge(['name' => $this->name])
141
            ->when($this instanceof BackedEnum,
142
                fn (Collection $collection) => $collection
143
                    ->merge(['value' => $this->value])
144
            )
145
            ->all();
146
    }
147
148
    public function getLocalizationKey(): string
149
    {
150
        return 'enums.'.static::class.'.'.$this();
151
    }
152
153
    public function label(): string
154
    {
155
        return $this instanceof Localizable
156
            ? trans($this->getLocalizationKey())
157
            : str($this->name)->lower()->studly();
158
    }
159
160
    public function isDefault(): bool
161
    {
162
        $rfe = new ReflectionEnumUnitCase($this, $this->name);
163
        foreach ($rfe->getAttributes() as $attribute) {
164
            if ($attribute->getName() === DefaultCase::class) {
165
                return true;
166
            }
167
        }
168
169
        return false;
170
    }
171
172
    public function __invoke(): int|string
173
    {
174
        return $this instanceof BackedEnum ? $this->value : $this->name;
175
    }
176
177
    public function __call(string $property, $arguments): mixed
178
    {
179
        return collect($this->metas())
180
            ->first(fn (Meta $attr) => $attr::method() === $property)
181
            ?->value;
182
    }
183
184
    /**
185
     * @throws UndefinedCaseException
186
     */
187
    public static function __callStatic($name, $args): int|string
188
    {
189
        $case = collect(static::cases())
190
            ->first(fn (UnitEnum $case) => $case->name === $name)
191
            ?? throw new UndefinedCaseException(static::class, $name);
192
193
        return $case();
194
    }
195
}
196