MethodRenderer   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 48
c 1
b 0
f 0
dl 0
loc 108
rs 10
wmc 22

6 Methods

Rating   Name   Duplication   Size   Complexity  
A renderMethodSignature() 0 26 5
A renderType() 0 13 6
A __invoke() 0 10 2
A renderParameter() 0 16 3
A renderCall() 0 13 1
A useReturn() 0 13 5
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 ReflectionException;
15
use ReflectionMethod;
16
use ReflectionNamedType;
17
use ReflectionParameter;
18
use ReflectionType;
19
use ReflectionUnionType;
20
21
use function array_map;
22
use function assert;
23
use function implode;
24
use function json_encode;
25
26
use const PHP_VERSION_ID;
27
28
class MethodRenderer
29
{
30
    public function __invoke(ReflectionMethod $method, string $getterCode): string
31
    {
32
        $signature = $this->renderMethodSignature($method);
33
        $call = $this->renderCall($method);
34
        $mayReturn = $this->useReturn($method) ? 'return ' : '';
35
36
        return <<<PHPTPL
37
                $signature
38
                {
39
                    {$mayReturn}{$getterCode}->$call;
40
                }
41
PHPTPL;
42
    }
43
44
    private function renderMethodSignature(ReflectionMethod $method): string
45
    {
46
        $qualifiers = [];
47
48
        if ($method->isPublic()) {
49
            $qualifiers[] = 'public';
50
        }
51
52
        if ($method->isStatic()) {
53
            $qualifiers[] = 'static';
54
        }
55
56
        $return = '';
57
        $returnType = $method->getReturnType();
58
59
        if ($returnType) {
60
            $return = ': ' . $this->renderType($returnType);
61
        }
62
63
        $params = [];
64
65
        foreach ($method->getParameters() as $parameter) {
66
            $params[] = $this->renderParameter($parameter);
67
        }
68
69
        return implode(' ', $qualifiers) . " function {$method->getName()}(" . implode(', ', $params) . ")$return";
70
    }
71
72
    /**
73
     * @throws ReflectionException
74
     */
75
    private function renderParameter(ReflectionParameter $parameter): string
76
    {
77
        $code = '';
78
        $type = $parameter->getType();
79
80
        if ($type) {
81
            $code = $this->renderType($type) . ' ';
82
        }
83
84
        $code .= '$' . $parameter->getName();
85
86
        if ($parameter->isOptional()) {
87
            $code .= " = " . json_encode($parameter->getDefaultValue());
88
        }
89
90
        return $code;
91
    }
92
93
    private function renderCall(ReflectionMethod $method): string
94
    {
95
        $parameters = implode(
96
            ', ',
97
            array_map(
98
                function (ReflectionParameter $parameter) {
99
                    return '$' . $parameter->getName();
100
                },
101
                $method->getParameters()
102
            )
103
        );
104
105
        return $method->getName() . "($parameters)";
106
    }
107
108
    private function renderType(ReflectionType $type): string
109
    {
110
        if (PHP_VERSION_ID >= 80000 && $type instanceof ReflectionUnionType) {
111
            return implode('|', array_map(function (ReflectionNamedType $namedType) {
112
                return $namedType->getName();
113
            }, $type->getTypes()));
114
        }
115
116
        assert($type instanceof ReflectionNamedType);
117
118
        $name = $type->getName();
119
120
        return ($name !== 'mixed' && $type->allowsNull() ? '?' : '') . ($type->isBuiltin() ? '' : '\\') . $name;
121
    }
122
123
    private function useReturn(ReflectionMethod $method): bool
124
    {
125
        $type = $method->getReturnType();
126
127
        if (PHP_VERSION_ID >= 80000 && $type instanceof ReflectionUnionType) {
128
            return true;
129
        }
130
131
        if ($type instanceof ReflectionNamedType && $type->getName() === 'void') {
132
            return false;
133
        }
134
135
        return true;
136
    }
137
}
138