1 | <?php |
||||
2 | |||||
3 | namespace Ballen\Clip; |
||||
4 | |||||
5 | use Ballen\Clip\Utilities\ArgumentsParser; |
||||
6 | use Ballen\Clip\Utilities\CommandRouter; |
||||
7 | use InvalidArgumentException; |
||||
8 | |||||
9 | /** |
||||
10 | * Clip |
||||
11 | * |
||||
12 | * A package for speeding up development of PHP console (CLI) applications. |
||||
13 | * |
||||
14 | * @author Bobby Allen <[email protected]> |
||||
15 | * @license https://raw.githubusercontent.com/bobsta63/clip/master/LICENSE |
||||
16 | * @link https://github.com/allebb/clip |
||||
17 | * @link http://www.bobbyallen.me |
||||
18 | * |
||||
19 | */ |
||||
20 | class ConsoleApplication |
||||
21 | { |
||||
22 | |||||
23 | /** |
||||
24 | * The CLI arguments |
||||
25 | * @var ArgumentsParser |
||||
26 | */ |
||||
27 | private $arguments; |
||||
28 | |||||
29 | /** |
||||
30 | * Command routing configuration. |
||||
31 | * @var CommandRouter |
||||
32 | */ |
||||
33 | private $router; |
||||
34 | |||||
35 | /** |
||||
36 | * Console Application Constructor |
||||
37 | * @param ArgumentsParser $argv The PHP $argv array (Pass $argv global if you wish to access the CLI arguments) |
||||
38 | */ |
||||
39 | 12 | public function __construct(ArgumentsParser $argv) |
|||
40 | { |
||||
41 | 12 | $this->arguments = $argv; |
|||
42 | 12 | $this->router = new CommandRouter(); |
|||
43 | } |
||||
44 | |||||
45 | /** |
||||
46 | * Returns the CLI arguments exposed to the CLI application. |
||||
47 | * @return ArgumentsParser |
||||
48 | */ |
||||
49 | 2 | public function arguments() |
|||
50 | { |
||||
51 | 2 | return $this->arguments; |
|||
52 | } |
||||
53 | |||||
54 | /** |
||||
55 | * Returns the router instance. |
||||
56 | * @return CommandRouter |
||||
57 | */ |
||||
58 | 2 | public function router() |
|||
59 | { |
||||
60 | 2 | return $this->router; |
|||
61 | } |
||||
62 | |||||
63 | /** |
||||
64 | * Enforces that the script must be run at the console. |
||||
65 | * @param boolean $enforced Enforce execution only through the CLI. |
||||
66 | * @param string $error_message Custom error message. |
||||
67 | * @return void |
||||
68 | */ |
||||
69 | public function enforceCli($enforced = false, $error_message = 'CLI execution permitted only!') |
||||
70 | { |
||||
71 | if ($enforced && (php_sapi_name() != "cli")) { |
||||
72 | die($error_message); |
||||
0 ignored issues
–
show
|
|||||
73 | } |
||||
74 | } |
||||
75 | |||||
76 | /** |
||||
77 | * Checks that the user is root! |
||||
78 | * @return boolean |
||||
79 | */ |
||||
80 | public function isSuperUser() |
||||
81 | { |
||||
82 | if (!function_exists('posix_getuid')) { |
||||
83 | throw new RuntimeException('The isSuperUser() method requires the PHP POSIX extention to be enabled!'); |
||||
0 ignored issues
–
show
|
|||||
84 | } |
||||
85 | if (posix_getuid() == 0) { |
||||
86 | return true; |
||||
87 | } |
||||
88 | return false; |
||||
89 | } |
||||
90 | |||||
91 | /** |
||||
92 | * Executes a system command. |
||||
93 | * @param string $command The command to execute. |
||||
94 | * @return string |
||||
95 | */ |
||||
96 | public function call($command) |
||||
97 | { |
||||
98 | return system($command); |
||||
99 | } |
||||
100 | |||||
101 | /** |
||||
102 | * Write to the console. |
||||
103 | * @param string $text The text to output. |
||||
104 | * @return \Ballen\Clip\ConsoleApplication |
||||
105 | */ |
||||
106 | public function write($text = '') |
||||
107 | { |
||||
108 | fwrite(STDOUT, $text); |
||||
109 | return $this; |
||||
110 | } |
||||
111 | |||||
112 | /** |
||||
113 | * Write a line of characters (or an empty line) to the CLI. |
||||
114 | * @param string $text The text to output. |
||||
115 | * @return \Ballen\Clip\ConsoleApplication |
||||
116 | */ |
||||
117 | public function writeln($text = '') |
||||
118 | { |
||||
119 | $this->write($text . PHP_EOL); |
||||
120 | return $this; |
||||
121 | } |
||||
122 | |||||
123 | /** |
||||
124 | * Request user input |
||||
125 | * @param string $question The input question/text |
||||
126 | * @param string $default A default value if one is not selected. |
||||
127 | * @param array $options Valid options that are acceptable, these are case insensitive! |
||||
128 | * @return string |
||||
129 | */ |
||||
130 | public function input($question, $default = '', $options = []) |
||||
131 | { |
||||
132 | if (empty($default)) { |
||||
133 | $this->write($question . ' '); |
||||
134 | } elseif (empty($options)) { |
||||
135 | $this->write($question . ' [' . $default . '] '); |
||||
136 | } else { |
||||
137 | $available_options = []; |
||||
138 | foreach (strtolower($options) as $option) { |
||||
0 ignored issues
–
show
$options of type array is incompatible with the type string expected by parameter $string of strtolower() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
139 | if ($option === strtolower($default)) { |
||||
140 | $option = strtoupper($option); |
||||
141 | } |
||||
142 | $available_options[] = $option; |
||||
143 | } |
||||
144 | $available_opts = rtrim(implode($available_options, '/'), '/'); |
||||
0 ignored issues
–
show
The call to
implode() has too many arguments starting with '/' .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
145 | $this->write($question . ' [' . $available_opts . '] '); |
||||
146 | } |
||||
147 | $answer = rtrim(fgets(STDIN), PHP_EOL); |
||||
148 | if (empty($answer)) { |
||||
149 | return $default; |
||||
150 | } |
||||
151 | if (count($options) > 0) { |
||||
152 | if (!in_array(strtolower($answer), array_map('strtolower', $options))) { |
||||
153 | return $this->input($question, $default, $options); |
||||
154 | } |
||||
155 | return $answer; |
||||
156 | } |
||||
157 | return $answer; |
||||
158 | } |
||||
159 | |||||
160 | /** |
||||
161 | * Writes an array to the CLI output |
||||
162 | * @param array $array The array of data to write to the console. |
||||
163 | * @return \Ballen\Clip\ConsoleApplication |
||||
164 | */ |
||||
165 | public function writearr($array = []) |
||||
166 | { |
||||
167 | print_r($array); |
||||
168 | return $this; |
||||
169 | } |
||||
170 | |||||
171 | /** |
||||
172 | * Exits with a specific status code. |
||||
173 | * @param int $status The status code to exit with. |
||||
174 | * @throws InvalidArgumentException |
||||
175 | */ |
||||
176 | public function exitWithStatus($status = 0) |
||||
177 | { |
||||
178 | if (!is_int($status)) { |
||||
0 ignored issues
–
show
|
|||||
179 | throw new InvalidArgumentException('The status code must be an integer value.'); |
||||
180 | } |
||||
181 | exit($status); |
||||
0 ignored issues
–
show
|
|||||
182 | } |
||||
183 | |||||
184 | /** |
||||
185 | * Exits the CLI with status code 0 (Successful) |
||||
186 | * @return void |
||||
187 | */ |
||||
188 | public function exitWithSuccess() |
||||
189 | { |
||||
190 | $this->exitWithStatus(0); |
||||
191 | } |
||||
192 | |||||
193 | /** |
||||
194 | * Exits the CLI with statu code 1 (Error) |
||||
195 | * @return void |
||||
196 | */ |
||||
197 | public function exitWithError() |
||||
198 | { |
||||
199 | $this->exitWithStatus(1); |
||||
200 | } |
||||
201 | |||||
202 | /** |
||||
203 | * Run the current application. |
||||
204 | * @return void |
||||
205 | */ |
||||
206 | public function run() |
||||
207 | { |
||||
208 | $this->router()->dispatch($this->arguments()->getCommand(1)); |
||||
0 ignored issues
–
show
It seems like
$this->arguments()->getCommand(1) can also be of type false ; however, parameter $call of Ballen\Clip\Utilities\CommandRouter::dispatch() 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
![]() |
|||||
209 | } |
||||
210 | } |
||||
211 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.