TypeHintReader::getParameter()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 2
dl 0
loc 11
ccs 5
cts 5
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Thr;
4
5
/**
6
 * Class TypeHintReader
7
 * @package Thr
8
 */
9
class TypeHintReader implements TypeReader
10
{
11
    private $class;
12
13
    /**
14
     * TypeHintReader constructor.
15
     * @param \ReflectionClass $class
16
     */
17 48
    public function __construct(\ReflectionClass $class)
18
    {
19 48
        $this->class = $class;
20 48
    }
21
22
    /**
23
     * {@inheritdoc}
24
     */
25 48
    public function getReflectionType(string $propertyName): \ReflectionType
26
    {
27 48
        $reflectionType = $this->getReflectionParameter($propertyName)
28 45
            ->getType();
29 45
        if ($reflectionType === null) {
30 3
            throw TypeHintReaderException::withoutTypeHint($propertyName);
31
        }
32
33 42
        return $reflectionType;
34
    }
35
36 48
    private function getReflectionParameter(
37
        string $propertyName
38
    ): \ReflectionParameter {
39 48
        return $this->getReflectionPropertyBySetter($propertyName)
40 48
            ?? $this->getReflectionPropertyByConstruct($propertyName);
41
    }
42
43 48
    private function getReflectionPropertyBySetter(
44
        string $propertyName
45
    ): ?\ReflectionParameter {
46 48
        $nameSetter = 'set'.ucfirst($propertyName);
47 48
        if ($this->class->hasMethod($nameSetter)) {
48 24
            $methodSetter = $this->class->getMethod($nameSetter);
49 24
            return $methodSetter->getParameters()[0];
50
        }
51
52 30
        return null;
53
    }
54
55 30
    private function getReflectionPropertyByConstruct(
56
        string $propertyName
57
    ): \ReflectionParameter {
58 30
        $constructor = $this->class->getConstructor();
59 30
        $parameter = $this->getParameter($propertyName, $constructor);
60
61 30
        if ($parameter instanceof \ReflectionParameter) {
62 27
            return $parameter;
63
        }
64
65 3
        throw TypeHintReaderException::invalidPropertyName($propertyName);
66
    }
67
68 30
    private function getParameter(
69
        string $propertyName,
70
        \ReflectionMethod $constructor
71
    ): ?\ReflectionParameter {
72 30
        foreach ($constructor->getParameters() as $parameter) {
73 30
            if ($parameter->getName() === $propertyName) {
74 30
                return $parameter;
75
            }
76
        }
77
78 3
        return null;
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84 42
    public function getTypeName(string $propertyName): string
85
    {
86 42
        return $this->getReflectionType($propertyName)->getName();
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92 3
    public function typeAllowNull(string $propertyName): bool
93
    {
94 3
        return $this->getReflectionType($propertyName)->allowsNull();
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100 3
    public function typeIsBuiltin(string $propertyName): bool
101
    {
102 3
        return $this->getReflectionType($propertyName)->isBuiltin();
103
    }
104
105
    /**
106
     * @param string $class
107
     * @return TypeHintReader
108
     * @throws TypeHintReaderException
109
     * @throws \ReflectionException
110
     */
111 33
    public static function byClassName(string $class): self
112
    {
113 33
        if (!class_exists($class)) {
114 3
            throw TypeHintReaderException::notExistsClass($class);
115
        }
116
117 30
        return new self(new \ReflectionClass($class));
118
    }
119
}
120