GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CallableReflection::isStaticMethod()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
namespace TRex\Reflection;
3
4
/**
5
 * Class CallableReflection
6
 * Callable Reflection: You can reflect a callback and know its type.
7
 * @package TRex\Reflection
8
 * @author Raphaël Lefebvre <[email protected]>
9
 */
10
class CallableReflection
11
{
12
    /**
13
     * type const
14
     */
15
    const ERROR_TYPE = 0;
16
    const FUNCTION_TYPE = 1;
17
    const CLOSURE_TYPE = 2;
18
    const INSTANCE_METHOD_TYPE = 3;
19
    const STATIC_METHOD_TYPE = 4;
20
    const INVOKED_OBJECT_TYPE = 5;
21
22
    /**
23
     * reflected callback
24
     *
25
     * @var callable
26
     */
27
    private $callable;
28
29
    /**
30
     * type of the reflected callback (const XXX_TYPE)
31
     *
32
     * @var int
33
     */
34
    private $type;
35
36
    /**
37
     * initializes the reflected callback
38
     *
39
     * @param callable $callable
40
     */
41 95
    public function __construct(callable $callable)
42
    {
43 95
        $this->setCallable($callable);
44 95
    }
45
46
    /**
47
     * getter of $callable
48
     *
49
     * @return callable
50
     */
51 95
    public function getCallable()
52
    {
53 95
        return $this->callable;
54
    }
55
56
    /**
57
     * Returns the appropriate class of the callable reflection.
58
     *
59
     * @return \ReflectionFunctionAbstract
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use \ReflectionFunction|\ReflectionMethod.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
60
     * @throws \LogicException
61
     */
62 19
    public function getReflector()
63
    {
64 19
        if ($this->isFunction() || $this->isClosure()) {
65 6
            return new \ReflectionFunction($this->getCallable());
66
        }
67 13
        if ($this->isMethod()) {
68 10
            return new \ReflectionMethod($this->getClassName(), $this->getMethodName());
69
        }
70 3
        if ($this->isInvokedObject()) {
71 3
            return new \ReflectionMethod($this->getClassName(), '__invoke');
72
        }
73
        throw new \LogicException('Unknown callable reflection');
74
    }
75
76
    /**
77
     * invokes the reflected callback
78
     *
79
     * @return mixed
80
     */
81 5
    public function invoke()
82
    {
83 5
        return $this->invokeArgs(func_get_args());
84
    }
85
86
    /**
87
     * invokes the reflected callback
88
     *
89
     * @param array $args
90
     * @return mixed
91
     */
92 18
    public function invokeArgs(array $args)
93
    {
94 18
        return call_user_func_array($this->getCallable(), $args);
95
    }
96
97
    /**
98
     * Invokes the reflected callback with associative params.
99
     *
100
     * @param array $args
101
     * @return mixed
102
     */
103 9
    public function invokeA(array $args)
104
    {
105 9
        return $this->invokeArgs($this->mapArgs($args));
106
    }
107
108
    /**
109
     * invokes the reflected callback with static binding
110
     *
111
     * @return mixed
112
     */
113 5
    public function invokeStatic()
114
    {
115 5
        return $this->invokeArgsStatic(func_get_args());
116
    }
117
118
    /**
119
     * invokes the reflected callback with static binding
120
     *
121
     * @param array $args
122
     * @return mixed
123
     */
124 15
    public function invokeArgsStatic(array $args)
125
    {
126 15
        return forward_static_call_array($this->getCallable(), $args);
127
    }
128
129
    /**
130
     * Invokes the reflected callback with static binding.
131
     * Uses an associative array of params.
132
     *
133
     * @param array $args
134
     * @return mixed
135
     */
136 5
    public function invokeAStatic(array $args)
137
    {
138 5
        return $this->invokeArgsStatic($this->mapArgs($args));
139
    }
140
141
    /**
142
     * getter of $type
143
     *
144
     * @return int
145
     */
146 74
    public function getType()
147
    {
148 74
        if (null === $this->type) {
149 74
            $this->initType();
150 74
        }
151 74
        return $this->type;
152
    }
153
154
    /**
155
     * indicates whether the callback is a function
156
     *
157
     * @return bool
158
     */
159 29
    public function isFunction()
160
    {
161 29
        return $this->getType() === self::FUNCTION_TYPE;
162
    }
163
164
    /**
165
     * indicates whether the callback is a Closure
166
     *
167
     * @return bool
168
     */
169 26
    public function isClosure()
170
    {
171 26
        return $this->getType() === self::CLOSURE_TYPE;
172
    }
173
174
    /**
175
     * indicates whether the callback is a method
176
     *
177
     * @return bool
178
     */
179 23
    public function isMethod()
180
    {
181 23
        return $this->isInstanceMethod() || $this->isStaticMethod();
182
    }
183
184
    /**
185
     * indicates whether the callback is a object method
186
     *
187
     * @return bool
188
     */
189 33
    public function isInstanceMethod()
190
    {
191 33
        return $this->getType() === self::INSTANCE_METHOD_TYPE;
192
    }
193
194
    /**
195
     * indicates whether the callback is a class method
196
     *
197
     * @return bool
198
     */
199 19
    public function isStaticMethod()
200
    {
201 19
        return $this->getType() === self::STATIC_METHOD_TYPE;
202
    }
203
204
    /**
205
     * indicates whether the callback is an invoked object
206
     *
207
     * @return bool
208
     */
209 19
    public function isInvokedObject()
210
    {
211 19
        return $this->getType() === self::INVOKED_OBJECT_TYPE;
212
    }
213
214
    /**
215
     * returns the name of the function, if the reflected callback is a function
216
     *
217
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be callable? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
218
     */
219 5
    public function getFunctionName()
220
    {
221 5
        if ($this->isFunction()) {
222 1
            return $this->getCallable();
223
        }
224 4
        return '';
225
    }
226
227
    /**
228
     * returns the Closure object, if the reflected callback is a Closure
229
     *
230
     * @return \Closure|null
0 ignored issues
show
Documentation introduced by
Should the return type not be callable|null? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
231
     */
232 5
    public function getClosure()
233
    {
234 5
        if ($this->isClosure()) {
235 1
            return $this->getCallable();
236
        }
237 4
        return null;
238
    }
239
240
    /**
241
     * returns the name of the method, if the reflected callback is a method (except __invoke)
242
     *
243
     * @return string
244
     */
245 15
    public function getMethodName()
246
    {
247 15
        if ($this->isMethod()) {
248 12
            return $this->explodeCallable()[1];
249
        }
250 3
        return '';
251
    }
252
253
    /**
254
     * returns the name of the class, if the reflected callback is an object (except Closure)
255
     *
256
     * @return string
257
     */
258 18
    public function getClassName()
259
    {
260 18
        if ($this->isMethod() || $this->isInvokedObject()) {
261 16
            $callable = $this->explodeCallable();
262 16
            if ($this->isInstanceMethod() || $this->isInvokedObject()) {
263 12
                return get_class($callable[0]);
264
            }
265 4
            return $callable[0];
266
        }
267 2
        return '';
268
    }
269
270
    /**
271
     * returns the object, if the reflected callback is an object (except Closure)
272
     *
273
     * @return object|null
274
     */
275 5
    public function getObject()
276
    {
277 5
        if ($this->isInstanceMethod() || $this->isInvokedObject()) {
278 2
            return $this->explodeCallable()[0];
279
        }
280 3
        return null;
281
    }
282
283
    /**
284
     * setter of $callable
285
     *
286
     * @param callable $callable
287
     */
288 95
    private function setCallable(callable $callable)
289
    {
290 95
        $this->callable = $callable;
291 95
    }
292
293
    /**
294
     * explodes the reflected callback in an array and splits method/function from class/object
295
     *
296
     * @return array
297
     */
298 60
    private function explodeCallable()
299
    {
300 60
        if (is_string($this->getCallable())) {
301 28
            return explode('::', $this->getCallable());
302
        }
303 46
        if (is_array($this->getCallable())) {
304 32
            return $this->getCallable();
305
        }
306 14
        return array($this->getCallable());
307
    }
308
309
    /**
310
     * setter of $type
311
     *
312
     * @param int $type
313
     */
314 74
    private function setType($type)
315
    {
316 74
        $this->type = (int)$type;
317 74
    }
318
319
    /**
320
     * initializes $type
321
     */
322 74
    private function initType()
323
    {
324 74
        if ($this->getCallable() instanceof \Closure) {
325 14
            $this->setType(self::CLOSURE_TYPE);
326
327 14
        } else {
328 60
            $callable = $this->explodeCallable();
329 60
            if (count($callable) === 1) {
330 28
                if (is_object($callable[0])) {
331 14
                    $this->setType(self::INVOKED_OBJECT_TYPE);
332
333 14
                } else {
334 14
                    $this->setType(self::FUNCTION_TYPE);
335
                }
336
337 60
            } elseif (count($callable) === 2) {
338 32
                if (is_object($callable[0])) {
339 18
                    $this->setType(self::INSTANCE_METHOD_TYPE);
340
341 18
                } else {
342 14
                    $this->setType(self::STATIC_METHOD_TYPE);
343
                }
344
345 32
            } else {
346
                $this->setType(self::ERROR_TYPE);
347
                throw new \LogicException('Type not found for callable');
348
            }
349
        }
350 74
    }
351
352
    /**
353
     * @param array $args
354
     * @throws \InvalidArgumentException
355
     * @return array
356
     */
357 14
    private function mapArgs(array $args)
358
    {
359 14
        $params = array();
360 14
        foreach ($this->getReflector()->getParameters() as $position => $reflectedParam) {
361 14
            if (array_key_exists($reflectedParam->name, $args)) {
362 13
                $params[$position] = $args[$reflectedParam->name];
363 14
            } elseif ($reflectedParam->isOptional()) {
364 11
                $params[$position] = $reflectedParam->getDefaultValue();
365 11
            } else {
366 1
                throw new \InvalidArgumentException(
367 1
                    sprintf(
368 1
                        'Missing key "%s" for the %sth params of %s',
369 1
                        $reflectedParam->name,
370 1
                        $position,
371 1
                        $this->getReflector()->getName()
372 1
                    )
373 1
                );
374
            }
375 13
        }
376 13
        return $params;
377
    }
378
}
379