Passed
Branch 7.x (a5d545)
by Adrien
05:06
created

SplReflectionEnumProxy   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 34
c 2
b 0
f 1
dl 0
loc 139
ccs 0
cts 31
cp 0
rs 10
wmc 16

6 Methods

Rating   Name   Duplication   Size   Complexity  
A isBacked() 0 14 5
A getConstants() 0 3 1
A getReflectionConstant() 0 3 2
A __construct() 0 4 1
A getName() 0 3 1
A getBackingType() 0 22 6
1
<?php
2
3
/**
4
 * Part of SplTypes package.
5
 *
6
 * (c) Adrien Loyant <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Ducks\Component\SplTypes\Reflection;
15
16
use Ducks\Component\SplTypes\SplBackedEnum;
17
use Ducks\Component\SplTypes\SplUnitEnum;
18
19
final class SplReflectionEnumProxy
20
{
21
    use Proxy\ConstantCaseCollectionTrait;
22
    use Proxy\EnumCaseCollectionTrait;
23
24
    /**
25
     * The reflection class used in proxy
26
     *
27
     * @var \ReflectionClass
28
     *
29
     * @phpstan-var \ReflectionClass<object>
30
     */
31
    private \ReflectionClass $class;
32
33
    /**
34
     * Is enum is backed
35
     *
36
     * @var boolean|null
37
     */
38
    private ?bool $backed = null;
39
40
    /**
41
     * Will be used to set backingType.
42
     *
43
     * @var \ReflectionNamedType|null|false
44
     */
45
    private $backingType = null;
46
47
    /**
48
     * Name of the class constant.
49
     *
50
     * @var string
51
     *
52
     * @readonly
53
     *
54
     * @phpstan-var class-string
55
     *
56
     * @psalm-readonly
57
     *
58
     * @phan-read-only
59
     */
60
    public string $name;
61
62
    /**
63
     * Build a proxy SplReflectionEnum from a ReflectionClass
64
     *
65
     * @param \ReflectionClass<object> $class
66
     */
67
    public function __construct(\ReflectionClass $class)
68
    {
69
        $this->class = $class;
70
        $this->name = $class->getName();
71
    }
72
73
    /**
74
     * Name of the class constant.
75
     *
76
     * @return string
77
     */
78
    public function getName(): string
79
    {
80
        return $this->name;
81
    }
82
83
    /**
84
     * Gets constants.
85
     *
86
     * @return mixed[] An array of constants,
87
     * where the keys hold the name and the values the value of the constants.
88
     *
89
     * @phpstan-return array<string, mixed>
90
     */
91
    public function getConstants(): array
92
    {
93
        return $this->class->getConstants();
94
    }
95
96
    /**
97
     * Gets a ReflectionClassConstant for a class's property
98
     *
99
     * @param string $name The class constant name.
100
     *
101
     * @return \ReflectionClassConstant|null
102
     */
103
    public function getReflectionConstant(string $name): ?\ReflectionClassConstant
104
    {
105
        return $this->class->getReflectionConstant($name) ?: null;
106
    }
107
108
    /**
109
     * Determines if an Enum is a Backed Enum
110
     *
111
     * @return boolean
112
     */
113
    public function isBacked(): bool
114
    {
115
        if (null === $this->backed) {
116
            if (\is_a($this->name, SplBackedEnum::class, true)) {
117
                $this->backed = true;
118
            } elseif (\is_a($this->name, SplUnitEnum::class, true)) {
119
                $this->backed = false;
120
            } else {
121
                $constant = $this->getFirstCaseConstant();
122
                $this->backed = $constant instanceof \ReflectionClassConstant && null !== $constant->getValue();
123
            }
124
        }
125
126
        return $this->backed;
127
    }
128
129
    /**
130
     * Gets the backing type of an Enum, if any
131
     *
132
     * @return \ReflectionNamedType|null An instance of ReflectionNamedType, or null if the Enum has no backing type.
133
     *
134
     * @link https://www.php.net/manual/en/reflectionenum.getbackingtype.php
135
     */
136
    public function getBackingType(): ?\ReflectionNamedType
137
    {
138
        if (null === $this->backingType) {
139
            if ($this->isBacked()) {
140
                if ($this->class->hasProperty('value')) {
141
                    /** @var \ReflectionNamedType|false $type */
142
                    $type = $this->class->getProperty('value')->getType() ?? false;
143
                    $this->backingType = $type;
144
                } else {
145
                    $constant = $this->getFirstCaseConstant();
146
                    if ($constant instanceof \ReflectionClassConstant) {
147
                        $this->backingType = SplReflectionEnumHelper::getReflectionNamedTypeFromType(
148
                            \gettype($constant->getValue())
149
                        );
150
                    }
151
                }
152
            } else {
153
                $this->backingType = false;
154
            }
155
        }
156
157
        return $this->backingType ?: null;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->backingType ?: null could return the type true which is incompatible with the type-hinted return ReflectionNamedType|null. Consider adding an additional type-check to rule them out.
Loading history...
158
    }
159
}
160