Passed
Push — master ( 489ba2...382a6c )
by Alexander
01:29
created

ClassRenderer::render()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
1
<?php
2
3
namespace Yiisoft\Proxy;
4
5
final class ClassRenderer
6
{
7
    private string $classSignatureTemplate = '{{modifiers}} {{classType}} {{name}} extends {{parent}}{{implements}}';
8
9
    private string $proxyMethodSignatureTemplate = '{{modifiers}} function {{name}}({{params}}){{returnType}}';
10
11
    private string $proxyMethodBodyTemplate = '{{return}}$this->call({{methodName}}, [{{params}}]);';
12
13
    public function render(ClassConfig $classConfig): string
14
    {
15
        return trim($this->renderClassSignature($classConfig)) . "\n" . '{' . $this->renderClassBody($classConfig) . '}';
16
    }
17
18
    private function renderClassSignature(ClassConfig $classConfig): string
19
    {
20
        return strtr($this->classSignatureTemplate, [
21
            '{{modifiers}}' => $this->renderModifiers($classConfig->modifiers),
22
            '{{classType}}' => $classConfig->isInterface ? 'interface' : 'class',
23
            '{{name}}' => $classConfig->shortName,
24
            '{{parent}}' => $classConfig->parent,
25
            '{{implements}}' => $this->renderImplements($classConfig->interfaces),
26
        ]);
27
    }
28
29
    private function renderImplements(array $interfaces): string
30
    {
31
        return $interfaces !== [] ? ' implements '  . implode(' ', $interfaces) : '';
32
    }
33
34
    private function renderModifiers(array $modifiers)
35
    {
36
        return implode(' ', $modifiers);
37
    }
38
39
    private function renderClassBody(ClassConfig $classConfig): string
40
    {
41
        return $this->renderMethods($classConfig->methods);
42
    }
43
44
    private function renderMethods(array $methods): string
45
    {
46
        $methodsCode = '';
47
        foreach ($methods as $method) {
48
            $methodsCode .= "\n" . $this->renderMethod($method);
49
        }
50
51
        return $methodsCode;
52
    }
53
54
    private function renderMethod(MethodConfig $method): string
55
    {
56
        return $this->renderMethodSignature($method) . "\n" . $this->margin() . '{' . $this->renderMethodBody($method) . $this->margin() . '}' . "\n";
57
    }
58
59
    private function renderMethodSignature(MethodConfig $method): string
60
    {
61
        return strtr($this->proxyMethodSignatureTemplate, [
62
            '{{modifiers}}' => $this->margin() . $this->renderModifiers($method->modifiers),
63
            '{{name}}' => $method->name,
64
            '{{params}}' => $this->renderMethodParameters($method->parameters),
65
            '{{returnType}}' => $this->renderReturnType($method),
66
        ]);
67
    }
68
69
    private function renderMethodParameters(array $parameters): string
70
    {
71
        $params = '';
72
        foreach ($parameters as $parameter) {
73
            $params .= $this->renderMethodParameter($parameter) . ', ';
74
        }
75
76
        return rtrim($params, ', ');
77
    }
78
79
    private function renderMethodParameter(ParameterConfig $parameter): string
80
    {
81
        return ltrim(($parameter->hasType ? $this->renderType($parameter->type) : '') . ' $' . $parameter->name .
82
            $this->renderParameterDefaultValue($parameter));
83
    }
84
85
    private function renderParameterDefaultValue(ParameterConfig $parameter): string
86
    {
87
        return ($parameter->isDefaultValueAvailable ? ' = ' .
88
            ($parameter->isDefaultValueConstant ? $parameter->defaultValueConstantName : self::varExport($parameter->defaultValue)) : '');
89
    }
90
91
    private function renderMethodBody(MethodConfig $method): string
92
    {
93
        return "\n" . strtr($this->proxyMethodBodyTemplate, [
94
                '{{return}}' => $this->margin(2) . $this->renderReturn($method),
95
                '{{methodName}}' => "'" . $method->name . "'",
96
                '{{params}}' => $this->renderMethodCallParameters($method->parameters)
97
            ]) . "\n";
98
    }
99
100
    private function renderReturn(MethodConfig $method): string
101
    {
102
        return $method->hasReturnType ? ($method->returnType->name === 'void' ? '': 'return ') : 'return ';
103
    }
104
105
    private function renderReturnType(MethodConfig $method): string
106
    {
107
        return $method->hasReturnType ? ': ' . $this->renderType($method->returnType) : '';
108
    }
109
110
    private function renderType(TypeConfig $type): string
111
    {
112
        return ($type->allowsNull ? '?' : '') . $type->name;
113
    }
114
115
    private function renderMethodCallParameters(array $parameters): string
116
    {
117
        $params = array_keys($parameters);
118
        return $params !== [] ? '$' . implode(', $', $params) : '';
119
    }
120
121
    private static function varExport($var): string
122
    {
123
        $output = '';
124
        switch (gettype($var)) {
125
            case 'boolean':
126
                $output = $var ? 'true' : 'false';
127
                break;
128
            case 'integer':
129
                $output = (string)$var;
130
                break;
131
            case 'double':
132
                $output = (string)$var;
133
                break;
134
            case 'string':
135
                $output = "'" . addslashes($var) . "'";
136
                break;
137
            case 'NULL':
138
                $output = 'null';
139
                break;
140
            case 'array':
141
                if (empty($var)) {
142
                    $output .= '[]';
143
                } else {
144
                    $keys = array_keys($var);
145
                    $output .= '[';
146
                    foreach ($keys as $key) {
147
                        $output .= self::varExport($key);
148
                        $output .= ' => ';
149
                        $output .= self::varExport($var[$key]);
150
                    }
151
                    $output .= ']';
152
                }
153
                break;
154
        }
155
156
        return $output;
157
    }
158
159
    private function margin(int $count = 1): string
160
    {
161
        return str_repeat('    ', $count);
162
    }
163
}
164