Passed
Pull Request — master (#21)
by
unknown
02:46
created

ClassRenderer::renderMethodSignature()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 7
ccs 6
cts 6
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Proxy;
6
7
use Yiisoft\Proxy\Config\ClassConfig;
8
use Yiisoft\Proxy\Config\MethodConfig;
9
use Yiisoft\Proxy\Config\ParameterConfig;
10
use Yiisoft\Proxy\Config\TypeConfig;
11
12
final class ClassRenderer
13
{
14
    private string $classSignatureTemplate = '{{modifiers}} {{classType}} {{name}}{{extends}}{{parent}}{{implements}}';
15
16
    private string $proxyMethodSignatureTemplate = '{{modifiers}} function {{name}}({{params}}){{returnType}}';
17
18
    private string $proxyMethodBodyTemplate = '{{return}}$this->call({{methodName}}, [{{params}}]);';
19
20 5
    public function render(ClassConfig $classConfig): string
21
    {
22 5
        return trim($this->renderClassSignature($classConfig))
23
            . "\n"
24
            . '{'
25 5
            . $this->renderClassBody($classConfig)
26
            . '}';
27
    }
28
29 5
    private function renderClassSignature(ClassConfig $classConfig): string
30
    {
31 5
        $classType = $classConfig->isInterface
32 2
            ? 'interface'
33 3
            : 'class';
34 5
        $extends = $classConfig->parent
35 2
            ? ' extends '
36 3
            : '';
37
38 5
        return strtr($this->classSignatureTemplate, [
39 5
            '{{modifiers}}' => $this->renderModifiers($classConfig->modifiers),
40
            '{{classType}}' => $classType,
41 5
            '{{name}}' => $classConfig->shortName,
42
            '{{extends}}' => $extends,
43 5
            '{{parent}}' => $classConfig->parent,
44 5
            '{{implements}}' => $this->renderImplements($classConfig->interfaces),
45
        ]);
46
    }
47
48 5
    private function renderImplements(array $interfaces): string
49
    {
50 5
        $output = $interfaces !== []
51 2
            ? ' implements ' . implode(', ', $interfaces)
52 3
            : '';
53
54 5
        return $output;
55
    }
56
57 5
    private function renderModifiers(array $modifiers): string
58
    {
59 5
        return implode(' ', $modifiers);
60
    }
61
62 5
    private function renderClassBody(ClassConfig $classConfig): string
63
    {
64 5
        return $this->renderMethods($classConfig->methods);
65
    }
66
67
    /**
68
     * @param MethodConfig[] $methods
69
     * @return string
70
     */
71 5
    private function renderMethods(array $methods): string
72
    {
73 5
        $methodsCode = '';
74 5
        foreach ($methods as $method) {
75 2
            $methodsCode .= "\n" . $this->renderMethod($method);
76
        }
77
78 5
        return $methodsCode;
79
    }
80
81 2
    private function renderMethod(MethodConfig $method): string
82
    {
83 2
        return $this->renderMethodSignature($method)
84 2
            . "\n" . $this->margin()
85
            . '{'
86 2
            . $this->renderMethodBody($method)
87 2
            . $this->margin()
88
            . '}'
89
            . "\n";
90
    }
91
92 2
    private function renderMethodSignature(MethodConfig $method): string
93
    {
94 2
        return strtr($this->proxyMethodSignatureTemplate, [
95 2
            '{{modifiers}}' => $this->margin() . $this->renderModifiers($method->modifiers),
96 2
            '{{name}}' => $method->name,
97 2
            '{{params}}' => $this->renderMethodParameters($method->parameters),
98 2
            '{{returnType}}' => $this->renderReturnType($method),
99
        ]);
100
    }
101
102 2
    private function renderMethodParameters(array $parameters): string
103
    {
104 2
        $params = '';
105 2
        foreach ($parameters as $parameter) {
106 1
            $params .= $this->renderMethodParameter($parameter) . ', ';
107
        }
108
109 2
        return rtrim($params, ', ');
110
    }
111
112 1
    private function renderMethodParameter(ParameterConfig $parameter): string
113
    {
114 1
        $type = $parameter->hasType
115 1
            ? $this->renderType($parameter->type)
0 ignored issues
show
Bug introduced by
It seems like $parameter->type can also be of type null; however, parameter $type of Yiisoft\Proxy\ClassRenderer::renderType() does only seem to accept Yiisoft\Proxy\Config\TypeConfig, maybe add an additional type check? ( Ignorable by Annotation )

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

115
            ? $this->renderType(/** @scrutinizer ignore-type */ $parameter->type)
Loading history...
116 1
            : '';
117 1
        $output = $type
118
            . ' $'
119 1
            . $parameter->name
120 1
            . $this->renderParameterDefaultValue($parameter);
121
122 1
        return ltrim($output);
123
    }
124
125 1
    private function renderParameterDefaultValue(ParameterConfig $parameter): string
126
    {
127 1
        if (!$parameter->isDefaultValueAvailable) {
128 1
            return '';
129
        }
130
131 1
        $value = $parameter->isDefaultValueConstant
132 1
            ? $parameter->defaultValueConstantName
133 1
            : self::varExport($parameter->defaultValue);
134
135 1
        return ' = ' . $value;
136
    }
137
138 2
    private function renderMethodBody(MethodConfig $method): string
139
    {
140 2
        return "\n" . strtr($this->proxyMethodBodyTemplate, [
141 2
            '{{return}}' => $this->margin(2) . $this->renderReturn($method),
142 2
            '{{methodName}}' => "'" . $method->name . "'",
143 2
            '{{params}}' => $this->renderMethodCallParameters($method->parameters),
144
        ]) . "\n";
145
    }
146
147 2
    private function renderReturn(MethodConfig $method): string
148
    {
149 2
        $output = $method->returnType?->name === 'void'
150 1
            ? ''
151 2
            : 'return ';
152
153 2
        return $output;
154
    }
155
156 2
    private function renderReturnType(MethodConfig $method): string
157
    {
158 2
        $output = $method->hasReturnType
159 2
            ? ': ' . $this->renderType($method->returnType)
0 ignored issues
show
Bug introduced by
It seems like $method->returnType can also be of type null; however, parameter $type of Yiisoft\Proxy\ClassRenderer::renderType() does only seem to accept Yiisoft\Proxy\Config\TypeConfig, maybe add an additional type check? ( Ignorable by Annotation )

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

159
            ? ': ' . $this->renderType(/** @scrutinizer ignore-type */ $method->returnType)
Loading history...
160 1
            : '';
161
162 2
        return $output;
163
    }
164
165 2
    private function renderType(TypeConfig $type): string
166
    {
167 2
        $output = $type->allowsNull
168 1
            ? '?'
169 2
            : '';
170 2
        $output .= $type->name;
171
172 2
        return $output;
173
    }
174
175 2
    private function renderMethodCallParameters(array $parameters): string
176
    {
177 2
        $keys = array_keys($parameters);
178 2
        $output = $keys !== []
179 1
            ? '$' . implode(', $', $keys)
180 2
            : '';
181
182 2
        return $output;
183
    }
184
185 1
    private static function varExport(mixed $var): string
186
    {
187 1
        $output = '';
188 1
        switch (gettype($var)) {
189 1
            case 'boolean':
190 1
                $output = $var
191 1
                    ? 'true'
192 1
                    : 'false';
193 1
                break;
194 1
            case 'integer':
195 1
            case 'double':
196 1
                $output = (string)$var;
197 1
                break;
198 1
            case 'string':
199 1
                $output = "'" . addslashes($var) . "'";
200 1
                break;
201 1
            case 'NULL':
202 1
                $output = 'null';
203 1
                break;
204 1
            case 'array':
205 1
                if (empty($var)) {
206 1
                    $output .= '[]';
207
                } else {
208 1
                    $keys = array_keys($var);
209 1
                    $output .= '[';
210 1
                    foreach ($keys as $key) {
211 1
                        $output .= self::varExport($key);
212 1
                        $output .= ' => ';
213 1
                        $output .= self::varExport($var[$key]);
214
                    }
215 1
                    $output .= ']';
216
                }
217 1
                break;
218
        }
219
220 1
        return $output;
221
    }
222
223 2
    private function margin(int $count = 1): string
224
    {
225 2
        return str_repeat('    ', $count);
226
    }
227
}
228