ClassTemplate   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Test Coverage

Coverage 91.3%

Importance

Changes 0
Metric Value
dl 0
loc 121
ccs 42
cts 46
cp 0.913
rs 10
c 0
b 0
f 0
wmc 15
lcom 0
cbo 3

2 Methods

Rating   Name   Duplication   Size   Complexity  
A generate() 0 4 1
C doGenerate() 0 71 14
1
<?php
2
declare(strict_types=1);
3
4
namespace Moka\Generator\Template;
5
6
use Moka\Exception\InvalidArgumentException;
7
use Moka\Proxy\ProxyInterface;
8
use Moka\Proxy\ProxyTrait;
9
10
/**
11
 * Class ClassTemplate
12
 * @package Moka\Generator\Template
13
 */
14
class ClassTemplate implements TemplateInterface
15
{
16
    private const UNSAFE_METHODS = ['__construct', '__destruct', '__call', '__get', '__clone'];
17
18
    private const TEMPLATE_FQCN = 'Moka_%s_%s';
19
20
    private const TEMPLATE_CLASS = '
21
    class %s extends %s implements %s
22
    {
23
        use %s;
24
        
25
        %s
26
27
        public function __construct()
28
        {
29
            %s
30
        }
31
        
32
        public function __call(%s $name, %s $arguments)
33
        {
34
            return $this->doCall($name, $arguments);
35
        }
36
        
37
        public function __get(%s $name)
38
        {
39
            return $this->doGet($name);
40
        }
41
42
        %s
43
    };
44
    
45
    return "%s";
46
    ';
47
48
    /**
49
     * @param \Reflector|\ReflectionClass $class
50
     * @return string
51
     */
52 11
    public static function generate(\Reflector $class): string
53
    {
54 11
        return static::doGenerate($class);
55
    }
56
57
    /**
58
     * @param \ReflectionClass $class
59
     * @return string
60
     * @throws \RuntimeException
61
     * @throws InvalidArgumentException
62
     */
63 11
    protected static function doGenerate(\ReflectionClass $class): string
64
    {
65 11
        $properties = $class->getProperties(\ReflectionProperty::IS_PUBLIC);
66 11
        $propertiesCode = [];
67
68 11
        $constructorCode = [];
69
70 11
        $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
71 11
        $methodsCode = [];
72
73 11
        $callParametersTypes = array_fill(0, 2, '');
74 11
        $getNameType = '';
75
76 11
        foreach ($properties as $property) {
77 5
            if ($property->isStatic()) {
78 5
                continue;
79
            }
80
81 5
            $propertiesCode[] = PropertyTemplate::generate($property);
82 5
            $constructorCode[] = PropertyInitializationTemplate::generate($property);
83
        }
84
85 11
        foreach ($methods as $method) {
86
            if (
87 10
                !$method->isFinal() &&
88 10
                !\in_array($method->name, self::UNSAFE_METHODS, $strict = true)
89
            ) {
90 10
                $methodsCode[] = MethodTemplate::generate($method);
91
            }
92
93 10
            if ('__call' === $method->name) {
94 2
                $callParameters = $method->getParameters();
95 2
                foreach ($callParameters as $callParameter) {
96 2
                    $callParametersTypes[$callParameter->getPosition()] = $callParameter->getType()
97 1
                        ? $callParameter->getType()->getName()
98 2
                        : null;
99
                }
100
            }
101
102 10
            if ('__get' === $method->name) {
103
                $geFirstParameter = $method->getParameters()[0];
104
                $getNameType = $geFirstParameter->getType()
105
                    ? $geFirstParameter->getType()->getName()
106
                    : null;
107
            }
108
        }
109
110 11
        $mockClassName = $class->name;
111 11
        $proxyClassName = sprintf(
112 11
            self::TEMPLATE_FQCN,
113 11
            preg_replace('/\\\/', '__', $mockClassName),
114 11
            random_int($min = 0, $max = PHP_INT_MAX)
115
        );
116
117 11
        [$callNameType, $callArgumentsType] = $callParametersTypes;
0 ignored issues
show
Bug introduced by
The variable $callNameType does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $callArgumentsType does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
118
119 11
        return sprintf(
120 11
            self::TEMPLATE_CLASS,
121
            $proxyClassName,
122
            $mockClassName,
123 11
            ProxyInterface::class,
124 11
            ProxyTrait::class,
125 11
            implode(PHP_EOL, $propertiesCode),
126 11
            implode(PHP_EOL, $constructorCode),
127 11
            $callNameType ?: '',
128 11
            $callArgumentsType ?: '',
129 11
            $getNameType ?: '',
130 11
            implode(PHP_EOL, $methodsCode),
131
            $proxyClassName
132
        );
133
    }
134
}
135