SplReflectionEnumUnitCase::getEnumValue()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 11
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 19
ccs 0
cts 11
cp 0
crap 12
rs 9.9
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\SplUnitEnum;
17
18
/**
19
 * The SplReflectionEnumUnitCase class reports information about an SplEnum unit case, which has no scalar equivalent.
20
 *
21
 * @property-read class-string<\Ducks\Component\SplTypes\SplEnumerable> $class
22
 *
23
 * @psalm-api
24
 * @psalm-immutable
25
 * @psalm-suppress PropertyNotSetInConstructor
26
 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<\Ducks\Comp...SplTypes\SplEnumerable> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<\Ducks\Component\SplTypes\SplEnumerable>.
Loading history...
27
class SplReflectionEnumUnitCase extends \ReflectionClassConstant
28
{
29
    /**
30
     * Internal instances enum
31
     *
32
     * @var array[]
33
     *
34
     * @phpstan-var array<string,array<string,SplUnitEnum>>
35
     */
36
    private static array $instances = [];
37
38
    /**
39
     * Instantiates a SplReflectionEnumUnitCase object
40
     *
41
     * @param object|string $class An enum instance or a name.
42
     * @param string $constant An enum constant name.
43
     *
44
     * @throws \ReflectionException if $class is not a \Ducks\Component\SplTypes\SplEnumerable interface.
45
     * @throws \ReflectionException in case the given class constant case does not exist.
46
     * @throws \ReflectionException if $constant is not a case.
47
     *
48
     * @phpcs:ignore Generic.Files.LineLength.TooLong
49
     * @phpstan-param \Ducks\Component\SplTypes\SplEnumerable|class-string<\Ducks\Component\SplTypes\SplEnumerable> $class An enum instance or a name.
50
     * @phpstan-param string $constant An enum constant name.
51
     *
52
     * @psalm-suppress UninitializedProperty
53
     * @psalm-suppress ImpureMethodCall
54
     *
55
     * @link https://www.php.net/manual/en/reflectionenumunitcase.construct.php
56
     */
57
    public function __construct($class, string $constant)
58
    {
59
        parent::__construct($class, $constant);
60
61
        if (!$this->getEnum()->hasCase($constant)) {
62
            /** @psalm-suppress PossiblyNullOperand */
63
            throw new \ReflectionException(
64
                'Enum case ' . $this->class . '::' . $this->name . ' is not a case'
65
            );
66
        }
67
    }
68
69
    /**
70
     * Gets the reflection of the enum of this case
71
     *
72
     * @return SplReflectionEnum instance describing the Enum this case belongs to.
73
     *
74
     * @throws \ReflectionException if objectOrClass is not a \Ducks\Component\SplTypes\SplEnumerable
75
     *
76
     * @phpstan-return SplReflectionEnum<\Ducks\Component\SplTypes\SplEnumerable>
77
     *
78
     * @psalm-suppress ArgumentTypeCoercion Needed because we need to throw Error on wrong type
79
     *
80
     * @see SplReflectionEnum::__construct()
81
     * @link https://www.php.net/manual/en/reflectionenumunitcase.getenum.php
82
     */
83
    public function getEnum(): SplReflectionEnum
84
    {
85
        /** @var SplReflectionEnum<\Ducks\Component\SplTypes\SplEnumerable> */
86
        return new SplReflectionEnum($this->class);
87
    }
88
89
    /**
90
     * Gets the enum case object described by this reflection object
91
     *
92
     * @return SplUnitEnum The enum case object described by this reflection object.
93
     *
94
     * @psalm-suppress MoreSpecificReturnType
95
     * @psalm-suppress LessSpecificReturnStatement
96
     * @psalm-suppress ImpureMethodCall
97
     * @psalm-suppress ImpureStaticProperty
98
     */
99
    public function getValue(): SplUnitEnum
100
    {
101
        if (!isset(self::$instances[$this->class][$this->name])) {
102
            self::$instances[$this->class][$this->name] = $this->getEnumValue();
103
        }
104
105
        return self::$instances[$this->class][$this->name];
106
    }
107
108
    /**
109
     * Gets the enum from the class and constant name.
110
     *
111
     * @return SplUnitEnum
112
     *
113
     * @psalm-suppress ImpureMethodCall
114
     */
115
    private function getEnumValue(): SplUnitEnum
116
    {
117
        $class = $this->getDeclaringClass();
118
        /** @var SplUnitEnum $instance */
119
        $instance = $class->newInstanceWithoutConstructor();
120
121
        $object = $class->getConstructor();
122
        if ($object instanceof \ReflectionMethod) {
123
            $object->setAccessible(true);
124
            $object->invoke($instance);
125
126
            if ($class->hasProperty('name')) {
127
                $property = $class->getProperty('name');
128
                $property->setAccessible(true);
129
                $property->setValue($instance, $this->name);
130
            }
131
        }
132
133
        return $instance;
134
    }
135
}
136