Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/**
4
 * Mockery
5
 *
6
 * LICENSE
7
 *
8
 * This source file is subject to the new BSD license that is bundled
9
 * with this package in the file LICENSE.txt.
10
 * It is also available through the world-wide-web at this URL:
11
 * http://github.com/padraic/mockery/blob/master/LICENSE
12
 * If you did not receive a copy of the license and are unable to
13
 * obtain it through the world-wide-web, please send an email
14
 * to padraic@php.net so we can send you a copy immediately.
15
 *
16
 * @category   Mockery
17
 * @package    Mockery
18
 * @copyright  Copyright (c) 2017 Dave Marshall https://github.com/davedevelopment
19
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
20
 */
21
 
22
namespace Mockery;
23
 
24
/**
25
 * @internal
26
 */
27
class Reflector
28
{
29
    /**
30
     * Determine if the parameter is typed as an array.
31
     *
32
     * @param \ReflectionParameter $param
33
     *
34
     * @return bool
35
     */
36
    public static function isArray(\ReflectionParameter $param)
37
    {
38
        $type = $param->getType();
39
 
40
        return $type instanceof \ReflectionNamedType && $type->getName();
41
    }
42
 
43
    /**
44
     * Compute the string representation for the paramater type.
45
     *
46
     * @param \ReflectionParameter $param
47
     * @param bool $withoutNullable
48
     *
49
     * @return string|null
50
     */
51
    public static function getTypeHint(\ReflectionParameter $param, $withoutNullable = false)
52
    {
53
        if (!$param->hasType()) {
54
            return null;
55
        }
56
 
57
        $type = $param->getType();
58
        $declaringClass = $param->getDeclaringClass();
59
        $typeHint = self::typeToString($type, $declaringClass);
60
 
61
        return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
62
    }
63
 
64
    /**
65
     * Compute the string representation for the return type.
66
     *
67
     * @param \ReflectionParameter $param
68
     * @param bool $withoutNullable
69
     *
70
     * @return string|null
71
     */
72
    public static function getReturnType(\ReflectionMethod $method, $withoutNullable = false)
73
    {
74
        $type = $method->getReturnType();
75
 
76
        if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
77
            $type = $method->getTentativeReturnType();
78
        }
79
 
80
        if (is_null($type)) {
81
            return null;
82
        }
83
 
84
        $typeHint = self::typeToString($type, $method->getDeclaringClass());
85
 
86
        return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
87
    }
88
 
89
    /**
90
     * Compute the string representation for the simplest return type.
91
     *
92
     * @param \ReflectionParameter $param
93
     *
94
     * @return string|null
95
     */
96
    public static function getSimplestReturnType(\ReflectionMethod $method)
97
    {
98
        $type = $method->getReturnType();
99
 
100
        if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
101
            $type = $method->getTentativeReturnType();
102
        }
103
 
104
        if (is_null($type) || $type->allowsNull()) {
105
            return null;
106
        }
107
 
108
        $typeInformation = self::getTypeInformation($type, $method->getDeclaringClass());
109
 
110
        // return the first primitive type hint
111
        foreach ($typeInformation as $info) {
112
            if ($info['isPrimitive']) {
113
                return $info['typeHint'];
114
            }
115
        }
116
 
117
        // if no primitive type, return the first type
118
        foreach ($typeInformation as $info) {
119
            return $info['typeHint'];
120
        }
121
 
122
        return null;
123
    }
124
 
125
    /**
126
     * Get the string representation of the given type.
127
     *
128
     * @param \ReflectionType $type
129
     * @param string $declaringClass
130
     *
131
     * @return string|null
132
     */
133
    private static function typeToString(\ReflectionType $type, \ReflectionClass $declaringClass)
134
    {
135
        return \implode('|', \array_map(function (array $typeInformation) {
136
            return $typeInformation['typeHint'];
137
        }, self::getTypeInformation($type, $declaringClass)));
138
    }
139
 
140
    /**
141
     * Get the string representation of the given type.
142
     *
143
     * @param \ReflectionType  $type
144
     * @param \ReflectionClass $declaringClass
145
     *
146
     * @return list<array{typeHint: string, isPrimitive: bool}>
147
     */
148
    private static function getTypeInformation(\ReflectionType $type, \ReflectionClass $declaringClass)
149
    {
150
        // PHP 8 union types and PHP 8.1 intersection types can be recursively processed
151
        if ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) {
152
            $types = [];
153
 
154
            foreach ($type->getTypes() as $innterType) {
155
                foreach (self::getTypeInformation($innterType, $declaringClass) as $info) {
156
                    if ($info['typeHint'] === 'null' && $info['isPrimitive']) {
157
                        continue;
158
                    }
159
 
160
                    $types[] = $info;
161
                }
162
            }
163
 
164
            return $types;
165
        }
166
 
167
        // $type must be an instance of \ReflectionNamedType
168
        $typeHint = $type->getName();
169
 
170
        // builtins can be returned as is
171
        if ($type->isBuiltin()) {
172
            return [
173
                [
174
                    'typeHint' => $typeHint,
175
                    'isPrimitive' => in_array($typeHint, ['array', 'bool', 'int', 'float', 'null', 'object', 'string']),
176
                ],
177
            ];
178
        }
179
 
180
        // 'static' can be returned as is
181
        if ($typeHint === 'static') {
182
            return [
183
                [
184
                    'typeHint' => $typeHint,
185
                    'isPrimitive' => false,
186
                ],
187
            ];
188
        }
189
 
190
        // 'self' needs to be resolved to the name of the declaring class
191
        if ($typeHint === 'self') {
192
            $typeHint = $declaringClass->getName();
193
        }
194
 
195
        // 'parent' needs to be resolved to the name of the parent class
196
        if ($typeHint === 'parent') {
197
            $typeHint = $declaringClass->getParentClass()->getName();
198
        }
199
 
200
        // class names need prefixing with a slash
201
        return [
202
            [
203
                'typeHint' => sprintf('\\%s', $typeHint),
204
                'isPrimitive' => false,
205
            ],
206
        ];
207
    }
208
 
209
    /**
210
     * Format the given type as a nullable type.
211
     *
212
     * @param string $typeHint
213
     *
214
     * @return string
215
     */
216
    private static function formatNullableType($typeHint)
217
    {
218
        if (\PHP_VERSION_ID < 80000) {
219
            return sprintf('?%s', $typeHint);
220
        }
221
 
222
        return $typeHint === 'mixed' ? 'mixed' : sprintf('%s|null', $typeHint);
223
    }
224
}