Passed
Push — master ( 501718...48df40 )
by Olivier
01:34
created

MethodRenderer::useReturn()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 6
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 13
rs 9.6111
1
<?php
2
3
/*
4
 * This file is part of the olvlvl/symfony-dependency-injection-proxy package.
5
 *
6
 * (c) Olivier Laviale <[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
namespace olvlvl\SymfonyDependencyInjectionProxy;
13
14
use ReflectionMethod;
15
use ReflectionNamedType;
16
use ReflectionParameter;
17
use ReflectionType;
18
use ReflectionUnionType;
19
20
use function array_map;
21
use function implode;
22
use function json_encode;
23
24
use const PHP_VERSION_ID;
25
26
class MethodRenderer
27
{
28
    public function __invoke(ReflectionMethod $method, string $getterCode): string
29
    {
30
        $signature = $this->renderMethodSignature($method);
31
        $call = $this->renderCall($method);
32
        $mayReturn = $this->useReturn($method) ? 'return ' : '';
33
34
        return <<<PHPTPL
35
                $signature
36
                {
37
                    {$mayReturn}{$getterCode}->$call;
38
                }
39
PHPTPL;
40
    }
41
42
    private function renderMethodSignature(ReflectionMethod $method): string
43
    {
44
        $qualifiers = [];
45
46
        if ($method->isPublic()) {
47
            $qualifiers[] = 'public';
48
        }
49
50
        if ($method->isStatic()) {
51
            $qualifiers[] = 'static';
52
        }
53
54
        $return = '';
55
56
        if ($method->hasReturnType()) {
57
            $type = $method->getReturnType();
58
            $return = ': ' . $this->renderType($type);
59
        }
60
61
        $params = [];
62
63
        foreach ($method->getParameters() as $parameter) {
64
            $params[] = $this->renderParameter($parameter);
65
        }
66
67
        return implode(' ', $qualifiers) . " function {$method->getName()}(" . implode(', ', $params) . ")$return";
68
    }
69
70
    private function renderParameter(ReflectionParameter $parameter): string
71
    {
72
        $code = '';
73
74
        if ($parameter->hasType()) {
75
            $code = $this->renderType($parameter->getType()) . ' ';
76
        }
77
78
        $code .= '$' . $parameter->getName();
79
80
        if ($parameter->isOptional()) {
81
            $code .= " = " . json_encode($parameter->getDefaultValue());
82
        }
83
84
        return $code;
85
    }
86
87
    private function renderCall(ReflectionMethod $method): string
88
    {
89
        $parameters = implode(
90
            ', ',
91
            array_map(
92
                function (ReflectionParameter $parameter) {
93
                    return '$' . $parameter->getName();
94
                },
95
                $method->getParameters()
96
            )
97
        );
98
99
        return $method->getName() . "($parameters)";
100
    }
101
102
    private function renderType(ReflectionType $type): string
103
    {
104
        if (PHP_VERSION_ID >= 80000 && $type instanceof ReflectionUnionType) {
105
            return implode('|', array_map(function (ReflectionNamedType $namedType) {
106
                return $namedType->getName();
107
            }, $type->getTypes()));
108
        }
109
110
        $name = $type->getName();
0 ignored issues
show
Bug introduced by
The method getName() does not exist on ReflectionType. It seems like you code against a sub-type of ReflectionType such as ReflectionNamedType. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

110
        /** @scrutinizer ignore-call */ 
111
        $name = $type->getName();
Loading history...
111
112
        return ($name !== 'mixed' && $type->allowsNull() ? '?' : '') . ($type->isBuiltin() ? '' : '\\') . $name;
113
    }
114
115
    private function useReturn(ReflectionMethod $method): bool
116
    {
117
        $type = $method->getReturnType();
118
119
        if (PHP_VERSION_ID >= 80000 && $type instanceof ReflectionUnionType) {
120
            return true;
121
        }
122
123
        if ($method->hasReturnType() && $type->getName() === 'void') {
124
            return false;
125
        }
126
127
        return true;
128
    }
129
}
130