Mercurial > hg > rc1
comparison vendor/sabre/vobject/lib/Cli.php @ 7:430dbd5346f7
vendor sabre as distributed
| author | Charlie Root |
|---|---|
| date | Sat, 13 Jan 2018 09:06:10 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 6:cec75ba50afc | 7:430dbd5346f7 |
|---|---|
| 1 <?php | |
| 2 | |
| 3 namespace Sabre\VObject; | |
| 4 | |
| 5 use | |
| 6 InvalidArgumentException; | |
| 7 | |
| 8 /** | |
| 9 * This is the CLI interface for sabre-vobject. | |
| 10 * | |
| 11 * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). | |
| 12 * @author Evert Pot (http://evertpot.com/) | |
| 13 * @license http://sabre.io/license/ Modified BSD License | |
| 14 */ | |
| 15 class Cli { | |
| 16 | |
| 17 /** | |
| 18 * No output | |
| 19 * | |
| 20 * @var bool | |
| 21 */ | |
| 22 protected $quiet = false; | |
| 23 | |
| 24 /** | |
| 25 * Help display | |
| 26 * | |
| 27 * @var bool | |
| 28 */ | |
| 29 protected $showHelp = false; | |
| 30 | |
| 31 /** | |
| 32 * Wether to spit out 'mimedir' or 'json' format. | |
| 33 * | |
| 34 * @var string | |
| 35 */ | |
| 36 protected $format; | |
| 37 | |
| 38 /** | |
| 39 * JSON pretty print | |
| 40 * | |
| 41 * @var bool | |
| 42 */ | |
| 43 protected $pretty; | |
| 44 | |
| 45 /** | |
| 46 * Source file | |
| 47 * | |
| 48 * @var string | |
| 49 */ | |
| 50 protected $inputPath; | |
| 51 | |
| 52 /** | |
| 53 * Destination file | |
| 54 * | |
| 55 * @var string | |
| 56 */ | |
| 57 protected $outputPath; | |
| 58 | |
| 59 /** | |
| 60 * output stream | |
| 61 * | |
| 62 * @var resource | |
| 63 */ | |
| 64 protected $stdout; | |
| 65 | |
| 66 /** | |
| 67 * stdin | |
| 68 * | |
| 69 * @var resource | |
| 70 */ | |
| 71 protected $stdin; | |
| 72 | |
| 73 /** | |
| 74 * stderr | |
| 75 * | |
| 76 * @var resource | |
| 77 */ | |
| 78 protected $stderr; | |
| 79 | |
| 80 /** | |
| 81 * Input format (one of json or mimedir) | |
| 82 * | |
| 83 * @var string | |
| 84 */ | |
| 85 protected $inputFormat; | |
| 86 | |
| 87 /** | |
| 88 * Makes the parser less strict. | |
| 89 * | |
| 90 * @var bool | |
| 91 */ | |
| 92 protected $forgiving = false; | |
| 93 | |
| 94 /** | |
| 95 * Main function | |
| 96 * | |
| 97 * @return int | |
| 98 */ | |
| 99 public function main(array $argv) { | |
| 100 | |
| 101 // @codeCoverageIgnoreStart | |
| 102 // We cannot easily test this, so we'll skip it. Pretty basic anyway. | |
| 103 | |
| 104 if (!$this->stderr) { | |
| 105 $this->stderr = fopen('php://stderr', 'w'); | |
| 106 } | |
| 107 if (!$this->stdout) { | |
| 108 $this->stdout = fopen('php://stdout', 'w'); | |
| 109 } | |
| 110 if (!$this->stdin) { | |
| 111 $this->stdin = fopen('php://stdin', 'r'); | |
| 112 } | |
| 113 | |
| 114 // @codeCoverageIgnoreEnd | |
| 115 | |
| 116 | |
| 117 try { | |
| 118 | |
| 119 list($options, $positional) = $this->parseArguments($argv); | |
| 120 | |
| 121 if (isset($options['q'])) { | |
| 122 $this->quiet = true; | |
| 123 } | |
| 124 $this->log($this->colorize('green', "sabre/vobject ") . $this->colorize('yellow', Version::VERSION)); | |
| 125 | |
| 126 foreach($options as $name=>$value) { | |
| 127 | |
| 128 switch($name) { | |
| 129 | |
| 130 case 'q' : | |
| 131 // Already handled earlier. | |
| 132 break; | |
| 133 case 'h' : | |
| 134 case 'help' : | |
| 135 $this->showHelp(); | |
| 136 return 0; | |
| 137 break; | |
| 138 case 'format' : | |
| 139 switch($value) { | |
| 140 | |
| 141 // jcard/jcal documents | |
| 142 case 'jcard' : | |
| 143 case 'jcal' : | |
| 144 | |
| 145 // specific document versions | |
| 146 case 'vcard21' : | |
| 147 case 'vcard30' : | |
| 148 case 'vcard40' : | |
| 149 case 'icalendar20' : | |
| 150 | |
| 151 // specific formats | |
| 152 case 'json' : | |
| 153 case 'mimedir' : | |
| 154 | |
| 155 // icalendar/vcad | |
| 156 case 'icalendar' : | |
| 157 case 'vcard' : | |
| 158 $this->format = $value; | |
| 159 break; | |
| 160 | |
| 161 default : | |
| 162 throw new InvalidArgumentException('Unknown format: ' . $value); | |
| 163 | |
| 164 } | |
| 165 break; | |
| 166 case 'pretty' : | |
| 167 if (version_compare(PHP_VERSION, '5.4.0') >= 0) { | |
| 168 $this->pretty = true; | |
| 169 } | |
| 170 break; | |
| 171 case 'forgiving' : | |
| 172 $this->forgiving = true; | |
| 173 break; | |
| 174 case 'inputformat' : | |
| 175 switch($value) { | |
| 176 // json formats | |
| 177 case 'jcard' : | |
| 178 case 'jcal' : | |
| 179 case 'json' : | |
| 180 $this->inputFormat = 'json'; | |
| 181 break; | |
| 182 | |
| 183 // mimedir formats | |
| 184 case 'mimedir' : | |
| 185 case 'icalendar' : | |
| 186 case 'vcard' : | |
| 187 case 'vcard21' : | |
| 188 case 'vcard30' : | |
| 189 case 'vcard40' : | |
| 190 case 'icalendar20' : | |
| 191 | |
| 192 $this->inputFormat = 'mimedir'; | |
| 193 break; | |
| 194 | |
| 195 default : | |
| 196 throw new InvalidArgumentException('Unknown format: ' . $value); | |
| 197 | |
| 198 } | |
| 199 break; | |
| 200 default : | |
| 201 throw new InvalidArgumentException('Unknown option: ' . $name); | |
| 202 | |
| 203 } | |
| 204 | |
| 205 } | |
| 206 | |
| 207 if (count($positional) === 0) { | |
| 208 $this->showHelp(); | |
| 209 return 1; | |
| 210 } | |
| 211 | |
| 212 if (count($positional) === 1) { | |
| 213 throw new InvalidArgumentException('Inputfile is a required argument'); | |
| 214 } | |
| 215 | |
| 216 if (count($positional) > 3) { | |
| 217 throw new InvalidArgumentException('Too many arguments'); | |
| 218 } | |
| 219 | |
| 220 if (!in_array($positional[0], array('validate','repair','convert','color'))) { | |
| 221 throw new InvalidArgumentException('Uknown command: ' . $positional[0]); | |
| 222 } | |
| 223 | |
| 224 } catch (InvalidArgumentException $e) { | |
| 225 $this->showHelp(); | |
| 226 $this->log('Error: ' . $e->getMessage(), 'red'); | |
| 227 return 1; | |
| 228 } | |
| 229 | |
| 230 $command = $positional[0]; | |
| 231 | |
| 232 $this->inputPath = $positional[1]; | |
| 233 $this->outputPath = isset($positional[2])?$positional[2]:'-'; | |
| 234 | |
| 235 if ($this->outputPath !== '-') { | |
| 236 $this->stdout = fopen($this->outputPath, 'w'); | |
| 237 } | |
| 238 | |
| 239 if (!$this->inputFormat) { | |
| 240 if (substr($this->inputPath, -5)==='.json') { | |
| 241 $this->inputFormat = 'json'; | |
| 242 } else { | |
| 243 $this->inputFormat = 'mimedir'; | |
| 244 } | |
| 245 } | |
| 246 if (!$this->format) { | |
| 247 if (substr($this->outputPath,-5)==='.json') { | |
| 248 $this->format = 'json'; | |
| 249 } else { | |
| 250 $this->format = 'mimedir'; | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 | |
| 255 $realCode = 0; | |
| 256 | |
| 257 try { | |
| 258 | |
| 259 while($input = $this->readInput()) { | |
| 260 | |
| 261 $returnCode = $this->$command($input); | |
| 262 if ($returnCode!==0) $realCode = $returnCode; | |
| 263 | |
| 264 } | |
| 265 | |
| 266 } catch (EofException $e) { | |
| 267 // end of file | |
| 268 } catch (\Exception $e) { | |
| 269 $this->log('Error: ' . $e->getMessage(),'red'); | |
| 270 return 2; | |
| 271 } | |
| 272 | |
| 273 return $realCode; | |
| 274 | |
| 275 } | |
| 276 | |
| 277 /** | |
| 278 * Shows the help message. | |
| 279 * | |
| 280 * @return void | |
| 281 */ | |
| 282 protected function showHelp() { | |
| 283 | |
| 284 $this->log('Usage:', 'yellow'); | |
| 285 $this->log(" vobject [options] command [arguments]"); | |
| 286 $this->log(''); | |
| 287 $this->log('Options:', 'yellow'); | |
| 288 $this->log($this->colorize('green', ' -q ') . "Don't output anything."); | |
| 289 $this->log($this->colorize('green', ' -help -h ') . "Display this help message."); | |
| 290 $this->log($this->colorize('green', ' --format ') . "Convert to a specific format. Must be one of: vcard, vcard21,"); | |
| 291 $this->log($this->colorize('green', ' --forgiving ') . "Makes the parser less strict."); | |
| 292 $this->log(" vcard30, vcard40, icalendar20, jcal, jcard, json, mimedir."); | |
| 293 $this->log($this->colorize('green', ' --inputformat ') . "If the input format cannot be guessed from the extension, it"); | |
| 294 $this->log(" must be specified here."); | |
| 295 // Only PHP 5.4 and up | |
| 296 if (version_compare(PHP_VERSION, '5.4.0') >= 0) { | |
| 297 $this->log($this->colorize('green', ' --pretty ') . "json pretty-print."); | |
| 298 } | |
| 299 $this->log(''); | |
| 300 $this->log('Commands:', 'yellow'); | |
| 301 $this->log($this->colorize('green', ' validate') . ' source_file Validates a file for correctness.'); | |
| 302 $this->log($this->colorize('green', ' repair') . ' source_file [output_file] Repairs a file.'); | |
| 303 $this->log($this->colorize('green', ' convert') . ' source_file [output_file] Converts a file.'); | |
| 304 $this->log($this->colorize('green', ' color') . ' source_file Colorize a file, useful for debbugging.'); | |
| 305 $this->log( | |
| 306 <<<HELP | |
| 307 | |
| 308 If source_file is set as '-', STDIN will be used. | |
| 309 If output_file is omitted, STDOUT will be used. | |
| 310 All other output is sent to STDERR. | |
| 311 | |
| 312 HELP | |
| 313 ); | |
| 314 | |
| 315 $this->log('Examples:', 'yellow'); | |
| 316 $this->log(' vobject convert contact.vcf contact.json'); | |
| 317 $this->log(' vobject convert --format=vcard40 old.vcf new.vcf'); | |
| 318 $this->log(' vobject convert --inputformat=json --format=mimedir - -'); | |
| 319 $this->log(' vobject color calendar.ics'); | |
| 320 $this->log(''); | |
| 321 $this->log('https://github.com/fruux/sabre-vobject','purple'); | |
| 322 | |
| 323 } | |
| 324 | |
| 325 /** | |
| 326 * Validates a VObject file | |
| 327 * | |
| 328 * @param Component $vObj | |
| 329 * @return int | |
| 330 */ | |
| 331 protected function validate($vObj) { | |
| 332 | |
| 333 $returnCode = 0; | |
| 334 | |
| 335 switch($vObj->name) { | |
| 336 case 'VCALENDAR' : | |
| 337 $this->log("iCalendar: " . (string)$vObj->VERSION); | |
| 338 break; | |
| 339 case 'VCARD' : | |
| 340 $this->log("vCard: " . (string)$vObj->VERSION); | |
| 341 break; | |
| 342 } | |
| 343 | |
| 344 $warnings = $vObj->validate(); | |
| 345 if (!count($warnings)) { | |
| 346 $this->log(" No warnings!"); | |
| 347 } else { | |
| 348 | |
| 349 $levels = array( | |
| 350 1 => 'REPAIRED', | |
| 351 2 => 'WARNING', | |
| 352 3 => 'ERROR', | |
| 353 ); | |
| 354 $returnCode = 2; | |
| 355 foreach($warnings as $warn) { | |
| 356 | |
| 357 $extra = ''; | |
| 358 if ($warn['node'] instanceof Property) { | |
| 359 $extra = ' (property: "' . $warn['node']->name . '")'; | |
| 360 } | |
| 361 $this->log(" [" . $levels[$warn['level']] . '] ' . $warn['message'] . $extra); | |
| 362 | |
| 363 } | |
| 364 | |
| 365 } | |
| 366 | |
| 367 return $returnCode; | |
| 368 | |
| 369 } | |
| 370 | |
| 371 /** | |
| 372 * Repairs a VObject file | |
| 373 * | |
| 374 * @param Component $vObj | |
| 375 * @return int | |
| 376 */ | |
| 377 protected function repair($vObj) { | |
| 378 | |
| 379 $returnCode = 0; | |
| 380 | |
| 381 switch($vObj->name) { | |
| 382 case 'VCALENDAR' : | |
| 383 $this->log("iCalendar: " . (string)$vObj->VERSION); | |
| 384 break; | |
| 385 case 'VCARD' : | |
| 386 $this->log("vCard: " . (string)$vObj->VERSION); | |
| 387 break; | |
| 388 } | |
| 389 | |
| 390 $warnings = $vObj->validate(Node::REPAIR); | |
| 391 if (!count($warnings)) { | |
| 392 $this->log(" No warnings!"); | |
| 393 } else { | |
| 394 | |
| 395 $levels = array( | |
| 396 1 => 'REPAIRED', | |
| 397 2 => 'WARNING', | |
| 398 3 => 'ERROR', | |
| 399 ); | |
| 400 $returnCode = 2; | |
| 401 foreach($warnings as $warn) { | |
| 402 | |
| 403 $extra = ''; | |
| 404 if ($warn['node'] instanceof Property) { | |
| 405 $extra = ' (property: "' . $warn['node']->name . '")'; | |
| 406 } | |
| 407 $this->log(" [" . $levels[$warn['level']] . '] ' . $warn['message'] . $extra); | |
| 408 | |
| 409 } | |
| 410 | |
| 411 } | |
| 412 fwrite($this->stdout, $vObj->serialize()); | |
| 413 | |
| 414 return $returnCode; | |
| 415 | |
| 416 } | |
| 417 | |
| 418 /** | |
| 419 * Converts a vObject file to a new format. | |
| 420 * | |
| 421 * @param Component $vObj | |
| 422 * @return int | |
| 423 */ | |
| 424 protected function convert($vObj) { | |
| 425 | |
| 426 $json = false; | |
| 427 $convertVersion = null; | |
| 428 $forceInput = null; | |
| 429 | |
| 430 switch($this->format) { | |
| 431 case 'json' : | |
| 432 $json = true; | |
| 433 if ($vObj->name === 'VCARD') { | |
| 434 $convertVersion = Document::VCARD40; | |
| 435 } | |
| 436 break; | |
| 437 case 'jcard' : | |
| 438 $json = true; | |
| 439 $forceInput = 'VCARD'; | |
| 440 $convertVersion = Document::VCARD40; | |
| 441 break; | |
| 442 case 'jcal' : | |
| 443 $json = true; | |
| 444 $forceInput = 'VCALENDAR'; | |
| 445 break; | |
| 446 case 'mimedir' : | |
| 447 case 'icalendar' : | |
| 448 case 'icalendar20' : | |
| 449 case 'vcard' : | |
| 450 break; | |
| 451 case 'vcard21' : | |
| 452 $convertVersion = Document::VCARD21; | |
| 453 break; | |
| 454 case 'vcard30' : | |
| 455 $convertVersion = Document::VCARD30; | |
| 456 break; | |
| 457 case 'vcard40' : | |
| 458 $convertVersion = Document::VCARD40; | |
| 459 break; | |
| 460 | |
| 461 } | |
| 462 | |
| 463 if ($forceInput && $vObj->name !== $forceInput) { | |
| 464 throw new \Exception('You cannot convert a ' . strtolower($vObj->name) . ' to ' . $this->format); | |
| 465 } | |
| 466 if ($convertVersion) { | |
| 467 $vObj = $vObj->convert($convertVersion); | |
| 468 } | |
| 469 if ($json) { | |
| 470 $jsonOptions = 0; | |
| 471 if ($this->pretty) { | |
| 472 $jsonOptions = JSON_PRETTY_PRINT; | |
| 473 } | |
| 474 fwrite($this->stdout, json_encode($vObj->jsonSerialize(), $jsonOptions)); | |
| 475 } else { | |
| 476 fwrite($this->stdout, $vObj->serialize()); | |
| 477 } | |
| 478 | |
| 479 return 0; | |
| 480 | |
| 481 } | |
| 482 | |
| 483 /** | |
| 484 * Colorizes a file | |
| 485 * | |
| 486 * @param Component $vObj | |
| 487 * @return int | |
| 488 */ | |
| 489 protected function color($vObj) { | |
| 490 | |
| 491 fwrite($this->stdout, $this->serializeComponent($vObj)); | |
| 492 | |
| 493 } | |
| 494 | |
| 495 /** | |
| 496 * Returns an ansi color string for a color name. | |
| 497 * | |
| 498 * @param string $color | |
| 499 * @return string | |
| 500 */ | |
| 501 protected function colorize($color, $str, $resetTo = 'default') { | |
| 502 | |
| 503 $colors = array( | |
| 504 'cyan' => '1;36', | |
| 505 'red' => '1;31', | |
| 506 'yellow' => '1;33', | |
| 507 'blue' => '0;34', | |
| 508 'green' => '0;32', | |
| 509 'default' => '0', | |
| 510 'purple' => '0;35', | |
| 511 ); | |
| 512 return "\033[" . $colors[$color] . 'm' . $str . "\033[".$colors[$resetTo]."m"; | |
| 513 | |
| 514 } | |
| 515 | |
| 516 /** | |
| 517 * Writes out a string in specific color. | |
| 518 * | |
| 519 * @param string $color | |
| 520 * @param string $str | |
| 521 * @return void | |
| 522 */ | |
| 523 protected function cWrite($color, $str) { | |
| 524 | |
| 525 fwrite($this->stdout, $this->colorize($color, $str)); | |
| 526 | |
| 527 } | |
| 528 | |
| 529 protected function serializeComponent(Component $vObj) { | |
| 530 | |
| 531 $this->cWrite('cyan', 'BEGIN'); | |
| 532 $this->cWrite('red', ':'); | |
| 533 $this->cWrite('yellow', $vObj->name . "\n"); | |
| 534 | |
| 535 /** | |
| 536 * Gives a component a 'score' for sorting purposes. | |
| 537 * | |
| 538 * This is solely used by the childrenSort method. | |
| 539 * | |
| 540 * A higher score means the item will be lower in the list. | |
| 541 * To avoid score collisions, each "score category" has a reasonable | |
| 542 * space to accomodate elements. The $key is added to the $score to | |
| 543 * preserve the original relative order of elements. | |
| 544 * | |
| 545 * @param int $key | |
| 546 * @param array $array | |
| 547 * @return int | |
| 548 */ | |
| 549 $sortScore = function($key, $array) { | |
| 550 | |
| 551 if ($array[$key] instanceof Component) { | |
| 552 | |
| 553 // We want to encode VTIMEZONE first, this is a personal | |
| 554 // preference. | |
| 555 if ($array[$key]->name === 'VTIMEZONE') { | |
| 556 $score=300000000; | |
| 557 return $score+$key; | |
| 558 } else { | |
| 559 $score=400000000; | |
| 560 return $score+$key; | |
| 561 } | |
| 562 } else { | |
| 563 // Properties get encoded first | |
| 564 // VCARD version 4.0 wants the VERSION property to appear first | |
| 565 if ($array[$key] instanceof Property) { | |
| 566 if ($array[$key]->name === 'VERSION') { | |
| 567 $score=100000000; | |
| 568 return $score+$key; | |
| 569 } else { | |
| 570 // All other properties | |
| 571 $score=200000000; | |
| 572 return $score+$key; | |
| 573 } | |
| 574 } | |
| 575 } | |
| 576 | |
| 577 }; | |
| 578 | |
| 579 $tmp = $vObj->children; | |
| 580 uksort( | |
| 581 $vObj->children, | |
| 582 function($a, $b) use ($sortScore, $tmp) { | |
| 583 | |
| 584 $sA = $sortScore($a, $tmp); | |
| 585 $sB = $sortScore($b, $tmp); | |
| 586 | |
| 587 return $sA - $sB; | |
| 588 | |
| 589 } | |
| 590 ); | |
| 591 | |
| 592 foreach($vObj->children as $child) { | |
| 593 if ($child instanceof Component) { | |
| 594 $this->serializeComponent($child); | |
| 595 } else { | |
| 596 $this->serializeProperty($child); | |
| 597 } | |
| 598 } | |
| 599 | |
| 600 $this->cWrite('cyan', 'END'); | |
| 601 $this->cWrite('red', ':'); | |
| 602 $this->cWrite('yellow', $vObj->name . "\n"); | |
| 603 | |
| 604 } | |
| 605 | |
| 606 /** | |
| 607 * Colorizes a property. | |
| 608 * | |
| 609 * @param Property $property | |
| 610 * @return void | |
| 611 */ | |
| 612 protected function serializeProperty(Property $property) { | |
| 613 | |
| 614 if ($property->group) { | |
| 615 $this->cWrite('default', $property->group); | |
| 616 $this->cWrite('red', '.'); | |
| 617 } | |
| 618 | |
| 619 $str = ''; | |
| 620 $this->cWrite('yellow', $property->name); | |
| 621 | |
| 622 foreach($property->parameters as $param) { | |
| 623 | |
| 624 $this->cWrite('red',';'); | |
| 625 $this->cWrite('blue', $param->serialize()); | |
| 626 | |
| 627 } | |
| 628 $this->cWrite('red',':'); | |
| 629 | |
| 630 if ($property instanceof Property\Binary) { | |
| 631 | |
| 632 $this->cWrite('default', 'embedded binary stripped. (' . strlen($property->getValue()) . ' bytes)'); | |
| 633 | |
| 634 } else { | |
| 635 | |
| 636 $parts = $property->getParts(); | |
| 637 $first1 = true; | |
| 638 // Looping through property values | |
| 639 foreach($parts as $part) { | |
| 640 if ($first1) { | |
| 641 $first1 = false; | |
| 642 } else { | |
| 643 $this->cWrite('red', $property->delimiter); | |
| 644 } | |
| 645 $first2 = true; | |
| 646 // Looping through property sub-values | |
| 647 foreach((array)$part as $subPart) { | |
| 648 if ($first2) { | |
| 649 $first2 = false; | |
| 650 } else { | |
| 651 // The sub-value delimiter is always comma | |
| 652 $this->cWrite('red', ','); | |
| 653 } | |
| 654 | |
| 655 $subPart = strtr( | |
| 656 $subPart, | |
| 657 array( | |
| 658 '\\' => $this->colorize('purple', '\\\\', 'green'), | |
| 659 ';' => $this->colorize('purple', '\;', 'green'), | |
| 660 ',' => $this->colorize('purple', '\,', 'green'), | |
| 661 "\n" => $this->colorize('purple', "\\n\n\t", 'green'), | |
| 662 "\r" => "", | |
| 663 ) | |
| 664 ); | |
| 665 | |
| 666 $this->cWrite('green', $subPart); | |
| 667 } | |
| 668 } | |
| 669 | |
| 670 } | |
| 671 $this->cWrite("default", "\n"); | |
| 672 | |
| 673 } | |
| 674 | |
| 675 /** | |
| 676 * Parses the list of arguments. | |
| 677 * | |
| 678 * @param array $argv | |
| 679 * @return void | |
| 680 */ | |
| 681 protected function parseArguments(array $argv) { | |
| 682 | |
| 683 $positional = array(); | |
| 684 $options = array(); | |
| 685 | |
| 686 for($ii=0; $ii < count($argv); $ii++) { | |
| 687 | |
| 688 // Skipping the first argument. | |
| 689 if ($ii===0) continue; | |
| 690 | |
| 691 $v = $argv[$ii]; | |
| 692 | |
| 693 if (substr($v,0,2)==='--') { | |
| 694 // This is a long-form option. | |
| 695 $optionName = substr($v,2); | |
| 696 $optionValue = true; | |
| 697 if (strpos($optionName,'=')) { | |
| 698 list($optionName, $optionValue) = explode('=', $optionName); | |
| 699 } | |
| 700 $options[$optionName] = $optionValue; | |
| 701 } elseif (substr($v,0,1) === '-' && strlen($v)>1) { | |
| 702 // This is a short-form option. | |
| 703 foreach(str_split(substr($v,1)) as $option) { | |
| 704 $options[$option] = true; | |
| 705 } | |
| 706 | |
| 707 } else { | |
| 708 | |
| 709 $positional[] = $v; | |
| 710 | |
| 711 } | |
| 712 | |
| 713 } | |
| 714 | |
| 715 return array($options, $positional); | |
| 716 | |
| 717 } | |
| 718 | |
| 719 protected $parser; | |
| 720 | |
| 721 /** | |
| 722 * Reads the input file | |
| 723 * | |
| 724 * @return Component | |
| 725 */ | |
| 726 protected function readInput() { | |
| 727 | |
| 728 if (!$this->parser) { | |
| 729 if ($this->inputPath!=='-') { | |
| 730 $this->stdin = fopen($this->inputPath,'r'); | |
| 731 } | |
| 732 | |
| 733 if ($this->inputFormat === 'mimedir') { | |
| 734 $this->parser = new Parser\MimeDir($this->stdin, ($this->forgiving?Reader::OPTION_FORGIVING:0)); | |
| 735 } else { | |
| 736 $this->parser = new Parser\Json($this->stdin, ($this->forgiving?Reader::OPTION_FORGIVING:0)); | |
| 737 } | |
| 738 } | |
| 739 | |
| 740 return $this->parser->parse(); | |
| 741 | |
| 742 } | |
| 743 | |
| 744 /** | |
| 745 * Sends a message to STDERR. | |
| 746 * | |
| 747 * @param string $msg | |
| 748 * @return void | |
| 749 */ | |
| 750 protected function log($msg, $color = 'default') { | |
| 751 | |
| 752 if (!$this->quiet) { | |
| 753 if ($color!=='default') { | |
| 754 $msg = $this->colorize($color, $msg); | |
| 755 } | |
| 756 fwrite($this->stderr, $msg . "\n"); | |
| 757 } | |
| 758 | |
| 759 } | |
| 760 | |
| 761 } |
