891faa8fbe17b4c64287859141083e810a36d252
[yaffs-website] / vendor / phpspec / prophecy / src / Prophecy / Doubler / Generator / ClassCodeGenerator.php
1 <?php
2
3 /*
4  * This file is part of the Prophecy.
5  * (c) Konstantin Kudryashov <ever.zet@gmail.com>
6  *     Marcello Duarte <marcello.duarte@gmail.com>
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 <ever.zet@gmail.com>
19  */
20 class ClassCodeGenerator
21 {
22     /**
23      * @var TypeHintReference
24      */
25     private $typeHintReference;
26
27     public function __construct(TypeHintReference $typeHintReference = null)
28     {
29         $this->typeHintReference = $typeHintReference ?: new TypeHintReference();
30     }
31
32     /**
33      * Generates PHP code for class node.
34      *
35      * @param string         $classname
36      * @param Node\ClassNode $class
37      *
38      * @return string
39      */
40     public function generate($classname, Node\ClassNode $class)
41     {
42         $parts     = explode('\\', $classname);
43         $classname = array_pop($parts);
44         $namespace = implode('\\', $parts);
45
46         $code = sprintf("class %s extends \%s implements %s {\n",
47             $classname, $class->getParentClass(), implode(', ',
48                 array_map(function ($interface) {return '\\'.$interface;}, $class->getInterfaces())
49             )
50         );
51
52         foreach ($class->getProperties() as $name => $visibility) {
53             $code .= sprintf("%s \$%s;\n", $visibility, $name);
54         }
55         $code .= "\n";
56
57         foreach ($class->getMethods() as $method) {
58             $code .= $this->generateMethod($method)."\n";
59         }
60         $code .= "\n}";
61
62         return sprintf("namespace %s {\n%s\n}", $namespace, $code);
63     }
64
65     private function generateMethod(Node\MethodNode $method)
66     {
67         $php = sprintf("%s %s function %s%s(%s)%s {\n",
68             $method->getVisibility(),
69             $method->isStatic() ? 'static' : '',
70             $method->returnsReference() ? '&':'',
71             $method->getName(),
72             implode(', ', $this->generateArguments($method->getArguments())),
73             $this->getReturnType($method)
74         );
75         $php .= $method->getCode()."\n";
76
77         return $php.'}';
78     }
79
80     /**
81      * @return string
82      */
83     private function getReturnType(Node\MethodNode $method)
84     {
85         if (version_compare(PHP_VERSION, '7.1', '>=')) {
86             if ($method->hasReturnType()) {
87                 return $method->hasNullableReturnType()
88                     ? sprintf(': ?%s', $method->getReturnType())
89                     : sprintf(': %s', $method->getReturnType());
90             }
91         }
92
93         if (version_compare(PHP_VERSION, '7.0', '>=')) {
94             return $method->hasReturnType() && $method->getReturnType() !== 'void'
95                 ? sprintf(': %s', $method->getReturnType())
96                 : '';
97         }
98
99         return '';
100     }
101
102     private function generateArguments(array $arguments)
103     {
104         $typeHintReference = $this->typeHintReference;
105         return array_map(function (Node\ArgumentNode $argument) use ($typeHintReference) {
106             $php = '';
107
108             if (version_compare(PHP_VERSION, '7.1', '>=')) {
109                 $php .= $argument->isNullable() ? '?' : '';
110             }
111
112             if ($hint = $argument->getTypeHint()) {
113                 $php .= $typeHintReference->isBuiltInParamTypeHint($hint) ? $hint : '\\'.$hint;
114             }
115
116             $php .= ' '.($argument->isPassedByReference() ? '&' : '');
117
118             $php .= $argument->isVariadic() ? '...' : '';
119
120             $php .= '$'.$argument->getName();
121
122             if ($argument->isOptional() && !$argument->isVariadic()) {
123                 $php .= ' = '.var_export($argument->getDefault(), true);
124             }
125
126             return $php;
127         }, $arguments);
128     }
129 }