Completed
Pull Request — master (#266)
by Marco
15:13
created

ParameterGenerator::fromReflection()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 21
ccs 12
cts 12
cp 1
rs 9.3143
cc 2
eloc 11
nc 2
nop 1
crap 2
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license.
17
 */
18
19
namespace ProxyManager\Generator;
20
21
use ReflectionException;
22
use Zend\Code\Generator\ParameterGenerator as ZendParameterGenerator;
23
use Zend\Code\Generator\ValueGenerator;
24
use Zend\Code\Reflection\ParameterReflection;
25
26
/**
27
 * Parameter generator that ensures that the parameter type is a FQCN when it is a class
28
 *
29
 * @author Marco Pivetta <[email protected]>
30
 * @license MIT
31
 */
32
class ParameterGenerator extends ZendParameterGenerator
33
{
34
    /**
35
     * Set if a parameter is variadic or not
36
     *
37
     * @var boolean
38
     */
39
    private $variadic = false;
40
41
    /**
42
     * @override - uses `static` to instantiate the parameter
43
     *
44
     * {@inheritDoc}
45
     */
46 7
    public static function fromReflection(ParameterReflection $reflectionParameter)
47
    {
48
        /* @var $param self */
49 7
        $param = new static();
50
51 7
        $param->setVariadic($reflectionParameter->isVariadic());
52 7
        $param->setName($reflectionParameter->getName());
53 7
        $param->setPosition($reflectionParameter->getPosition());
54
55 7
        $type = self::extractParameterType($reflectionParameter);
56
57 7
        if (null !== $type) {
58 4
            $param->setType($type);
59 4
        }
60
61 7
        self::setOptionalParameter($param, $reflectionParameter);
62
63 7
        $param->setPassedByReference($reflectionParameter->isPassedByReference());
64
65 7
        return $param;
66
    }
67
68
    /**
69
     * Retrieves the type of a reflection parameter (null if none is found)
70
     *
71
     * @param ParameterReflection $reflectionParameter
72
     *
73
     * @return string|null
74
     */
75 7
    private static function extractParameterType(ParameterReflection $reflectionParameter)
76
    {
77 7
        if ($reflectionParameter->isArray()) {
78 1
            return 'array';
79
        }
80
81 6
        if ($reflectionParameter->isCallable()) {
82 1
            return 'callable';
83
        }
84
85 5
        if ($typeClass = $reflectionParameter->getClass()) {
86 2
            return $typeClass->getName();
87
        }
88
89 3
        return null;
90
    }
91
92
    /**
93
     * @return string
94
     */
95 5
    public function generate()
96
    {
97 5
        return $this->getGeneratedType()
98 5
            . (true === $this->passedByReference ? '&' : '')
99 5
            . ($this->variadic ? '...' : '')
100 5
            . '$' . $this->name
101 5
            . ($this->variadic ? '' : $this->generateDefaultValue());
102
    }
103
104
    /**
105
     * @return string
106
     */
107 5
    private function generateDefaultValue()
108
    {
109 5
        if (null === $this->defaultValue) {
110 3
            return '';
111
        }
112
113 2
        $defaultValue = $this->defaultValue instanceof ValueGenerator
114 2
            ? $this->defaultValue
115 2
            : new ValueGenerator($this->defaultValue);
116
117 2
        $defaultValue->setOutputMode(ValueGenerator::OUTPUT_SINGLE_LINE);
118
119 2
        return ' = ' . $defaultValue;
120
    }
121
122
    /**
123
     * Retrieves the generated parameter type
124
     *
125
     * @return string
126
     */
127 5
    private function getGeneratedType()
128
    {
129 5
        if ($this->isSimpleType()) {
130 2
            return '';
131
        }
132
133 3
        if ($this->isInternalType()) {
134 3
            return $this->type . ' ';
135
        }
136
137 1
        return '\\' . trim($this->type, '\\') . ' ';
138
    }
139
140
    /**
141
     * Checks whether the type of the parameter is a simple internal type (no type-hint required)
142
     *
143
     * @return bool
144
     */
145 5
    private function isSimpleType()
146
    {
147 5
        return ! $this->type || in_array($this->type, static::$simple);
148
    }
149
150
    /**
151
     * Checks whether the type of the parameter is internal (currently `array` or `callable` supported)
152
     *
153
     * @return bool
154
     */
155 3
    private function isInternalType()
156
    {
157 3
        return 'array' === strtolower($this->type) || 'callable' === strtolower($this->type);
158
    }
159
160
    /**
161
     * Set the default value for a parameter (if it is optional)
162
     *
163
     * @param ZendParameterGenerator $parameterGenerator
164
     * @param ParameterReflection    $reflectionParameter
165
     */
166 7
    private static function setOptionalParameter(
167
        ZendParameterGenerator $parameterGenerator,
168
        ParameterReflection $reflectionParameter
169
    ) {
170 7
        if ($reflectionParameter->isOptional()) {
171
            try {
172 4
                $parameterGenerator->setDefaultValue($reflectionParameter->getDefaultValue());
173 4
            } catch (ReflectionException $e) {
174 3
                $parameterGenerator->setDefaultValue(null);
175
            }
176 4
        }
177 7
    }
178
179 7
    public function setVariadic($isVariadic)
180
    {
181 7
        $this->variadic = $isVariadic;
182 7
    }
183
184 4
    public function isVariadic()
185
    {
186 4
        return $this->variadic;
187
    }
188
189
}
190