1 | <?php |
||||
2 | |||||
3 | namespace Ballen\Clip\Utilities; |
||||
4 | |||||
5 | use Ballen\Clip\Interfaces\CommandInterface; |
||||
6 | |||||
7 | /** |
||||
8 | * Clip |
||||
9 | * |
||||
10 | * A package for speeding up development of PHP console (CLI) applications. |
||||
11 | * |
||||
12 | * @author Bobby Allen <[email protected]> |
||||
13 | * @license https://raw.githubusercontent.com/bobsta63/clip/master/LICENSE |
||||
14 | * @link https://github.com/allebb/clip |
||||
15 | * @link http://www.bobbyallen.me |
||||
16 | * |
||||
17 | */ |
||||
18 | class ClassMethodHandler |
||||
19 | { |
||||
20 | |||||
21 | /** |
||||
22 | * Character for splitting the "dot" notation on command handlers. |
||||
23 | */ |
||||
24 | const CHAR_DOT = '.'; |
||||
25 | |||||
26 | /** |
||||
27 | * Character for splitting the "at" notation on command handlers. |
||||
28 | */ |
||||
29 | const CHAR_AT = '@'; |
||||
30 | |||||
31 | /** |
||||
32 | * Class of which will be instantiated at runtime. |
||||
33 | * @var string |
||||
34 | */ |
||||
35 | protected $class; |
||||
36 | |||||
37 | /** |
||||
38 | * The method of which should be called at runtime. |
||||
39 | * @var string |
||||
40 | */ |
||||
41 | protected $method = 'handle'; |
||||
42 | |||||
43 | /** |
||||
44 | * Optional argument(s) to pass through when calling the Class contructor. |
||||
45 | * @var mixed |
||||
46 | */ |
||||
47 | protected $constructor_arguments; |
||||
48 | |||||
49 | /** |
||||
50 | * Creates a new instance |
||||
51 | * @param string|array $handler |
||||
52 | * @param array $constructor_arguments Optional arguments to pass to the class constructor. |
||||
53 | */ |
||||
54 | 24 | public function __construct($handler, $constructor_arguments = []) |
|||
55 | { |
||||
56 | 24 | $this->constructor_arguments = $constructor_arguments; |
|||
57 | 24 | $this->extract($handler); |
|||
58 | 16 | $this->validate(); |
|||
59 | } |
||||
60 | |||||
61 | /** |
||||
62 | * Calls the requested class and method name passing in the optional arguments. |
||||
63 | * @param mixed $params Optional parameters to pass to the class method. |
||||
64 | * @return void |
||||
65 | */ |
||||
66 | 8 | public function call($params = null) |
|||
67 | { |
||||
68 | 8 | $method = $this->method; |
|||
69 | |||||
70 | 8 | if (!empty($this->constructor_arguments)) { |
|||
71 | 8 | $instance = new $this->class($this->constructor_arguments); |
|||
72 | } else { |
||||
73 | $instance = new $this->class(); |
||||
74 | } |
||||
75 | 8 | if (!is_null($params)) { |
|||
76 | 8 | return $instance->$method($params); |
|||
77 | } |
||||
78 | return $instance->$method(); |
||||
79 | } |
||||
80 | |||||
81 | /** |
||||
82 | * Extracts the class and method name. |
||||
83 | * @param string|array $handler The handler parameter |
||||
84 | * @return void |
||||
85 | */ |
||||
86 | 24 | private function extract($handler) |
|||
87 | { |
||||
88 | 24 | if (is_array($handler)) { |
|||
89 | 6 | return $this->fromClassMethodArray($handler); |
|||
0 ignored issues
–
show
|
|||||
90 | } |
||||
91 | 18 | if (strpos($handler, self::CHAR_AT) !== false) { |
|||
92 | 8 | return $this->fromAtNotation($handler); |
|||
0 ignored issues
–
show
Are you sure the usage of
$this->fromAtNotation($handler) targeting Ballen\Clip\Utilities\Cl...ndler::fromAtNotation() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
93 | } |
||||
94 | 10 | if (strpos($handler, self::CHAR_DOT) !== false) { |
|||
95 | 6 | return $this->fromDotNotation($handler); |
|||
0 ignored issues
–
show
Are you sure the usage of
$this->fromDotNotation($handler) targeting Ballen\Clip\Utilities\Cl...dler::fromDotNotation() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
96 | } |
||||
97 | 4 | return $this->fromClassName($handler); |
|||
0 ignored issues
–
show
Are you sure the usage of
$this->fromClassName($handler) targeting Ballen\Clip\Utilities\Cl...andler::fromClassName() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
98 | } |
||||
99 | |||||
100 | /** |
||||
101 | * Validates that the current class and methods exist and are callable. |
||||
102 | * @return void |
||||
103 | * @throws \RuntimeException |
||||
104 | */ |
||||
105 | 16 | private function validate() |
|||
106 | { |
||||
107 | 16 | if (!class_exists($this->class)) { |
|||
108 | 2 | throw new \RuntimeException(sprintf('Class %s does not exist, is this the correct namespace?', $this->class)); |
|||
109 | } |
||||
110 | 14 | if (!in_array($this->method, get_class_methods($this->class))) { |
|||
111 | 6 | throw new \RuntimeException(sprintf('The method "%s" does not exist in "%s" class.', $this->method, $this->class)); |
|||
112 | } |
||||
113 | } |
||||
114 | |||||
115 | /** |
||||
116 | * Extracts the class name and method from the Class Method string in "@" notation (eg. Class@Method). |
||||
117 | * @param string|array $handler The handler parameter |
||||
118 | * @return void |
||||
119 | * @throws \InvalidArgumentException |
||||
120 | */ |
||||
121 | 8 | private function fromAtNotation($handler) |
|||
122 | { |
||||
123 | 8 | $parts = explode(self::CHAR_AT, $handler); |
|||
0 ignored issues
–
show
It seems like
$handler can also be of type array ; however, parameter $string of explode() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
124 | 8 | if (count($parts) != 2) { |
|||
125 | 2 | throw new \InvalidArgumentException('Invalid Class Method format from "at" notation.'); |
|||
126 | } |
||||
127 | 6 | $this->class = $parts[0]; |
|||
128 | 6 | $this->method = $parts[1]; |
|||
129 | } |
||||
130 | |||||
131 | /** |
||||
132 | * Extracts the class name and method from the Class Method string in "dot" notation (eg. Class.Method). |
||||
133 | * @param string|array $handler The handler parameter |
||||
134 | * @return void |
||||
135 | * @throws \InvalidArgumentException |
||||
136 | */ |
||||
137 | 6 | private function fromDotNotation($handler) |
|||
138 | { |
||||
139 | 6 | $parts = explode(self::CHAR_DOT, $handler); |
|||
0 ignored issues
–
show
It seems like
$handler can also be of type array ; however, parameter $string of explode() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
140 | 6 | if (count($parts) != 2) { |
|||
141 | 2 | throw new \InvalidArgumentException('Invalid Class Method format from "dot" notation.'); |
|||
142 | } |
||||
143 | 4 | $this->class = $parts[0]; |
|||
144 | 4 | $this->method = $parts[1]; |
|||
145 | } |
||||
146 | |||||
147 | /** |
||||
148 | * Extracts the class name (no method present) from a single string. |
||||
149 | * @param string $handler The handler parameter |
||||
150 | * @return void |
||||
151 | * @throws \InvalidArgumentException |
||||
152 | */ |
||||
153 | 4 | private function fromClassName($handler) |
|||
154 | { |
||||
155 | 4 | if (!is_subclass_of($handler, CommandInterface::class)) { |
|||
156 | 2 | throw new \InvalidArgumentException(sprintf('The command class must implement the "CommandInterface" interface.')); |
|||
157 | } |
||||
158 | 2 | $this->class = $handler; |
|||
159 | } |
||||
160 | |||||
161 | /** |
||||
162 | * Extracts the class and method name from an array eg (['Class', 'Method']) |
||||
163 | * @param string|array $handler The handler parameter |
||||
164 | * @return void |
||||
165 | * @throws \InvalidArgumentException |
||||
166 | */ |
||||
167 | 6 | private function fromClassMethodArray($handler) |
|||
168 | { |
||||
169 | 6 | if (count($handler) != 2) { |
|||
0 ignored issues
–
show
It seems like
$handler can also be of type string ; however, parameter $value of count() does only seem to accept Countable|array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
170 | 2 | throw new \InvalidArgumentException('Class method array constructor can only contain 2 elements.'); |
|||
171 | } |
||||
172 | 4 | $this->class = $handler[0]; |
|||
173 | 4 | $this->method = $handler[1]; |
|||
174 | } |
||||
175 | } |
||||
176 |
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.