Completed
Push — master ( e871a2...62a147 )
by Konstantin
04:13
created

ClassCodeGenerator   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Importance

Changes 5
Bugs 2 Features 3
Metric Value
wmc 19
c 5
b 2
f 3
lcom 0
cbo 3
dl 0
loc 89
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B generate() 0 24 3
B generateMethod() 0 16 5
C generateArguments() 0 36 11
1
<?php
2
3
/*
4
 * This file is part of the Prophecy.
5
 * (c) Konstantin Kudryashov <[email protected]>
6
 *     Marcello Duarte <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Prophecy\Doubler\Generator;
13
14
/**
15
 * Class code creator.
16
 * Generates PHP code for specific class node tree.
17
 *
18
 * @author Konstantin Kudryashov <[email protected]>
19
 */
20
class ClassCodeGenerator
21
{
22
    /**
23
     * Generates PHP code for class node.
24
     *
25
     * @param string         $classname
26
     * @param Node\ClassNode $class
27
     *
28
     * @return string
29
     */
30
    public function generate($classname, Node\ClassNode $class)
31
    {
32
        $parts     = explode('\\', $classname);
33
        $classname = array_pop($parts);
34
        $namespace = implode('\\', $parts);
35
36
        $code = sprintf("class %s extends \%s implements %s {\n",
37
            $classname, $class->getParentClass(), implode(', ',
38
                array_map(function ($interface) {return '\\'.$interface;}, $class->getInterfaces())
39
            )
40
        );
41
42
        foreach ($class->getProperties() as $name => $visibility) {
43
            $code .= sprintf("%s \$%s;\n", $visibility, $name);
44
        }
45
        $code .= "\n";
46
47
        foreach ($class->getMethods() as $method) {
48
            $code .= $this->generateMethod($method)."\n";
49
        }
50
        $code .= "\n}";
51
52
        return sprintf("namespace %s {\n%s\n}", $namespace, $code);
53
    }
54
55
    private function generateMethod(Node\MethodNode $method)
56
    {
57
        $php = sprintf("%s %s function %s%s(%s)%s {\n",
58
            $method->getVisibility(),
59
            $method->isStatic() ? 'static' : '',
60
            $method->returnsReference() ? '&':'',
61
            $method->getName(),
62
            implode(', ', $this->generateArguments($method->getArguments())),
63
            version_compare(PHP_VERSION, '7.0', '>=') && $method->hasReturnType()
64
                ? sprintf(': %s', $method->getReturnType())
65
                : ''
66
        );
67
        $php .= $method->getCode()."\n";
68
69
        return $php.'}';
70
    }
71
72
    private function generateArguments(array $arguments)
73
    {
74
        return array_map(function (Node\ArgumentNode $argument) {
75
            $php = '';
76
77
            if ($hint = $argument->getTypeHint()) {
78
                switch ($hint) {
79
                    case 'array':
80
                    case 'callable':
81
                        $php .= $hint;
82
                        break;
83
84
                    case 'string':
85
                    case 'int':
86
                    case 'float':
87
                    case 'bool':
88
                        if (version_compare(PHP_VERSION, '7.0', '>=')) {
89
                            $php .= $hint;
90
                            break;
91
                        }
92
                        // Fall-through to default case for PHP 5.x
93
94
                    default:
95
                        $php .= '\\'.$hint;
96
                }
97
            }
98
99
            $php .= ' '.($argument->isPassedByReference() ? '&' : '').'$'.$argument->getName();
100
101
            if ($argument->isOptional()) {
102
                $php .= ' = '.var_export($argument->getDefault(), true);
103
            }
104
105
            return $php;
106
        }, $arguments);
107
    }
108
}
109