Passed
Push — master ( d44e7d...fd48aa )
by Alexey
07:53
created

ReflectedCallable::callable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1.125

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 4
cp 0.5
crap 1.125
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types = 1);
2
3
namespace Venta\Container;
4
5
use Closure;
6
use InvalidArgumentException;
7
use ReflectionFunction;
8
use ReflectionFunctionAbstract;
9
use ReflectionMethod;
10
11
/**
12
 * Class ReflectedCallable
13
 *
14
 * @package Venta\Container
15
 */
16
class ReflectedCallable
17
{
18
19
    /**
20
     * @var callable
21
     */
22
    private $callable;
23
24
    /**
25
     * @var ReflectionFunctionAbstract
26
     */
27
    private $reflection;
28
29
    /**
30
     * ReflectedCallable constructor.
31
     *
32
     * @param callable $callable
33
     */
34 32
    public function __construct($callable)
35
    {
36 32
        $this->callable = $this->normalizeCallable($callable);
37 30
    }
38
39
    /**
40
     * @return callable
41
     */
42 26
    public function callable()
43
    {
44 26
        return $this->callable;
45
    }
46
47
    /**
48
     * @return bool
49
     */
50 29
    public function isFunction(): bool
51
    {
52 29
        return !is_array($this->callable);
53
    }
54
55
    /**
56
     * @return ReflectionFunctionAbstract|ReflectionMethod|ReflectionFunction
57
     */
58 29
    public function reflection(): ReflectionFunctionAbstract
59
    {
60 29
        if (empty($this->reflection)) {
61 29
            $this->reflection = $this->isFunction()
62 11
                ? new ReflectionFunction($this->callable)
63 18
                : new ReflectionMethod($this->callable[0], $this->callable[1]);
64
        }
65
66 29
        return $this->reflection;
67
    }
68
69
    /**
70
     * @param $callable
71
     * @return callable
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Closure|string|array.

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...
72
     * @throws InvalidArgumentException
73
     */
74 32
    private function normalizeCallable($callable)
75
    {
76 32
        if (is_object($callable)) {
77 11
            if ($callable instanceof Closure) {
78 9
                return $callable;
79
            } else {
80 2
                if (!method_exists($callable, '__invoke')) {
81
                    throw new InvalidArgumentException('Invalid callable provided.');
82
                }
83
84
                // Callable object is an instance with magic __invoke() method.
85 2
                return [$callable, '__invoke'];
86
            }
87
        }
88
89 21
        if (is_string($callable)) {
90
            // Existing function is always callable.
91 12
            if (function_exists($callable)) {
92 2
                return $callable;
93
            }
94 10
            if (method_exists($callable, '__invoke')) {
95
                // We allow to call class by name if `__invoke()` method is implemented.
96 1
                return [$callable, '__invoke'];
97
            }
98 9
            if (strpos($callable, '::') !== false) {
99
                // Replace "ClassName::methodName" string with ["ClassName", "methodName"] array.
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
100 8
                $callable = explode('::', $callable);
101
            }
102
        }
103
104
        // Is correct callable array.
105 18
        if (is_array($callable) && isset($callable[0], $callable[1]) && method_exists($callable[0], $callable[1])) {
106 16
            return $callable;
107
        }
108
109 2
        throw new InvalidArgumentException('Invalid callable provided.');
110
    }
111
}