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); |
|
|
|
|
90
|
|
|
} |
91
|
18 |
|
if (strpos($handler, self::CHAR_AT) !== false) { |
92
|
8 |
|
return $this->fromAtNotation($handler); |
|
|
|
|
93
|
|
|
} |
94
|
10 |
|
if (strpos($handler, self::CHAR_DOT) !== false) { |
95
|
6 |
|
return $this->fromDotNotation($handler); |
|
|
|
|
96
|
|
|
} |
97
|
4 |
|
return $this->fromClassName($handler); |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
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) { |
|
|
|
|
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.