Completed
Pull Request — master (#46)
by Jitendra
01:52
created

Metadata::getMethodParameters()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 6
nop 3
dl 0
loc 21
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the PHINT package.
5
 *
6
 * (c) Jitendra Adhikari <[email protected]>
7
 *     <https://github.com/adhocore>
8
 *
9
 * Licensed under MIT license.
10
 */
11
12
namespace Ahc\Phint\Util;
13
14
use CrazyFactory\DocBlocks\DocBlock;
15
16
class Metadata
17
{
18
    public function forClass(string $classFqcn): array
19
    {
20
        return $this->forReflectionClass(new \ReflectionClass($classFqcn));
21
    }
22
23
    public function forReflectionClass(\ReflectionClass $class): array
24
    {
25
        $name  = $class->name;
26
        $texts = (new DocBlock($class))->texts();
27
        $title = \array_shift($texts);
28
29
        $metadata = [
30
            'namespace'   => \preg_replace('!\W\w+$!', '', $name),
31
            'classFqcn'   => $name,
32
            'classPath'   => $class->getFileName(),
33
            'name'        => $class->getShortName(),
34
            'className'   => $class->getShortName(),
35
            'isTrait'     => $class->isTrait(),
36
            'isAbstract'  => $class->isAbstract(),
37
            'isInterface' => $class->isInterface(),
38
            'newable'     => $class->isInstantiable(),
39
            'title'       => $title,
40
            'texts'       => $texts,
41
            'methods'     => [],
42
        ];
43
44
        foreach ($class->getMethods() as $method) {
45
            if ($method->class !== $name) {
46
                continue;
47
            }
48
49
            $metadata['methods'][$method->name] = $this->forReflectionMethod($method);
50
        }
51
52
        return $metadata;
53
    }
54
55
    public function forMethod(string $classFqcn, string $method): array
56
    {
57
        $reflMethod = (new \ReflectionClass($classFqcn))->getMethod($method);
58
59
        return $this->forReflectionMethod($reflMethod);
60
    }
61
62
    public function forReflectionMethod(\ReflectionMethod $method): array
63
    {
64
        $parser = new DocBlock($method);
65
        $texts  = $parser->texts();
66
        $title  = \array_shift($texts);
67
68
        $metadata = [
69
            'name'       => $method->name,
70
            'inClass'    => $method->getDeclaringClass()->name,
71
            'isStatic'   => $method->isStatic(),
72
            'isFinal'    => $method->isFinal(),
73
            'isPublic'   => $method->isPublic(),
74
            'isAbstract' => $method->isAbstract(),
75
            'maybeMagic' => \substr($method->name, 0, 2) === '__',
76
            'title'      => $title,
77
            'texts'      => $texts,
78
        ];
79
80
        $params = [];
81
        foreach ($parser->find('param') as $param) {
82
            if (\preg_match('/(.*)\$(\w+)/', $param->getValue(), $match)) {
83
                $params[$match[2]] = \trim($match[1]);
84
            }
85
        }
86
87
        if (null !== $return = $parser->first('return')) {
88
            $return = \preg_replace('/(\S+)(.*)/', '$1', $return->getValue());
89
        }
90
91
        return $metadata + $this->getMethodParameters($method, $params, $return ?? '');
92
    }
93
94
    protected function getMethodParameters(\ReflectionMethod $method, array $docParams, string $return)
95
    {
96
        $params = [];
97
        $parser = new DocBlock($method);
0 ignored issues
show
Unused Code introduced by
The assignment to $parser is dead and can be removed.
Loading history...
98
99
        foreach ($method->getParameters() as $param) {
100
            $name = $param->name;
101
            if (!$param->hasType()) {
102
                $params[] = \trim(($docParams[$name] ?? '') . " \$$name");
103
104
                continue;
105
            }
106
107
            $params[] = $this->getRealType($param) . " \$$name";
108
        }
109
110
        if ($returnType = $method->getReturnType()) {
111
            $return = $this->getRealType($returnType);
112
        }
113
114
        return \compact('params', 'return');
115
    }
116
117
    protected function getRealType($param): string
118
    {
119
        $type = \method_exists($param, 'getType')
120
            ? $param->getType()
121
            : (string) $param;
122
123
        if (\preg_match('/void|null/', $type)) {
124
            return $type;
125
        }
126
127
        return $type . ($param->allowsNull() ? '|null' : '');
128
    }
129
}
130