Passed
Push — master ( 0ad537...62a59e )
by Enea
12:21 queued 12s
created

Enum::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 3
c 1
b 0
f 1
nc 2
nop 1
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
/**
3
 * Created by enea dhack - 08/07/2020 16:59.
4
 */
5
6
namespace Vaened\Enum;
7
8
use BadMethodCallException;
9
use ReflectionClass;
10
use Stringable;
11
use UnexpectedValueException;
12
use function array_reduce;
13
14
abstract class Enum implements Enumerable, Stringable
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_ENUM, expecting T_STRING on line 14 at column 15
Loading history...
15
{
16
    private string|int|float|bool $value;
17
18
    private static array $attributes = [];
19
20 20
    private static array $cache = [];
21
22 20
    final private function __construct(string|int|float|bool $value)
23 2
    {
24
        if (! self::isValid($value)) {
25
            throw new UnexpectedValueException("Value '$value' is not part of the enum " . static::class);
26 18
        }
27 18
28
        $this->value = $value;
29 20
    }
30
31 20
    public static function create(string|int|float|bool $value): static
32
    {
33
        return new static($value);
34 4
    }
35
36 4
    public static function instantiate(string $key): static
37
    {
38 4
        $values = static::associates();
39 2
40
        if (! isset($values[$key])) {
41
            throw new UnexpectedValueException("Key '$key' is not part of the enum " . static::class);
42 2
        }
43
44
        return static::create($values[$key]);
45 22
    }
46
47 22
    public static function isValid(string|int|float|bool $value): bool
48
    {
49
        return in_array($value, static::associates(), true);
50 2
    }
51
52 2
    public static function values(): array
53
    {
54
        return array_map(static fn(string|int|float|bool $value) => static::create($value), static::associates());
55 26
    }
56
57 26
    private static function associates(): array
58 26
    {
59
        $classname = static::class;
60
        return self::$cache[$classname] ??= static::getConstantsFrom($classname);
61 2
    }
62
63 2
    private static function getConstantsFrom(string $classname): array
64
    {
65
        return (new ReflectionClass($classname))->getConstants();
66 2
    }
67
68 2
    private static function getEnumAttributes(): array
69
    {
70
        return self::$attributes[static::class] ??= static::bindEnumAttributes();
71 2
    }
72
73
    private static function bindEnumAttributes(): array
74 2
    {
75 2
        return array_reduce(static::attributes(), static function (array $acc, Attributor $attribute): array {
76 2
            $acc[$attribute->getCase()] = $attribute->getAttributes();
77
            return $acc;
78
        }, []);
79
    }
80
81
    protected static function attributes(): array
82
    {
83
        return [];
84 12
    }
85
86 12
    public function value(): string|int|float|bool
87
    {
88
        return $this->value;
89 10
    }
90
91 10
    public function key(): string
92
    {
93
        return array_search($this->value, static::associates(), true);
94 2
    }
95
96 2
    public function equals(string|int|float|bool $value): bool
97
    {
98
        return $this->value() === $value;
99 2
    }
100
101 2
    protected function attribute(string $name): mixed
102 2
    {
103 2
        $constants = static::getEnumAttributes();
104
        $attributes = $constants[$this->key()] ?? [];
105
        return $attributes[$name] ?? null;
106 14
    }
107
108 14
    public static function __callStatic(string $name, array $arguments): self
109
    {
110 14
        $values = static::associates();
111 12
112
        if (isset($values[$name])) {
113
            return static::create($values[$name]);
114 2
        }
115
116
        throw new BadMethodCallException("No static method or enum constant '$name' in enum " . static::class);
117 2
    }
118
119 2
    public function __toString(): string
120
    {
121
        return $this->value();
122
    }
123
}
124
125