Completed
Push — master ( 7ee214...32fd8d )
by Alberto
19s
created

ClassTemplate::doGenerate()   C

Complexity

Conditions 11
Paths 27

Size

Total Lines 70
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 45
CRAP Score 11

Importance

Changes 0
Metric Value
cc 11
eloc 46
nc 27
nop 1
dl 0
loc 70
ccs 45
cts 45
cp 1
crap 11
rs 5.7333
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\Proxy\ProxyInterface;
7
use Moka\Proxy\ProxyTrait;
8
9
/**
10
 * Class ClassTemplate
11
 * @package Moka\Generator\Template
12
 */
13
class ClassTemplate implements TemplateInterface
14
{
15
    const UNSAFE_METHODS = ['__construct', '__destruct', '__call', '__clone'];
16
17
    const TEMPLATE_FQCN = 'Moka_%s_%s';
18
19
    const TEMPLATE_CLASS = '
20
    class %s extends %s implements %s
21
    {
22
        use %s;
23
        
24
        %s
25
26
        public function __construct()
27
        {
28
            %s
29
        }
30
        
31
        %s
32
        
33
        public function __call(%s $name, %s $arguments)
34
        {
35
            return $this->doCall($name, $arguments);
36
        }
37
        
38
        public function __get(%s $name)
39
        {
40
            return $this->doGet($name);
41
        }
42
    };
43
    
44
    return "%s";
45
    ';
46
47
    /**
48
     * @param \ReflectionClass $class
49
     * @return string
50
     */
51 11
    public static function generate(\Reflector $class): string
52
    {
53 11
        return static::doGenerate($class);
54
    }
55
56
    /**
57
     * @param \ReflectionClass $class
58
     * @return string
59
     */
60 11
    protected static function doGenerate(\ReflectionClass $class): string
61
    {
62 11
        $properties = $class->getProperties(\ReflectionProperty::IS_PUBLIC);
63 11
        $propertiesCode = [];
64
65 11
        $constructorCode = [];
66
67 11
        $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
68 11
        $methodsCode = [];
69 11
        $methodNames = array_map(function (\ReflectionMethod $method) {
70 10
            return $method->name;
71 11
        }, $methods);
72
73 11
        $callParametersTypes = array_fill(0, 2, '');
74 11
        $getNameType = '';
75
76 11
        foreach ($properties as $property) {
77 5
            if (!in_array($property->name, $methodNames)) {
78 1
                continue;
79
            }
80
81 4
            $propertiesCode[] = PropertyTemplate::generate($property);
82
83 4
            $constructorCode[] = PropertyInitializationTemplate::generate($property);
84
        }
85
86 11
        foreach ($methods as $method) {
87
            if (
88 10
                !$method->isFinal() &&
89 10
                !in_array($method->name, self::UNSAFE_METHODS, true)
90
            ) {
91 10
                $methodsCode[] = MethodTemplate::generate($method);
92
            }
93
94 10
            if ('__call' === $method->name) {
95 2
                $callParameters = $method->getParameters();
96 2
                foreach ($callParameters as $callParameter) {
97 2
                    $callParametersTypes[$callParameter->getPosition()] = (string)$callParameter->getType();
98
                }
99
            }
100
101 10
            if ('__get' === $method->name) {
102 10
                $getNameType = (string)$method->getParameters()[0]->getType();
103
            }
104
        }
105
106 11
        $mockClassName = $class->name;
107 11
        $proxyClassName = sprintf(
108 11
            self::TEMPLATE_FQCN,
109 11
            preg_replace('/\\\/', '__', $mockClassName),
110 11
            mt_rand()
111
        );
112
113 11
        list($callNameType, $callArgumentsType) = $callParametersTypes;
114
115 11
        return sprintf(
116 11
            self::TEMPLATE_CLASS,
117 11
            $proxyClassName,
118 11
            $mockClassName,
119 11
            ProxyInterface::class,
120 11
            ProxyTrait::class,
121 11
            implode(PHP_EOL, $propertiesCode),
122 11
            implode(PHP_EOL, $constructorCode),
123 11
            implode(PHP_EOL, $methodsCode),
124 11
            $callNameType ?: '',
125 11
            $callArgumentsType ?: '',
126 11
            $getNameType,
127 11
            $proxyClassName
128
        );
129
    }
130
}
131