ClassTemplate::doGenerate()   C
last analyzed

Complexity

Conditions 14
Paths 39

Size

Total Lines 71

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 40
CRAP Score 14.1472

Importance

Changes 0
Metric Value
cc 14
nc 39
nop 1
dl 0
loc 71
ccs 40
cts 44
cp 0.9091
crap 14.1472
rs 5.646
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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