ReflectionMethodFactory::isAbstract()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace DependencyInjection\Internal;
4
5
class ReflectionMethodFactory implements ReflectionFactoryInterface
6
{
7
    /**
8
     * @var \ReflectionMethod
9
     */
10
    private $reflectionMethod;
11
12
    public function __construct($class, $name)
13
    {
14
        if (!is_string($class) && !is_object($class)) {
15
            throw Exception\ReflectionExceptionFactory::invalidArgument(
16
                sprintf("Parameter 1 of %s must be either class name or object.", __METHOD__)
17
            );
18
        }
19
20
        if (!isset($name) || !is_string($name)) {
21
            throw Exception\ReflectionExceptionFactory::invalidArgument(
22
                sprintf("Parameter 2 of %s must be either valid method name.", __METHOD__)
23
            );
24
        }
25
26
        $reflector = (is_string($class) ? ReflectionClassFactory::create($class)
27
            : ReflectionObjectFactory::create($class));
28
29
        if (!$reflector->hasMethod($name)) {
0 ignored issues
show
Bug introduced by
The method hasMethod does only exist in DependencyInjection\Inte...\ReflectionClassFactory, but not in DependencyInjection\Inte...ReflectionObjectFactory.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
30
            throw Exception\ReflectionExceptionFactory::reflectionInternal(
31
                sprintf("Class %s doesn't have method %s", __CLASS__, $name)
32
            );
33
        }
34
35
        $this->reflectionMethod = new \ReflectionMethod($class, $name);
36
    }
37
38
    public static function create($class, $name)
39
    {
40
        return new static($class, $name);
41
    }
42
43
    public static function export($class, $name, $return = false)
44
    {
45
        return \ReflectionMethod::export($class, $name, $return);
46
    }
47
48
    public function getClosure($object)
49
    {
50
        $closure = $this->reflectionMethod->getClosure($object);
51
52
        return ($closure instanceof \Closure ? $closure : null);
53
    }
54
55
    public function getDeclaringClass()
56
    {
57
        $declaringClass = $this->reflectionMethod->getDeclaringClass();
58
59
        return ($declaringClass instanceof \ReflectionClass ? $declaringClass : null);
60
    }
61
62
    public function getModifiers()
63
    {
64
        return $this->reflectionMethod->getModifiers();
65
    }
66
67
    public function getPrototype()
68
    {
69
        $prototype = $this->reflectionMethod->getPrototype();
70
71
        return ($prototype instanceof \ReflectionMethod ? $prototype : null);
72
    }
73
74
    public function invoke($object)
75
    {
76
        if (!is_object($object)) {
77
            throw Exception\ReflectionExceptionFactory::invalidArgument(
78
                sprintf("Parameter 1 of %s must be an object.", __METHOD__)
79
            );
80
        }
81
82
        return call_user_func_array([$this->reflectionMethod, 'invoke'],
83
            array_merge([$object], array_slice(func_get_args(), 1)));
84
    }
85
86
    public function invokeArgs($object, $args = [])
87
    {
88
        if (!is_object($object)) {
89
            throw Exception\ReflectionExceptionFactory::invalidArgument(
90
                sprintf("Parameter 1 of %s must be an object.", __METHOD__)
91
            );
92
        }
93
94
        if (!is_array($args)) {
95
            throw Exception\ReflectionExceptionFactory::invalidArgument(
96
                sprintf("Parameter 2 of %s must be an array.", __METHOD__)
97
            );
98
        }
99
100
        return $this->reflectionMethod->invokeArgs($object, $args);
101
    }
102
103
    public function isAbstract()
104
    {
105
        return $this->reflectionMethod->isAbstract();
106
    }
107
108
    public function isConstructor()
109
    {
110
        return $this->reflectionMethod->isConstructor();
111
    }
112
113
    public function isDestructor()
114
    {
115
        return $this->reflectionMethod->isDestructor();
116
    }
117
118
    public function isFinal()
119
    {
120
        return $this->reflectionMethod->isFinal();
121
    }
122
123
    public function isPrivate()
124
    {
125
        return $this->reflectionMethod->isPrivate();
126
    }
127
128
    public function isProtected()
129
    {
130
        return $this->reflectionMethod->isProtected();
131
    }
132
133
    public function isPublic()
134
    {
135
        return $this->reflectionMethod->isPublic();
136
    }
137
138
    public function isStatic()
139
    {
140
        return $this->reflectionMethod->isStatic();
141
    }
142
143
    public function setAccessible($accessible)
144
    {
145
        if (!is_bool($accessible)) {
146
            throw Exception\ReflectionExceptionFactory::invalidArgument(
147
                sprintf("Parameter 1 of %s must be a boolean.", __METHOD__)
148
            );
149
        }
150
151
        $this->reflectionMethod->setAccessible($accessible);
152
    }
153
154
    public function __toString()
155
    {
156
        return (string)$this->reflectionMethod;
157
    }
158
159
    public function getReflector()
160
    {
161
        return $this->reflectionMethod;
162
    }
163
}
164