Completed
Push — master ( 261083...452422 )
by Rasmus
02:26
created

Reflection::createFromCallable()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 14
cts 14
cp 1
rs 6.9811
c 0
b 0
f 0
cc 7
eloc 14
nc 7
nop 1
crap 7
1
<?php
2
3
namespace mindplay\unbox;
4
5
use Closure;
6
use InvalidArgumentException;
7
use ReflectionFunction;
8
use ReflectionFunctionAbstract;
9
use ReflectionMethod;
10
use ReflectionParameter;
11
12
/**
13
 * Pseudo-namespace for some common reflection helper-functions.
14
 */
15
abstract class Reflection
16
{
17
    /**
18
     * @type string pattern for parsing an argument type from a ReflectionParameter string
19
     *
20
     * @see Reflection::getParameterType()
21
     */
22
    const ARG_PATTERN = '/(?:\<required\>|\<optional\>)\\s+([\\w\\\\]+)/';
23
24
    /**
25
     * Create a Reflection of the function references by any type of callable (or object implementing `__invoke()`)
26
     *
27
     * @param callable|object $callback
28
     *
29
     * @return ReflectionFunctionAbstract
30
     */
31 1
    public static function createFromCallable($callback)
32
    {
33 1
        if (is_object($callback)) {
34 1
            if ($callback instanceof Closure) {
35 1
                return new ReflectionFunction($callback);
36 1
            } elseif (method_exists($callback, '__invoke')) {
37 1
                return new ReflectionMethod($callback, '__invoke');
38
            }
39
40 1
            throw new InvalidArgumentException("class " . get_class($callback) . " does not implement __invoke()");
41 1
        } elseif (is_array($callback)) {
42 1
            if (is_callable($callback)) {
43 1
                return new ReflectionMethod($callback[0], $callback[1]);
44
            }
45
46 1
            throw new InvalidArgumentException("expected callable");
47 1
        } elseif (is_callable($callback)) {
48 1
            return new ReflectionFunction($callback);
49
        }
50
51 1
        throw new InvalidArgumentException("unexpected value: " . var_export($callback, true) . " - expected callable");
52
    }
53
54
    /**
55
     * Obtain the type-hint of a `ReflectionParameter`, but avoid triggering autoload (as a performance optimization)
56
     *
57
     * @param ReflectionParameter $param
58
     *
59
     * @return string|null fully-qualified type-name (or NULL, if no type-hint was available)
60
     */
61 1
    public static function getParameterType(ReflectionParameter $param)
62
    {
63 1
        if (method_exists($param, "getType")) {
64
            $type = $param->getType();
65
66
            return $type === null || $type->isBuiltin()
67
                ? null // ignore scalar type-hints
68
                : $type->__toString();
69
        }
70
71 1
        if (preg_match(self::ARG_PATTERN, $param->__toString(), $matches) === 1) {
72 1
            return $matches[1];
73
        }
74
75 1
        return null; // no type-hint is available
76
    }
77
}
78