Completed
Push — master ( 02745e...0cb812 )
by Valentin
07:17
created

Methods::packParams()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Cycle\ORM\Promise\Declaration\Extractor;
5
6
use PhpParser\Builder\Param;
7
use PhpParser\Node;
8
9
final class Methods
10
{
11
    private const MAGIC_METHOD_NAMES = [
12
        '__construct',
13
        '__destruct',
14
        '__call',
15
        '__callstatic',
16
        '__get',
17
        '__set',
18
        '__isset',
19
        '__unset',
20
        '__sleep',
21
        '__wakeup',
22
        '__toString',
23
        '__invoke',
24
        '__set_state',
25
        '__clone',
26
        '__debuginfo',
27
    ];
28
29
    public function getMethods(\ReflectionClass $reflection): array
30
    {
31
        $methods = [];
32
33
        foreach ($reflection->getMethods() as $method) {
34
            if ($this->isIgnoredMethod($method)) {
35
                continue;
36
            }
37
38
            $methods[] = new Node\Stmt\ClassMethod($method->getName(), [
0 ignored issues
show
Bug introduced by
Consider using $method->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
39
                'flags'      => $this->packFlags($method),
40
                'returnType' => $this->defineReturnType($method),
41
                'params'     => $this->packParams($method),
42
                'byRef'      => $method->returnsReference()
43
            ]);
44
        }
45
46
        return $methods;
47
    }
48
49
    private function isIgnoredMethod(\ReflectionMethod $method): bool
50
    {
51
        return $method->isPrivate() || $method->isStatic() || $method->isFinal() || $method->isAbstract() || $this->isMagicMethod($method->getName());
0 ignored issues
show
Bug introduced by
Consider using $method->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
52
    }
53
54
    private function isMagicMethod(string $name): bool
55
    {
56
        return in_array($name, self::MAGIC_METHOD_NAMES, true);
57
    }
58
59
    private function packFlags(\ReflectionMethod $method): int
60
    {
61
        $flags = [];
62
        if ($method->isPublic()) {
63
            $flags[] = Node\Stmt\Class_::MODIFIER_PUBLIC;
64
        } elseif ($method->isProtected()) {
65
            $flags[] = Node\Stmt\Class_::MODIFIER_PROTECTED;
66
        }
67
68
        return array_reduce($flags, static function ($a, $b) {
69
            return $a | $b;
70
        }, 0);
71
    }
72
73
    private function defineReturnType(\ReflectionMethod $method): ?Node
74
    {
75
        if (!$method->hasReturnType()) {
76
            return null;
77
        }
78
79
        $returnType = $method->getReturnType();
80
81
        if ($returnType === null) {
82
            return null;
83
        }
84
85
        $name = $returnType->getName();
86
87
        if (!$returnType->isBuiltin()) {
88
            $name = '\\' . $name;
89
        }
90
91
        if ($returnType->allowsNull()) {
92
            $name = '?' . $name;
93
        }
94
95
        return new Node\Identifier($name);
96
    }
97
98
    private function packParams(\ReflectionMethod $method): array
99
    {
100
        $params = [];
101
        foreach ($method->getParameters() as $parameter) {
102
            $param = new Param($parameter->getName());
0 ignored issues
show
Bug introduced by
Consider using $parameter->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
103
104
            $type = $this->defineParamReturnType($parameter);
105
            if ($type !== null) {
106
                $param->setType($type);
107
            }
108
109
            $params[] = $param->getNode();
110
        }
111
112
        return $params;
113
    }
114
115
    private function defineParamReturnType(\ReflectionParameter $parameter): ?string
116
    {
117
        if (!$parameter->hasType()) {
118
            return null;
119
        }
120
121
        $typeReflection = $parameter->getType();
122
        if ($typeReflection === null) {
123
            return null;
124
        }
125
126
        $type = $typeReflection->getName();
127
        if ($typeReflection->allowsNull()) {
128
            $type = "?$type";
129
        }
130
131
        return $type;
132
    }
133
}