91% of 1249OPs |
99% of 221Lines |
84% of 136Branches |
65% of 98Paths |
# | |
---|---|
1 |
<?php |
2 |
|
3 |
namespace mageekguy\atoum; |
4 |
|
5 |
use |
6 |
mageekguy\atoum, |
7 |
mageekguy\atoum\script, |
8 |
mageekguy\atoum\writer, |
9 |
mageekguy\atoum\writers, |
10 |
mageekguy\atoum\exceptions |
11 |
; |
12 |
|
13 |
abstract class script |
14 |
{ |
15 |
const padding = ' '; |
16 |
|
17 |
protected $name = ''; |
18 |
protected $locale = null; |
19 |
protected $adapter = null; |
20 |
protected $prompt = null; |
21 |
protected $cli = null; |
22 |
protected $verbosityLevel = 0; |
23 |
protected $outputWriter = null; |
24 |
protected $infoWriter = null; |
25 |
protected $warningWriter = null; |
26 |
protected $errorWriter = null; |
27 |
protected $helpWriter = null; |
28 |
protected $argumentsParser = null; |
29 |
|
30 |
private $doRun = true; |
31 |
private $help = array(); |
32 |
|
33 |
public function __construct($name, atoum\adapter $adapter = null)100% |
34 |
{ |
35 |
$this->name = (string) $name; |
36 |
|
37 |
$this |
38 |
->setCli() |
39 |
->setAdapter($adapter) |
40 |
->setLocale() |
41 |
->setPrompt() |
42 |
->setArgumentsParser() |
43 |
->setOutputWriter() |
44 |
->setInfoWriter() |
45 |
->setErrorWriter() |
46 |
->setWarningWriter() |
47 |
->setHelpWriter() |
48 |
; |
49 |
|
50 |
if ($this->adapter->php_sapi_name() !== 'cli') |
51 |
{ |
52 |
throw new exceptions\logic('\'' . $this->getName() . '\' must be used in CLI only'); |
53 |
} |
54 |
} |
55 |
|
56 |
public function getDirectory()100% |
57 |
{ |
58 |
$directory = $this->adapter->dirname($this->getName()); |
59 |
|
60 |
if ($this->adapter->is_dir($directory) === false) |
61 |
{ |
62 |
$directory = $this->adapter->getcwd(); |
63 |
} |
64 |
|
65 |
return rtrim($directory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; |
66 |
} |
67 |
|
68 |
public function setAdapter(atoum\adapter $adapter = null)100% |
69 |
{ |
70 |
$this->adapter = $adapter ?: new atoum\adapter(); |
71 |
|
72 |
return $this; |
73 |
} |
74 |
|
75 |
public function getAdapter()100% |
76 |
{ |
77 |
return $this->adapter; |
78 |
} |
79 |
|
80 |
public function setLocale(atoum\locale $locale = null)100% |
81 |
{ |
82 |
$this->locale = $locale ?: new atoum\locale(); |
83 |
|
84 |
return $this; |
85 |
} |
86 |
|
87 |
public function getLocale()100% |
88 |
{ |
89 |
return $this->locale; |
90 |
} |
91 |
|
92 |
public function setArgumentsParser(script\arguments\parser $parser = null)100% |
93 |
{ |
94 |
$this->argumentsParser = $parser ?: new script\arguments\parser(); |
95 |
|
96 |
$this->setArgumentHandlers(); |
97 |
|
98 |
return $this; |
99 |
} |
100 |
|
101 |
public function getArgumentsParser()100% |
102 |
{ |
103 |
return $this->argumentsParser; |
104 |
} |
105 |
|
106 |
public function setCli(atoum\cli $cli = null) |
107 |
{ |
108 |
$this->cli = $cli ?: new atoum\cli(); |
109 |
|
110 |
return $this; |
111 |
} |
112 |
|
113 |
public function getCli()100% |
114 |
{ |
115 |
return $this->cli; |
116 |
} |
117 |
|
118 |
public function hasArguments()50% |
119 |
{ |
120 |
return (sizeof($this->argumentsParser->getValues()) > 0); |
121 |
} |
122 |
|
123 |
public function setOutputWriter(atoum\writer $writer = null) |
124 |
{ |
125 |
$this->outputWriter = $writer ?: new writers\std\out($this->cli); |
126 |
|
127 |
return $this; |
128 |
} |
129 |
|
130 |
public function getOutputWriter()100% |
131 |
{ |
132 |
return $this->outputWriter; |
133 |
} |
134 |
|
135 |
public function setInfoWriter(atoum\writer $writer = null)100% |
136 |
{ |
137 |
if ($writer === null) |
138 |
{ |
139 |
$writer = new writers\std\out($this->cli); |
140 |
$writer |
141 |
->addDecorator(new writer\decorators\rtrim()) |
142 |
->addDecorator(new writer\decorators\eol()) |
143 |
->addDecorator(new atoum\cli\clear()) |
144 |
; |
145 |
} |
146 |
|
147 |
$this->infoWriter = $writer; |
148 |
|
149 |
return $this; |
150 |
} |
151 |
|
152 |
public function getInfoWriter() |
153 |
{ |
154 |
return $this->infoWriter; |
155 |
} |
156 |
|
157 |
public function setWarningWriter(atoum\writer $writer = null)100% |
158 |
{ |
159 |
if ($writer === null) |
160 |
{ |
161 |
$writer = new writers\std\err($this->cli); |
162 |
$writer |
163 |
->addDecorator(new writer\decorators\trim()) |
164 |
->addDecorator(new writer\decorators\prompt($this->locale->_('Warning: '))) |
165 |
->addDecorator(new writer\decorators\eol()) |
166 |
->addDecorator(new atoum\cli\clear()) |
167 |
; |
168 |
} |
169 |
|
170 |
$this->warningWriter = $writer; |
171 |
|
172 |
return $this; |
173 |
} |
174 |
|
175 |
public function getWarningWriter()100% |
176 |
{ |
177 |
return $this->warningWriter; |
178 |
} |
179 |
|
180 |
public function setErrorWriter(atoum\writer $writer = null)100% |
181 |
{ |
182 |
if ($writer === null) |
183 |
{ |
184 |
$writer = new writers\std\err($this->cli); |
185 |
$writer |
186 |
->addDecorator(new writer\decorators\trim()) |
187 |
->addDecorator(new writer\decorators\prompt($this->locale->_('Error: '))) |
188 |
->addDecorator(new writer\decorators\eol()) |
189 |
->addDecorator(new atoum\cli\clear()) |
190 |
; |
191 |
} |
192 | |
193 |
$this->errorWriter = $writer; |
194 |
|
195 |
return $this; |
196 |
} |
197 |
|
198 |
public function getErrorWriter()100% |
199 |
{ |
200 |
return $this->errorWriter; |
201 |
} |
202 |
|
203 |
public function setHelpWriter(atoum\writer $writer = null)100% |
204 |
{ |
205 |
if ($writer === null) |
206 |
{ |
207 |
$labelColorizer = new cli\colorizer('0;32'); |
208 |
$labelColorizer->setPattern('/(^[^:]+: )/'); |
209 |
|
210 |
$argumentColorizer = new cli\colorizer('0;32'); |
211 |
$argumentColorizer->setPattern('/((?:^| )[-+]+[-a-z]+)/'); |
212 | |
213 |
$valueColorizer = new cli\colorizer('0;34'); |
214 |
$valueColorizer->setPattern('/(<[^>]+>(?:\.\.\.)?)/'); |
215 |
|
216 |
$writer = new writers\std\out(); |
217 |
$writer |
218 |
->addDecorator($labelColorizer) |
219 |
->addDecorator($valueColorizer) |
220 |
->addDecorator($argumentColorizer) |
221 |
->addDecorator(new writer\decorators\rtrim()) |
222 |
->addDecorator(new writer\decorators\eol()) |
223 |
->addDecorator(new atoum\cli\clear()) |
224 |
; |
225 |
} |
226 | |
227 |
$this->helpWriter = $writer; |
228 |
|
229 |
return $this; |
230 |
} |
231 |
|
232 |
public function getHelpWriter()100% |
233 |
{ |
234 |
return $this->helpWriter; |
235 |
} |
236 |
|
237 |
public function setPrompt(script\prompt $prompt = null)100% |
238 |
{ |
239 |
if ($prompt === null) |
240 |
{ |
241 |
$prompt = new script\prompt(); |
242 |
} |
243 |
|
244 |
$this->prompt = $prompt->setOutputWriter($this->outputWriter); |
245 |
|
246 |
return $this; |
247 |
} |
248 |
|
249 |
public function getPrompt()100% |
250 |
{ |
251 |
return $this->prompt; |
252 |
} |
253 |
|
254 |
public function getName()100% |
255 |
{ |
256 |
return $this->name; |
257 |
} |
258 |
|
259 |
public function getHelp()100% |
260 |
{ |
261 |
return $this->help; |
262 |
} |
263 |
|
264 |
public function help()100% |
265 |
{ |
266 |
return $this |
267 |
->writeHelpUsage() |
268 |
->writeHelpOptions() |
269 |
->stopRun() |
270 |
; |
271 |
} |
272 |
|
273 |
public function addArgumentHandler(\closure $handler, array $arguments, $values = null, $help = null, $priority = 0)100% |
274 |
{ |
275 |
if ($help !== null) |
276 |
{ |
277 |
$this->help[] = array($arguments, $values, $help); |
278 |
} |
279 |
|
280 |
$this->argumentsParser->addHandler($handler, $arguments, $priority); |
281 |
|
282 |
return $this; |
283 |
} |
284 |
|
285 |
public function setDefaultArgumentHandler(\closure $handler)100% |
286 |
{ |
287 |
$this->argumentsParser->setDefaultHandler($handler); |
288 |
|
289 |
return $this; |
290 |
} |
291 |
|
292 |
public function run(array $arguments = array())100% |
293 |
{ |
294 |
$this->adapter->ini_set('log_errors_max_len', 0); |
295 |
$this->adapter->ini_set('log_errors', 'Off'); |
296 |
$this->adapter->ini_set('display_errors', 'stderr'); |
297 |
|
298 |
$this->doRun = true; |
299 |
|
300 |
if ($this->parseArguments($arguments)->doRun === true) |
301 |
{ |
302 |
$this->doRun(); |
303 |
} |
304 |
|
305 |
return $this; |
306 |
} |
307 |
|
308 |
public function prompt($message)100% |
309 |
{ |
310 |
return trim($this->prompt->ask(rtrim($message))); |
311 |
} |
312 |
|
313 |
public function writeLabel($label, $value, $level = 0)100% |
314 |
{ |
315 |
static::writeLabelWithWriter($label, $value, $level, $this->helpWriter); |
316 | |
317 |
return $this; |
318 |
} |
319 |
|
320 |
public function writeLabels(array $labels, $level = 1)100% |
321 |
{ |
322 |
static::writeLabelsWithWriter($labels, $level, $this->helpWriter); |
323 |
|
324 |
return $this; |
325 |
} |
326 |
|
327 |
public function clearMessage()100% |
328 |
{ |
329 |
$this->outputWriter->clear(); |
330 |
|
331 |
return $this; |
332 |
} |
333 |
|
334 |
public function writeMessage($message)100% |
335 |
{ |
336 |
$this->outputWriter |
337 |
->removeDecorators() |
338 |
->write($message) |
339 |
; |
340 |
|
341 |
return $this; |
342 |
} |
343 |
|
344 |
public function writeInfo($info)100% |
345 |
{ |
346 |
$this->infoWriter->write($info); |
347 | |
348 |
return $this; |
349 |
} |
350 |
|
351 |
public function writeHelp($message)100% |
352 |
{ |
353 |
$this->helpWriter->write($message); |
354 |
|
355 |
return $this; |
356 |
} |
357 |
|
358 |
public function writeWarning($warning)100% |
359 |
{ |
360 |
$this->warningWriter->write($warning); |
361 |
|
362 |
return $this; |
363 |
} |
364 |
|
365 |
public function writeError($message)100% |
366 |
{ |
367 |
$this->errorWriter->write($message); |
368 |
|
369 |
return $this; |
370 |
} |
371 |
|
372 |
public function verbose($message, $verbosityLevel = 1)100% |
373 |
{ |
374 |
if ($verbosityLevel > 0 && $this->verbosityLevel >= $verbosityLevel) |
375 |
{ |
376 |
$this->writeInfo($message); |
377 |
} |
378 |
|
379 |
return $this; |
380 |
} |
381 |
|
382 |
public function increaseVerbosityLevel()100% |
383 |
{ |
384 |
$this->verbosityLevel++; |
385 |
|
386 |
return $this; |
387 |
} |
388 |
|
389 |
public function decreaseVerbosityLevel()100% |
390 |
{ |
391 |
if ($this->verbosityLevel > 0) |
392 |
{ |
393 |
$this->verbosityLevel--; |
394 |
} |
395 |
|
396 |
return $this; |
397 |
} |
398 |
|
399 |
public function getVerbosityLevel()100% |
400 |
{ |
401 |
return $this->verbosityLevel; |
402 |
} |
403 |
|
404 |
public function resetVerbosityLevel()100% |
405 |
{ |
406 |
$this->verbosityLevel = 0; |
407 | |
408 |
return $this; |
409 |
} |
410 |
|
411 |
protected function setArgumentHandlers()100% |
412 |
{ |
413 |
$this->argumentsParser->resetHandlers(); |
414 |
|
415 |
$this->help = array(); |
416 |
|
417 |
return $this; |
418 |
} |
419 |
|
420 |
protected function canRun()0% |
421 |
{ |
422 |
return ($this->doRun === true); |
423 |
} |
424 |
|
425 |
protected function stopRun()100% |
426 |
{ |
427 |
$this->doRun = false; |
428 |
|
429 |
return $this; |
430 |
} |
431 |
|
432 |
protected function writeHelpUsage()100% |
433 |
{ |
434 |
if ($this->help) |
435 |
{ |
436 |
$this->writeHelp(sprintf($this->locale->_('Usage: %s [options]'), $this->getName())); |
437 |
} |
438 |
|
439 |
return $this; |
440 |
} |
441 |
|
442 |
protected function writeHelpOptions()100% |
443 |
{ |
444 |
if ($this->help) |
445 |
{ |
446 |
$arguments = array(); |
447 |
|
448 |
foreach ($this->help as $help) |
449 |
{ |
450 |
if ($help[1] !== null) |
451 |
{ |
452 |
foreach ($help[0] as & $argument) |
453 |
{ |
454 |
$argument .= ' ' . $help[1]; |
455 |
} |
456 |
} |
457 |
|
458 |
$arguments[join(', ', $help[0])] = $help[2]; |
459 |
} |
460 |
|
461 |
$this->writeHelp($this->locale->_('Available options are:')); |
462 |
|
463 |
static::writeLabelsWithWriter($arguments, 1, $this->helpWriter); |
464 |
} |
465 |
|
466 |
return $this; |
467 |
} |
468 |
|
469 |
protected function parseArguments(array $arguments)100% |
470 |
{ |
471 |
$this->argumentsParser->parse($this, $arguments); |
472 |
|
473 |
return $this; |
474 |
} |
475 |
|
476 |
protected function doRun()100% |
477 |
{ |
478 |
return $this; |
479 |
} |
480 |
|
481 |
protected static function writeLabelWithWriter($label, $value, $level, writer $writer)100% |
482 |
{ |
483 |
return $writer->write(($level <= 0 ? '' : str_repeat(self::padding, $level)) . (preg_match('/^ +$/', $label) ? $label : rtrim($label)) . ': ' . trim($value)); |
484 |
} |
485 |
|
486 |
protected static function writeLabelsWithWriter($labels, $level, writer $writer)100% |
487 |
{ |
488 |
$maxLength = 0; |
489 |
|
490 |
foreach (array_keys($labels) as $label) |
491 |
{ |
492 |
$length = strlen($label); |
493 |
|
494 |
if ($length > $maxLength) |
495 |
{ |
496 |
$maxLength = $length; |
497 |
} |
498 |
} |
499 |
|
500 |
foreach ($labels as $label => $value) |
501 |
{ |
502 |
$value = explode("\n", trim($value)); |
503 |
|
504 |
static::writeLabelWithWriter(str_pad($label, $maxLength, ' ', STR_PAD_LEFT), $value[0], $level, $writer); |
505 |
|
506 |
if (sizeof($value) > 1) |
507 |
{ |
508 |
foreach (array_slice($value, 1) as $line) |
509 |
{ |
510 |
static::writeLabelWithWriter(str_repeat(' ', $maxLength), $line, $level, $writer); |
511 |
} |
512 |
} |
513 |
} |
514 |
|
515 |
return $writer; |
516 |
} |
517 |
} |