Mercurial > hg > rc1
comparison vendor/pear/console_commandline/Console/CommandLine.php @ 0:1e000243b222
vanilla 1.3.3 distro, I hope
| author | Charlie Root |
|---|---|
| date | Thu, 04 Jan 2018 15:50:29 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:1e000243b222 |
|---|---|
| 1 <?php | |
| 2 | |
| 3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ | |
| 4 | |
| 5 /** | |
| 6 * This file is part of the PEAR Console_CommandLine package. | |
| 7 * | |
| 8 * A full featured package for managing command-line options and arguments | |
| 9 * hightly inspired from python optparse module, it allows the developper to | |
| 10 * easily build complex command line interfaces. | |
| 11 * | |
| 12 * PHP version 5 | |
| 13 * | |
| 14 * LICENSE: This source file is subject to the MIT license that is available | |
| 15 * through the world-wide-web at the following URI: | |
| 16 * http://opensource.org/licenses/mit-license.php | |
| 17 * | |
| 18 * @category Console | |
| 19 * @package Console_CommandLine | |
| 20 * @author David JEAN LOUIS <izimobil@gmail.com> | |
| 21 * @copyright 2007 David JEAN LOUIS | |
| 22 * @license http://opensource.org/licenses/mit-license.php MIT License | |
| 23 * @version CVS: $Id$ | |
| 24 * @link http://pear.php.net/package/Console_CommandLine | |
| 25 * @since Class available since release 0.1.0 | |
| 26 * @filesource | |
| 27 */ | |
| 28 | |
| 29 /** | |
| 30 * Required unconditionally | |
| 31 */ | |
| 32 require_once 'Console/CommandLine/Exception.php'; | |
| 33 require_once 'Console/CommandLine/Outputter/Default.php'; | |
| 34 require_once 'Console/CommandLine/Renderer/Default.php'; | |
| 35 require_once 'Console/CommandLine/MessageProvider/Default.php'; | |
| 36 | |
| 37 /** | |
| 38 * Main class for parsing command line options and arguments. | |
| 39 * | |
| 40 * There are three ways to create parsers with this class: | |
| 41 * <code> | |
| 42 * // direct usage | |
| 43 * $parser = new Console_CommandLine(); | |
| 44 * | |
| 45 * // with an xml definition file | |
| 46 * $parser = Console_CommandLine::fromXmlFile('path/to/file.xml'); | |
| 47 * | |
| 48 * // with an xml definition string | |
| 49 * $validXmlString = '..your xml string...'; | |
| 50 * $parser = Console_CommandLine::fromXmlString($validXmlString); | |
| 51 * </code> | |
| 52 * | |
| 53 * @category Console | |
| 54 * @package Console_CommandLine | |
| 55 * @author David JEAN LOUIS <izimobil@gmail.com> | |
| 56 * @copyright 2007 David JEAN LOUIS | |
| 57 * @license http://opensource.org/licenses/mit-license.php MIT License | |
| 58 * @version Release: @package_version@ | |
| 59 * @link http://pear.php.net/package/Console_CommandLine | |
| 60 * @since File available since release 0.1.0 | |
| 61 * @example docs/examples/ex1.php | |
| 62 * @example docs/examples/ex2.php | |
| 63 */ | |
| 64 class Console_CommandLine | |
| 65 { | |
| 66 // Public properties {{{ | |
| 67 | |
| 68 /** | |
| 69 * Error messages. | |
| 70 * | |
| 71 * @var array $errors Error messages | |
| 72 * @todo move this to Console_CommandLine_MessageProvider | |
| 73 */ | |
| 74 public static $errors = array( | |
| 75 'option_bad_name' => 'option name must be a valid php variable name (got: {$name})', | |
| 76 'argument_bad_name' => 'argument name must be a valid php variable name (got: {$name})', | |
| 77 'argument_no_default' => 'only optional arguments can have a default value', | |
| 78 'option_long_and_short_name_missing' => 'you must provide at least an option short name or long name for option "{$name}"', | |
| 79 'option_bad_short_name' => 'option "{$name}" short name must be a dash followed by a letter (got: "{$short_name}")', | |
| 80 'option_bad_long_name' => 'option "{$name}" long name must be 2 dashes followed by a word (got: "{$long_name}")', | |
| 81 'option_unregistered_action' => 'unregistered action "{$action}" for option "{$name}".', | |
| 82 'option_bad_action' => 'invalid action for option "{$name}".', | |
| 83 'option_invalid_callback' => 'you must provide a valid callback for option "{$name}"', | |
| 84 'action_class_does_not_exists' => 'action "{$name}" class "{$class}" not found, make sure that your class is available before calling Console_CommandLine::registerAction()', | |
| 85 'invalid_xml_file' => 'XML definition file "{$file}" does not exists or is not readable', | |
| 86 'invalid_rng_file' => 'RNG file "{$file}" does not exists or is not readable' | |
| 87 ); | |
| 88 | |
| 89 /** | |
| 90 * The name of the program, if not given it defaults to argv[0]. | |
| 91 * | |
| 92 * @var string $name Name of your program | |
| 93 */ | |
| 94 public $name; | |
| 95 | |
| 96 /** | |
| 97 * A description text that will be displayed in the help message. | |
| 98 * | |
| 99 * @var string $description Description of your program | |
| 100 */ | |
| 101 public $description = ''; | |
| 102 | |
| 103 /** | |
| 104 * A string that represents the version of the program, if this property is | |
| 105 * not empty and property add_version_option is not set to false, the | |
| 106 * command line parser will add a --version option, that will display the | |
| 107 * property content. | |
| 108 * | |
| 109 * @var string $version | |
| 110 * @access public | |
| 111 */ | |
| 112 public $version = ''; | |
| 113 | |
| 114 /** | |
| 115 * Boolean that determine if the command line parser should add the help | |
| 116 * (-h, --help) option automatically. | |
| 117 * | |
| 118 * @var bool $add_help_option Whether to add a help option or not | |
| 119 */ | |
| 120 public $add_help_option = true; | |
| 121 | |
| 122 /** | |
| 123 * Boolean that determine if the command line parser should add the version | |
| 124 * (-v, --version) option automatically. | |
| 125 * Note that the version option is also generated only if the version | |
| 126 * property is not empty, it's up to you to provide a version string of | |
| 127 * course. | |
| 128 * | |
| 129 * @var bool $add_version_option Whether to add a version option or not | |
| 130 */ | |
| 131 public $add_version_option = true; | |
| 132 | |
| 133 /** | |
| 134 * Boolean that determine if providing a subcommand is mandatory. | |
| 135 * | |
| 136 * @var bool $subcommand_required Whether a subcommand is required or not | |
| 137 */ | |
| 138 public $subcommand_required = false; | |
| 139 | |
| 140 /** | |
| 141 * The command line parser renderer instance. | |
| 142 * | |
| 143 * @var object that implements Console_CommandLine_Renderer interface | |
| 144 * @access protected | |
| 145 */ | |
| 146 public $renderer = false; | |
| 147 | |
| 148 /** | |
| 149 * The command line parser outputter instance. | |
| 150 * | |
| 151 * @var Console_CommandLine_Outputter An outputter | |
| 152 */ | |
| 153 public $outputter = false; | |
| 154 | |
| 155 /** | |
| 156 * The command line message provider instance. | |
| 157 * | |
| 158 * @var Console_CommandLine_MessageProvider A message provider instance | |
| 159 */ | |
| 160 public $message_provider = false; | |
| 161 | |
| 162 /** | |
| 163 * Boolean that tells the parser to be POSIX compliant, POSIX demands the | |
| 164 * following behavior: the first non-option stops option processing. | |
| 165 * | |
| 166 * @var bool $force_posix Whether to force posix compliance or not | |
| 167 */ | |
| 168 public $force_posix = false; | |
| 169 | |
| 170 /** | |
| 171 * Boolean that tells the parser to set relevant options default values, | |
| 172 * according to the option action. | |
| 173 * | |
| 174 * @see Console_CommandLine_Option::setDefaults() | |
| 175 * @var bool $force_options_defaults Whether to force option default values | |
| 176 */ | |
| 177 public $force_options_defaults = false; | |
| 178 | |
| 179 | |
| 180 /** | |
| 181 * Boolean that tells the parser to treat a single - option as an argument | |
| 182 * instead of trying to read STDIN. | |
| 183 * | |
| 184 * @var bool $avoid_reading_stdin Whether to treat - as an argument | |
| 185 */ | |
| 186 public $avoid_reading_stdin = false; | |
| 187 | |
| 188 /** | |
| 189 * An array of Console_CommandLine_Option objects. | |
| 190 * | |
| 191 * @var array $options The options array | |
| 192 */ | |
| 193 public $options = array(); | |
| 194 | |
| 195 /** | |
| 196 * An array of Console_CommandLine_Argument objects. | |
| 197 * | |
| 198 * @var array $args The arguments array | |
| 199 */ | |
| 200 public $args = array(); | |
| 201 | |
| 202 /** | |
| 203 * An array of Console_CommandLine_Command objects (sub commands). | |
| 204 * | |
| 205 * @var array $commands The commands array | |
| 206 */ | |
| 207 public $commands = array(); | |
| 208 | |
| 209 /** | |
| 210 * Parent, only relevant in Command objects but left here for interface | |
| 211 * convenience. | |
| 212 * | |
| 213 * @var Console_CommandLine The parent instance | |
| 214 * @todo move Console_CommandLine::parent to Console_CommandLine_Command | |
| 215 */ | |
| 216 public $parent = false; | |
| 217 | |
| 218 /** | |
| 219 * Array of valid actions for an option, this array will also store user | |
| 220 * registered actions. | |
| 221 * | |
| 222 * The array format is: | |
| 223 * <pre> | |
| 224 * array( | |
| 225 * <ActionName:string> => array(<ActionClass:string>, <builtin:bool>) | |
| 226 * ) | |
| 227 * </pre> | |
| 228 * | |
| 229 * @var array $actions List of valid actions | |
| 230 */ | |
| 231 public static $actions = array( | |
| 232 'StoreTrue' => array('Console_CommandLine_Action_StoreTrue', true), | |
| 233 'StoreFalse' => array('Console_CommandLine_Action_StoreFalse', true), | |
| 234 'StoreString' => array('Console_CommandLine_Action_StoreString', true), | |
| 235 'StoreInt' => array('Console_CommandLine_Action_StoreInt', true), | |
| 236 'StoreFloat' => array('Console_CommandLine_Action_StoreFloat', true), | |
| 237 'StoreArray' => array('Console_CommandLine_Action_StoreArray', true), | |
| 238 'Callback' => array('Console_CommandLine_Action_Callback', true), | |
| 239 'Counter' => array('Console_CommandLine_Action_Counter', true), | |
| 240 'Help' => array('Console_CommandLine_Action_Help', true), | |
| 241 'Version' => array('Console_CommandLine_Action_Version', true), | |
| 242 'Password' => array('Console_CommandLine_Action_Password', true), | |
| 243 'List' => array('Console_CommandLine_Action_List', true), | |
| 244 ); | |
| 245 | |
| 246 /** | |
| 247 * Custom errors messages for this command | |
| 248 * | |
| 249 * This array is of the form: | |
| 250 * <code> | |
| 251 * <?php | |
| 252 * array( | |
| 253 * $messageName => $messageText, | |
| 254 * $messageName => $messageText, | |
| 255 * ... | |
| 256 * ); | |
| 257 * ?> | |
| 258 * </code> | |
| 259 * | |
| 260 * If specified, these messages override the messages provided by the | |
| 261 * default message provider. For example: | |
| 262 * <code> | |
| 263 * <?php | |
| 264 * $messages = array( | |
| 265 * 'ARGUMENT_REQUIRED' => 'The argument foo is required.', | |
| 266 * ); | |
| 267 * ?> | |
| 268 * </code> | |
| 269 * | |
| 270 * @var array | |
| 271 * @see Console_CommandLine_MessageProvider_Default | |
| 272 */ | |
| 273 public $messages = array(); | |
| 274 | |
| 275 // }}} | |
| 276 // {{{ Private properties | |
| 277 | |
| 278 /** | |
| 279 * Array of options that must be dispatched at the end. | |
| 280 * | |
| 281 * @var array $_dispatchLater Options to be dispatched | |
| 282 */ | |
| 283 private $_dispatchLater = array(); | |
| 284 | |
| 285 private $_lastopt = false; | |
| 286 private $_stopflag = false; | |
| 287 | |
| 288 // }}} | |
| 289 // __construct() {{{ | |
| 290 | |
| 291 /** | |
| 292 * Constructor. | |
| 293 * Example: | |
| 294 * | |
| 295 * <code> | |
| 296 * $parser = new Console_CommandLine(array( | |
| 297 * 'name' => 'yourprogram', // defaults to argv[0] | |
| 298 * 'description' => 'Description of your program', | |
| 299 * 'version' => '0.0.1', // your program version | |
| 300 * 'add_help_option' => true, // or false to disable --help option | |
| 301 * 'add_version_option' => true, // or false to disable --version option | |
| 302 * 'force_posix' => false // or true to force posix compliance | |
| 303 * )); | |
| 304 * </code> | |
| 305 * | |
| 306 * @param array $params An optional array of parameters | |
| 307 * | |
| 308 * @return void | |
| 309 */ | |
| 310 public function __construct(array $params = array()) | |
| 311 { | |
| 312 if (isset($params['name'])) { | |
| 313 $this->name = $params['name']; | |
| 314 } else if (isset($argv) && count($argv) > 0) { | |
| 315 $this->name = $argv[0]; | |
| 316 } else if (isset($_SERVER['argv']) && count($_SERVER['argv']) > 0) { | |
| 317 $this->name = $_SERVER['argv'][0]; | |
| 318 } else if (isset($_SERVER['SCRIPT_NAME'])) { | |
| 319 $this->name = basename($_SERVER['SCRIPT_NAME']); | |
| 320 } | |
| 321 if (isset($params['description'])) { | |
| 322 $this->description = $params['description']; | |
| 323 } | |
| 324 if (isset($params['version'])) { | |
| 325 $this->version = $params['version']; | |
| 326 } | |
| 327 if (isset($params['add_version_option'])) { | |
| 328 $this->add_version_option = $params['add_version_option']; | |
| 329 } | |
| 330 if (isset($params['add_help_option'])) { | |
| 331 $this->add_help_option = $params['add_help_option']; | |
| 332 } | |
| 333 if (isset($params['subcommand_required'])) { | |
| 334 $this->subcommand_required = $params['subcommand_required']; | |
| 335 } | |
| 336 if (isset($params['force_posix'])) { | |
| 337 $this->force_posix = $params['force_posix']; | |
| 338 } else if (getenv('POSIXLY_CORRECT')) { | |
| 339 $this->force_posix = true; | |
| 340 } | |
| 341 if (isset($params['messages']) && is_array($params['messages'])) { | |
| 342 $this->messages = $params['messages']; | |
| 343 } | |
| 344 // set default instances | |
| 345 $this->renderer = new Console_CommandLine_Renderer_Default($this); | |
| 346 $this->outputter = new Console_CommandLine_Outputter_Default(); | |
| 347 $this->message_provider = new Console_CommandLine_MessageProvider_Default(); | |
| 348 } | |
| 349 | |
| 350 // }}} | |
| 351 // accept() {{{ | |
| 352 | |
| 353 /** | |
| 354 * Method to allow Console_CommandLine to accept either: | |
| 355 * + a custom renderer, | |
| 356 * + a custom outputter, | |
| 357 * + or a custom message provider | |
| 358 * | |
| 359 * @param mixed $instance The custom instance | |
| 360 * | |
| 361 * @return void | |
| 362 * @throws Console_CommandLine_Exception if wrong argument passed | |
| 363 */ | |
| 364 public function accept($instance) | |
| 365 { | |
| 366 if ($instance instanceof Console_CommandLine_Renderer) { | |
| 367 if (property_exists($instance, 'parser') && !$instance->parser) { | |
| 368 $instance->parser = $this; | |
| 369 } | |
| 370 $this->renderer = $instance; | |
| 371 } else if ($instance instanceof Console_CommandLine_Outputter) { | |
| 372 $this->outputter = $instance; | |
| 373 } else if ($instance instanceof Console_CommandLine_MessageProvider) { | |
| 374 $this->message_provider = $instance; | |
| 375 } else { | |
| 376 throw Console_CommandLine_Exception::factory( | |
| 377 'INVALID_CUSTOM_INSTANCE', | |
| 378 array(), | |
| 379 $this, | |
| 380 $this->messages | |
| 381 ); | |
| 382 } | |
| 383 } | |
| 384 | |
| 385 // }}} | |
| 386 // fromXmlFile() {{{ | |
| 387 | |
| 388 /** | |
| 389 * Returns a command line parser instance built from an xml file. | |
| 390 * | |
| 391 * Example: | |
| 392 * <code> | |
| 393 * require_once 'Console/CommandLine.php'; | |
| 394 * $parser = Console_CommandLine::fromXmlFile('path/to/file.xml'); | |
| 395 * $result = $parser->parse(); | |
| 396 * </code> | |
| 397 * | |
| 398 * @param string $file Path to the xml file | |
| 399 * | |
| 400 * @return Console_CommandLine The parser instance | |
| 401 */ | |
| 402 public static function fromXmlFile($file) | |
| 403 { | |
| 404 include_once 'Console/CommandLine/XmlParser.php'; | |
| 405 return Console_CommandLine_XmlParser::parse($file); | |
| 406 } | |
| 407 | |
| 408 // }}} | |
| 409 // fromXmlString() {{{ | |
| 410 | |
| 411 /** | |
| 412 * Returns a command line parser instance built from an xml string. | |
| 413 * | |
| 414 * Example: | |
| 415 * <code> | |
| 416 * require_once 'Console/CommandLine.php'; | |
| 417 * $xmldata = '<?xml version="1.0" encoding="utf-8" standalone="yes"?> | |
| 418 * <command> | |
| 419 * <description>Compress files</description> | |
| 420 * <option name="quiet"> | |
| 421 * <short_name>-q</short_name> | |
| 422 * <long_name>--quiet</long_name> | |
| 423 * <description>be quiet when run</description> | |
| 424 * <action>StoreTrue/action> | |
| 425 * </option> | |
| 426 * <argument name="files"> | |
| 427 * <description>a list of files</description> | |
| 428 * <multiple>true</multiple> | |
| 429 * </argument> | |
| 430 * </command>'; | |
| 431 * $parser = Console_CommandLine::fromXmlString($xmldata); | |
| 432 * $result = $parser->parse(); | |
| 433 * </code> | |
| 434 * | |
| 435 * @param string $string The xml data | |
| 436 * | |
| 437 * @return Console_CommandLine The parser instance | |
| 438 */ | |
| 439 public static function fromXmlString($string) | |
| 440 { | |
| 441 include_once 'Console/CommandLine/XmlParser.php'; | |
| 442 return Console_CommandLine_XmlParser::parseString($string); | |
| 443 } | |
| 444 | |
| 445 // }}} | |
| 446 // addArgument() {{{ | |
| 447 | |
| 448 /** | |
| 449 * Adds an argument to the command line parser and returns it. | |
| 450 * | |
| 451 * Adds an argument with the name $name and set its attributes with the | |
| 452 * array $params, then return the Console_CommandLine_Argument instance | |
| 453 * created. | |
| 454 * The method accepts another form: you can directly pass a | |
| 455 * Console_CommandLine_Argument object as the sole argument, this allows | |
| 456 * you to contruct the argument separately, in order to reuse it in | |
| 457 * different command line parsers or commands for example. | |
| 458 * | |
| 459 * Example: | |
| 460 * <code> | |
| 461 * $parser = new Console_CommandLine(); | |
| 462 * // add an array argument | |
| 463 * $parser->addArgument('input_files', array('multiple'=>true)); | |
| 464 * // add a simple argument | |
| 465 * $parser->addArgument('output_file'); | |
| 466 * $result = $parser->parse(); | |
| 467 * print_r($result->args['input_files']); | |
| 468 * print_r($result->args['output_file']); | |
| 469 * // will print: | |
| 470 * // array('file1', 'file2') | |
| 471 * // 'file3' | |
| 472 * // if the command line was: | |
| 473 * // myscript.php file1 file2 file3 | |
| 474 * </code> | |
| 475 * | |
| 476 * In a terminal, the help will be displayed like this: | |
| 477 * <code> | |
| 478 * $ myscript.php install -h | |
| 479 * Usage: myscript.php <input_files...> <output_file> | |
| 480 * </code> | |
| 481 * | |
| 482 * @param mixed $name A string containing the argument name or an | |
| 483 * instance of Console_CommandLine_Argument | |
| 484 * @param array $params An array containing the argument attributes | |
| 485 * | |
| 486 * @return Console_CommandLine_Argument the added argument | |
| 487 * @see Console_CommandLine_Argument | |
| 488 */ | |
| 489 public function addArgument($name, $params = array()) | |
| 490 { | |
| 491 if ($name instanceof Console_CommandLine_Argument) { | |
| 492 $argument = $name; | |
| 493 } else { | |
| 494 include_once 'Console/CommandLine/Argument.php'; | |
| 495 $argument = new Console_CommandLine_Argument($name, $params); | |
| 496 } | |
| 497 $argument->validate(); | |
| 498 $this->args[$argument->name] = $argument; | |
| 499 return $argument; | |
| 500 } | |
| 501 | |
| 502 // }}} | |
| 503 // addCommand() {{{ | |
| 504 | |
| 505 /** | |
| 506 * Adds a sub-command to the command line parser. | |
| 507 * | |
| 508 * Adds a command with the given $name to the parser and returns the | |
| 509 * Console_CommandLine_Command instance, you can then populate the command | |
| 510 * with options, configure it, etc... like you would do for the main parser | |
| 511 * because the class Console_CommandLine_Command inherits from | |
| 512 * Console_CommandLine. | |
| 513 * | |
| 514 * An example: | |
| 515 * <code> | |
| 516 * $parser = new Console_CommandLine(); | |
| 517 * $install_cmd = $parser->addCommand('install'); | |
| 518 * $install_cmd->addOption( | |
| 519 * 'verbose', | |
| 520 * array( | |
| 521 * 'short_name' => '-v', | |
| 522 * 'long_name' => '--verbose', | |
| 523 * 'description' => 'be noisy when installing stuff', | |
| 524 * 'action' => 'StoreTrue' | |
| 525 * ) | |
| 526 * ); | |
| 527 * $parser->parse(); | |
| 528 * </code> | |
| 529 * Then in a terminal: | |
| 530 * <code> | |
| 531 * $ myscript.php install -h | |
| 532 * Usage: myscript.php install [options] | |
| 533 * | |
| 534 * Options: | |
| 535 * -h, --help display this help message and exit | |
| 536 * -v, --verbose be noisy when installing stuff | |
| 537 * | |
| 538 * $ myscript.php install --verbose | |
| 539 * Installing whatever... | |
| 540 * $ | |
| 541 * </code> | |
| 542 * | |
| 543 * @param mixed $name A string containing the command name or an | |
| 544 * instance of Console_CommandLine_Command | |
| 545 * @param array $params An array containing the command attributes | |
| 546 * | |
| 547 * @return Console_CommandLine_Command the added subcommand | |
| 548 * @see Console_CommandLine_Command | |
| 549 */ | |
| 550 public function addCommand($name, $params = array()) | |
| 551 { | |
| 552 if ($name instanceof Console_CommandLine_Command) { | |
| 553 $command = $name; | |
| 554 } else { | |
| 555 include_once 'Console/CommandLine/Command.php'; | |
| 556 $params['name'] = $name; | |
| 557 $command = new Console_CommandLine_Command($params); | |
| 558 // some properties must cascade to the child command if not | |
| 559 // passed explicitely. This is done only in this case, because if | |
| 560 // we have a Command object we have no way to determine if theses | |
| 561 // properties have already been set | |
| 562 $cascade = array( | |
| 563 'add_help_option', | |
| 564 'add_version_option', | |
| 565 'outputter', | |
| 566 'message_provider', | |
| 567 'force_posix', | |
| 568 'force_options_defaults' | |
| 569 ); | |
| 570 foreach ($cascade as $property) { | |
| 571 if (!isset($params[$property])) { | |
| 572 $command->$property = $this->$property; | |
| 573 } | |
| 574 } | |
| 575 if (!isset($params['renderer'])) { | |
| 576 $renderer = clone $this->renderer; | |
| 577 $renderer->parser = $command; | |
| 578 $command->renderer = $renderer; | |
| 579 } | |
| 580 } | |
| 581 $command->parent = $this; | |
| 582 $this->commands[$command->name] = $command; | |
| 583 return $command; | |
| 584 } | |
| 585 | |
| 586 // }}} | |
| 587 // addOption() {{{ | |
| 588 | |
| 589 /** | |
| 590 * Adds an option to the command line parser and returns it. | |
| 591 * | |
| 592 * Adds an option with the name $name and set its attributes with the | |
| 593 * array $params, then return the Console_CommandLine_Option instance | |
| 594 * created. | |
| 595 * The method accepts another form: you can directly pass a | |
| 596 * Console_CommandLine_Option object as the sole argument, this allows | |
| 597 * you to contruct the option separately, in order to reuse it in different | |
| 598 * command line parsers or commands for example. | |
| 599 * | |
| 600 * Example: | |
| 601 * <code> | |
| 602 * $parser = new Console_CommandLine(); | |
| 603 * $parser->addOption('path', array( | |
| 604 * 'short_name' => '-p', // a short name | |
| 605 * 'long_name' => '--path', // a long name | |
| 606 * 'description' => 'path to the dir', // a description msg | |
| 607 * 'action' => 'StoreString', | |
| 608 * 'default' => '/tmp' // a default value | |
| 609 * )); | |
| 610 * $parser->parse(); | |
| 611 * </code> | |
| 612 * | |
| 613 * In a terminal, the help will be displayed like this: | |
| 614 * <code> | |
| 615 * $ myscript.php --help | |
| 616 * Usage: myscript.php [options] | |
| 617 * | |
| 618 * Options: | |
| 619 * -h, --help display this help message and exit | |
| 620 * -p, --path path to the dir | |
| 621 * | |
| 622 * </code> | |
| 623 * | |
| 624 * Various methods to specify an option, these 3 commands are equivalent: | |
| 625 * <code> | |
| 626 * $ myscript.php --path=some/path | |
| 627 * $ myscript.php -p some/path | |
| 628 * $ myscript.php -psome/path | |
| 629 * </code> | |
| 630 * | |
| 631 * @param mixed $name A string containing the option name or an | |
| 632 * instance of Console_CommandLine_Option | |
| 633 * @param array $params An array containing the option attributes | |
| 634 * | |
| 635 * @return Console_CommandLine_Option The added option | |
| 636 * @see Console_CommandLine_Option | |
| 637 */ | |
| 638 public function addOption($name, $params = array()) | |
| 639 { | |
| 640 include_once 'Console/CommandLine/Option.php'; | |
| 641 if ($name instanceof Console_CommandLine_Option) { | |
| 642 $opt = $name; | |
| 643 } else { | |
| 644 $opt = new Console_CommandLine_Option($name, $params); | |
| 645 } | |
| 646 $opt->validate(); | |
| 647 if ($this->force_options_defaults) { | |
| 648 $opt->setDefaults(); | |
| 649 } | |
| 650 $this->options[$opt->name] = $opt; | |
| 651 if (!empty($opt->choices) && $opt->add_list_option) { | |
| 652 $this->addOption('list_' . $opt->name, array( | |
| 653 'long_name' => '--list-' . $opt->name, | |
| 654 'description' => $this->message_provider->get( | |
| 655 'LIST_OPTION_MESSAGE', | |
| 656 array('name' => $opt->name) | |
| 657 ), | |
| 658 'action' => 'List', | |
| 659 'action_params' => array('list' => $opt->choices), | |
| 660 )); | |
| 661 } | |
| 662 return $opt; | |
| 663 } | |
| 664 | |
| 665 // }}} | |
| 666 // displayError() {{{ | |
| 667 | |
| 668 /** | |
| 669 * Displays an error to the user via stderr and exit with $exitCode if its | |
| 670 * value is not equals to false. | |
| 671 * | |
| 672 * @param string $error The error message | |
| 673 * @param int $exitCode The exit code number (default: 1). If set to | |
| 674 * false, the exit() function will not be called | |
| 675 * | |
| 676 * @return void | |
| 677 */ | |
| 678 public function displayError($error, $exitCode = 1) | |
| 679 { | |
| 680 $this->outputter->stderr($this->renderer->error($error)); | |
| 681 if ($exitCode !== false) { | |
| 682 exit($exitCode); | |
| 683 } | |
| 684 } | |
| 685 | |
| 686 // }}} | |
| 687 // displayUsage() {{{ | |
| 688 | |
| 689 /** | |
| 690 * Displays the usage help message to the user via stdout and exit with | |
| 691 * $exitCode if its value is not equals to false. | |
| 692 * | |
| 693 * @param int $exitCode The exit code number (default: 0). If set to | |
| 694 * false, the exit() function will not be called | |
| 695 * | |
| 696 * @return void | |
| 697 */ | |
| 698 public function displayUsage($exitCode = 0) | |
| 699 { | |
| 700 $this->outputter->stdout($this->renderer->usage()); | |
| 701 if ($exitCode !== false) { | |
| 702 exit($exitCode); | |
| 703 } | |
| 704 } | |
| 705 | |
| 706 // }}} | |
| 707 // displayVersion() {{{ | |
| 708 | |
| 709 /** | |
| 710 * Displays the program version to the user via stdout and exit with | |
| 711 * $exitCode if its value is not equals to false. | |
| 712 * | |
| 713 * | |
| 714 * @param int $exitCode The exit code number (default: 0). If set to | |
| 715 * false, the exit() function will not be called | |
| 716 * | |
| 717 * @return void | |
| 718 */ | |
| 719 public function displayVersion($exitCode = 0) | |
| 720 { | |
| 721 $this->outputter->stdout($this->renderer->version()); | |
| 722 if ($exitCode !== false) { | |
| 723 exit($exitCode); | |
| 724 } | |
| 725 } | |
| 726 | |
| 727 // }}} | |
| 728 // findOption() {{{ | |
| 729 | |
| 730 /** | |
| 731 * Finds the option that matches the given short_name (ex: -v), long_name | |
| 732 * (ex: --verbose) or name (ex: verbose). | |
| 733 * | |
| 734 * @param string $str The option identifier | |
| 735 * | |
| 736 * @return mixed A Console_CommandLine_Option instance or false | |
| 737 */ | |
| 738 public function findOption($str) | |
| 739 { | |
| 740 $str = trim($str); | |
| 741 if ($str === '') { | |
| 742 return false; | |
| 743 } | |
| 744 $matches = array(); | |
| 745 foreach ($this->options as $opt) { | |
| 746 if ($opt->short_name == $str || $opt->long_name == $str || | |
| 747 $opt->name == $str) { | |
| 748 // exact match | |
| 749 return $opt; | |
| 750 } | |
| 751 if (substr($opt->long_name, 0, strlen($str)) === $str) { | |
| 752 // abbreviated long option | |
| 753 $matches[] = $opt; | |
| 754 } | |
| 755 } | |
| 756 if ($count = count($matches)) { | |
| 757 if ($count > 1) { | |
| 758 $matches_str = ''; | |
| 759 $padding = ''; | |
| 760 foreach ($matches as $opt) { | |
| 761 $matches_str .= $padding . $opt->long_name; | |
| 762 $padding = ', '; | |
| 763 } | |
| 764 throw Console_CommandLine_Exception::factory( | |
| 765 'OPTION_AMBIGUOUS', | |
| 766 array('name' => $str, 'matches' => $matches_str), | |
| 767 $this, | |
| 768 $this->messages | |
| 769 ); | |
| 770 } | |
| 771 return $matches[0]; | |
| 772 } | |
| 773 return false; | |
| 774 } | |
| 775 // }}} | |
| 776 // registerAction() {{{ | |
| 777 | |
| 778 /** | |
| 779 * Registers a custom action for the parser, an example: | |
| 780 * | |
| 781 * <code> | |
| 782 * | |
| 783 * // in this example we create a "range" action: | |
| 784 * // the user will be able to enter something like: | |
| 785 * // $ <program> -r 1,5 | |
| 786 * // and in the result we will have: | |
| 787 * // $result->options['range']: array(1, 5) | |
| 788 * | |
| 789 * require_once 'Console/CommandLine.php'; | |
| 790 * require_once 'Console/CommandLine/Action.php'; | |
| 791 * | |
| 792 * class ActionRange extends Console_CommandLine_Action | |
| 793 * { | |
| 794 * public function execute($value=false, $params=array()) | |
| 795 * { | |
| 796 * $range = explode(',', str_replace(' ', '', $value)); | |
| 797 * if (count($range) != 2) { | |
| 798 * throw new Exception(sprintf( | |
| 799 * 'Option "%s" must be 2 integers separated by a comma', | |
| 800 * $this->option->name | |
| 801 * )); | |
| 802 * } | |
| 803 * $this->setResult($range); | |
| 804 * } | |
| 805 * } | |
| 806 * // then we can register our action | |
| 807 * Console_CommandLine::registerAction('Range', 'ActionRange'); | |
| 808 * // and now our action is available ! | |
| 809 * $parser = new Console_CommandLine(); | |
| 810 * $parser->addOption('range', array( | |
| 811 * 'short_name' => '-r', | |
| 812 * 'long_name' => '--range', | |
| 813 * 'action' => 'Range', // note our custom action | |
| 814 * 'description' => 'A range of two integers separated by a comma' | |
| 815 * )); | |
| 816 * // etc... | |
| 817 * | |
| 818 * </code> | |
| 819 * | |
| 820 * @param string $name The name of the custom action | |
| 821 * @param string $class The class name of the custom action | |
| 822 * | |
| 823 * @return void | |
| 824 */ | |
| 825 public static function registerAction($name, $class) | |
| 826 { | |
| 827 if (!isset(self::$actions[$name])) { | |
| 828 if (!class_exists($class)) { | |
| 829 self::triggerError('action_class_does_not_exists', | |
| 830 E_USER_ERROR, | |
| 831 array('{$name}' => $name, '{$class}' => $class)); | |
| 832 } | |
| 833 self::$actions[$name] = array($class, false); | |
| 834 } | |
| 835 } | |
| 836 | |
| 837 // }}} | |
| 838 // triggerError() {{{ | |
| 839 | |
| 840 /** | |
| 841 * A wrapper for programming errors triggering. | |
| 842 * | |
| 843 * @param string $msgId Identifier of the message | |
| 844 * @param int $level The php error level | |
| 845 * @param array $params An array of search=>replaces entries | |
| 846 * | |
| 847 * @return void | |
| 848 * @todo remove Console::triggerError() and use exceptions only | |
| 849 */ | |
| 850 public static function triggerError($msgId, $level, $params=array()) | |
| 851 { | |
| 852 if (isset(self::$errors[$msgId])) { | |
| 853 $msg = str_replace(array_keys($params), | |
| 854 array_values($params), self::$errors[$msgId]); | |
| 855 trigger_error($msg, $level); | |
| 856 } else { | |
| 857 trigger_error('unknown error', $level); | |
| 858 } | |
| 859 } | |
| 860 | |
| 861 // }}} | |
| 862 // parse() {{{ | |
| 863 | |
| 864 /** | |
| 865 * Parses the command line arguments and returns a | |
| 866 * Console_CommandLine_Result instance. | |
| 867 * | |
| 868 * @param integer $userArgc Number of arguments (optional) | |
| 869 * @param array $userArgv Array containing arguments (optional) | |
| 870 * | |
| 871 * @return Console_CommandLine_Result The result instance | |
| 872 * @throws Exception on user errors | |
| 873 */ | |
| 874 public function parse($userArgc=null, $userArgv=null) | |
| 875 { | |
| 876 $this->_lastopt = false; | |
| 877 $this->_stopflag = false; | |
| 878 | |
| 879 $this->addBuiltinOptions(); | |
| 880 if ($userArgc !== null && $userArgv !== null) { | |
| 881 $argc = $userArgc; | |
| 882 $argv = $userArgv; | |
| 883 } else { | |
| 884 list($argc, $argv) = $this->getArgcArgv(); | |
| 885 } | |
| 886 // build an empty result | |
| 887 include_once 'Console/CommandLine/Result.php'; | |
| 888 $result = new Console_CommandLine_Result(); | |
| 889 if (!($this instanceof Console_CommandLine_Command)) { | |
| 890 // remove script name if we're not in a subcommand | |
| 891 array_shift($argv); | |
| 892 $argc--; | |
| 893 } | |
| 894 // will contain arguments | |
| 895 $args = array(); | |
| 896 foreach ($this->options as $name=>$option) { | |
| 897 $result->options[$name] = $option->default; | |
| 898 } | |
| 899 // parse command line tokens | |
| 900 while ($argc--) { | |
| 901 $token = array_shift($argv); | |
| 902 try { | |
| 903 if ($cmd = $this->_getSubCommand($token)) { | |
| 904 $result->command_name = $cmd->name; | |
| 905 $result->command = $cmd->parse($argc, $argv); | |
| 906 break; | |
| 907 } else { | |
| 908 $this->parseToken($token, $result, $args, $argc); | |
| 909 } | |
| 910 } catch (Exception $exc) { | |
| 911 throw $exc; | |
| 912 } | |
| 913 } | |
| 914 // Parse a null token to allow any undespatched actions to be despatched. | |
| 915 $this->parseToken(null, $result, $args, 0); | |
| 916 // Check if an invalid subcommand was specified. If there are | |
| 917 // subcommands and no arguments, but an argument was provided, it is | |
| 918 // an invalid subcommand. | |
| 919 if ( count($this->commands) > 0 | |
| 920 && count($this->args) === 0 | |
| 921 && count($args) > 0 | |
| 922 ) { | |
| 923 throw Console_CommandLine_Exception::factory( | |
| 924 'INVALID_SUBCOMMAND', | |
| 925 array('command' => $args[0]), | |
| 926 $this, | |
| 927 $this->messages | |
| 928 ); | |
| 929 } | |
| 930 // if subcommand_required is set to true we must check that we have a | |
| 931 // subcommand. | |
| 932 if ( count($this->commands) | |
| 933 && $this->subcommand_required | |
| 934 && !$result->command_name | |
| 935 ) { | |
| 936 throw Console_CommandLine_Exception::factory( | |
| 937 'SUBCOMMAND_REQUIRED', | |
| 938 array('commands' => implode(array_keys($this->commands), ', ')), | |
| 939 $this, | |
| 940 $this->messages | |
| 941 ); | |
| 942 } | |
| 943 // minimum argument number check | |
| 944 $argnum = 0; | |
| 945 foreach ($this->args as $name=>$arg) { | |
| 946 if (!$arg->optional) { | |
| 947 $argnum++; | |
| 948 } | |
| 949 } | |
| 950 if (count($args) < $argnum) { | |
| 951 throw Console_CommandLine_Exception::factory( | |
| 952 'ARGUMENT_REQUIRED', | |
| 953 array('argnum' => $argnum, 'plural' => $argnum>1 ? 's': ''), | |
| 954 $this, | |
| 955 $this->messages | |
| 956 ); | |
| 957 } | |
| 958 // handle arguments | |
| 959 $c = count($this->args); | |
| 960 foreach ($this->args as $name=>$arg) { | |
| 961 $c--; | |
| 962 if ($arg->multiple) { | |
| 963 $result->args[$name] = $c ? array_splice($args, 0, -$c) : $args; | |
| 964 } else { | |
| 965 $result->args[$name] = array_shift($args); | |
| 966 } | |
| 967 if (!$result->args[$name] && $arg->optional && $arg->default) { | |
| 968 $result->args[$name] = $arg->default; | |
| 969 } | |
| 970 // check value is in argument choices | |
| 971 if (!empty($this->args[$name]->choices)) { | |
| 972 foreach ($result->args[$name] as $value) { | |
| 973 if (!in_array($value, $arg->choices)) { | |
| 974 throw Console_CommandLine_Exception::factory( | |
| 975 'ARGUMENT_VALUE_NOT_VALID', | |
| 976 array( | |
| 977 'name' => $name, | |
| 978 'choices' => implode('", "', $arg->choices), | |
| 979 'value' => implode(' ', $result->args[$name]), | |
| 980 ), | |
| 981 $this, | |
| 982 $arg->messages | |
| 983 ); | |
| 984 } | |
| 985 } | |
| 986 } | |
| 987 } | |
| 988 // dispatch deferred options | |
| 989 foreach ($this->_dispatchLater as $optArray) { | |
| 990 $optArray[0]->dispatchAction($optArray[1], $optArray[2], $this); | |
| 991 } | |
| 992 return $result; | |
| 993 } | |
| 994 | |
| 995 // }}} | |
| 996 // parseToken() {{{ | |
| 997 | |
| 998 /** | |
| 999 * Parses the command line token and modifies *by reference* the $options | |
| 1000 * and $args arrays. | |
| 1001 * | |
| 1002 * @param string $token The command line token to parse | |
| 1003 * @param object $result The Console_CommandLine_Result instance | |
| 1004 * @param array &$args The argv array | |
| 1005 * @param int $argc Number of lasting args | |
| 1006 * | |
| 1007 * @return void | |
| 1008 * @access protected | |
| 1009 * @throws Exception on user errors | |
| 1010 */ | |
| 1011 protected function parseToken($token, $result, &$args, $argc) | |
| 1012 { | |
| 1013 $last = $argc === 0; | |
| 1014 if (!$this->_stopflag && $this->_lastopt) { | |
| 1015 if (strlen($token) > ($this->avoid_reading_stdin ? 1 : 0) && | |
| 1016 substr($token, 0, 1) == '-') { | |
| 1017 if ($this->_lastopt->argument_optional) { | |
| 1018 $this->_dispatchAction($this->_lastopt, '', $result); | |
| 1019 if ($this->_lastopt->action != 'StoreArray') { | |
| 1020 $this->_lastopt = false; | |
| 1021 } | |
| 1022 } else if (isset($result->options[$this->_lastopt->name])) { | |
| 1023 // case of an option that expect a list of args | |
| 1024 $this->_lastopt = false; | |
| 1025 } else { | |
| 1026 throw Console_CommandLine_Exception::factory( | |
| 1027 'OPTION_VALUE_REQUIRED', | |
| 1028 array('name' => $this->_lastopt->name), | |
| 1029 $this, | |
| 1030 $this->messages | |
| 1031 ); | |
| 1032 } | |
| 1033 } else { | |
| 1034 // when a StoreArray option is positioned last, the behavior | |
| 1035 // is to consider that if there's already an element in the | |
| 1036 // array, and the commandline expects one or more args, we | |
| 1037 // leave last tokens to arguments | |
| 1038 if ($this->_lastopt->action == 'StoreArray' | |
| 1039 && !empty($result->options[$this->_lastopt->name]) | |
| 1040 && count($this->args) > ($argc + count($args)) | |
| 1041 ) { | |
| 1042 if (!is_null($token)) { | |
| 1043 $args[] = $token; | |
| 1044 } | |
| 1045 return; | |
| 1046 } | |
| 1047 if (!is_null($token) || $this->_lastopt->action == 'Password') { | |
| 1048 $this->_dispatchAction($this->_lastopt, $token, $result); | |
| 1049 } | |
| 1050 if ($this->_lastopt->action != 'StoreArray') { | |
| 1051 $this->_lastopt = false; | |
| 1052 } | |
| 1053 return; | |
| 1054 } | |
| 1055 } | |
| 1056 if (!$this->_stopflag && substr($token, 0, 2) == '--') { | |
| 1057 // a long option | |
| 1058 $optkv = explode('=', $token, 2); | |
| 1059 if (trim($optkv[0]) == '--') { | |
| 1060 // the special argument "--" forces in all cases the end of | |
| 1061 // option scanning. | |
| 1062 $this->_stopflag = true; | |
| 1063 return; | |
| 1064 } | |
| 1065 $opt = $this->findOption($optkv[0]); | |
| 1066 if (!$opt) { | |
| 1067 throw Console_CommandLine_Exception::factory( | |
| 1068 'OPTION_UNKNOWN', | |
| 1069 array('name' => $optkv[0]), | |
| 1070 $this, | |
| 1071 $this->messages | |
| 1072 ); | |
| 1073 } | |
| 1074 $value = isset($optkv[1]) ? $optkv[1] : false; | |
| 1075 if (!$opt->expectsArgument() && $value !== false) { | |
| 1076 throw Console_CommandLine_Exception::factory( | |
| 1077 'OPTION_VALUE_UNEXPECTED', | |
| 1078 array('name' => $opt->name, 'value' => $value), | |
| 1079 $this, | |
| 1080 $this->messages | |
| 1081 ); | |
| 1082 } | |
| 1083 if ($opt->expectsArgument() && $value === false) { | |
| 1084 // maybe the long option argument is separated by a space, if | |
| 1085 // this is the case it will be the next arg | |
| 1086 if ($last && !$opt->argument_optional) { | |
| 1087 throw Console_CommandLine_Exception::factory( | |
| 1088 'OPTION_VALUE_REQUIRED', | |
| 1089 array('name' => $opt->name), | |
| 1090 $this, | |
| 1091 $this->messages | |
| 1092 ); | |
| 1093 } | |
| 1094 // we will have a value next time | |
| 1095 $this->_lastopt = $opt; | |
| 1096 return; | |
| 1097 } | |
| 1098 if ($opt->action == 'StoreArray') { | |
| 1099 $this->_lastopt = $opt; | |
| 1100 } | |
| 1101 $this->_dispatchAction($opt, $value, $result); | |
| 1102 } else if (!$this->_stopflag && | |
| 1103 strlen($token) > ($this->avoid_reading_stdin ? 1 : 0) && | |
| 1104 substr($token, 0, 1) == '-') { | |
| 1105 // a short option | |
| 1106 $optname = substr($token, 0, 2); | |
| 1107 if ($optname == '-' && !$this->avoid_reading_stdin) { | |
| 1108 // special case of "-": try to read stdin | |
| 1109 $args[] = file_get_contents('php://stdin'); | |
| 1110 return; | |
| 1111 } | |
| 1112 $opt = $this->findOption($optname); | |
| 1113 if (!$opt) { | |
| 1114 throw Console_CommandLine_Exception::factory( | |
| 1115 'OPTION_UNKNOWN', | |
| 1116 array('name' => $optname), | |
| 1117 $this, | |
| 1118 $this->messages | |
| 1119 ); | |
| 1120 } | |
| 1121 // parse other options or set the value | |
| 1122 // in short: handle -f<value> and -f <value> | |
| 1123 $next = substr($token, 2, 1); | |
| 1124 // check if we must wait for a value | |
| 1125 if (!$next) { | |
| 1126 if ($opt->expectsArgument()) { | |
| 1127 if ($last && !$opt->argument_optional) { | |
| 1128 throw Console_CommandLine_Exception::factory( | |
| 1129 'OPTION_VALUE_REQUIRED', | |
| 1130 array('name' => $opt->name), | |
| 1131 $this, | |
| 1132 $this->messages | |
| 1133 ); | |
| 1134 } | |
| 1135 // we will have a value next time | |
| 1136 $this->_lastopt = $opt; | |
| 1137 return; | |
| 1138 } | |
| 1139 $value = false; | |
| 1140 } else { | |
| 1141 if (!$opt->expectsArgument()) { | |
| 1142 if ($nextopt = $this->findOption('-' . $next)) { | |
| 1143 $this->_dispatchAction($opt, false, $result); | |
| 1144 $this->parseToken('-' . substr($token, 2), $result, | |
| 1145 $args, $last); | |
| 1146 return; | |
| 1147 } else { | |
| 1148 throw Console_CommandLine_Exception::factory( | |
| 1149 'OPTION_UNKNOWN', | |
| 1150 array('name' => $next), | |
| 1151 $this, | |
| 1152 $this->messages | |
| 1153 ); | |
| 1154 } | |
| 1155 } | |
| 1156 if ($opt->action == 'StoreArray') { | |
| 1157 $this->_lastopt = $opt; | |
| 1158 } | |
| 1159 $value = substr($token, 2); | |
| 1160 } | |
| 1161 $this->_dispatchAction($opt, $value, $result); | |
| 1162 } else { | |
| 1163 // We have an argument. | |
| 1164 // if we are in POSIX compliant mode, we must set the stop flag to | |
| 1165 // true in order to stop option parsing. | |
| 1166 if (!$this->_stopflag && $this->force_posix) { | |
| 1167 $this->_stopflag = true; | |
| 1168 } | |
| 1169 if (!is_null($token)) { | |
| 1170 $args[] = $token; | |
| 1171 } | |
| 1172 } | |
| 1173 } | |
| 1174 | |
| 1175 // }}} | |
| 1176 // addBuiltinOptions() {{{ | |
| 1177 | |
| 1178 /** | |
| 1179 * Adds the builtin "Help" and "Version" options if needed. | |
| 1180 * | |
| 1181 * @return void | |
| 1182 */ | |
| 1183 public function addBuiltinOptions() | |
| 1184 { | |
| 1185 if ($this->add_help_option) { | |
| 1186 $helpOptionParams = array( | |
| 1187 'long_name' => '--help', | |
| 1188 'description' => 'show this help message and exit', | |
| 1189 'action' => 'Help' | |
| 1190 ); | |
| 1191 if (!($option = $this->findOption('-h')) || $option->action == 'Help') { | |
| 1192 // short name is available, take it | |
| 1193 $helpOptionParams['short_name'] = '-h'; | |
| 1194 } | |
| 1195 $this->addOption('help', $helpOptionParams); | |
| 1196 } | |
| 1197 if ($this->add_version_option && !empty($this->version)) { | |
| 1198 $versionOptionParams = array( | |
| 1199 'long_name' => '--version', | |
| 1200 'description' => 'show the program version and exit', | |
| 1201 'action' => 'Version' | |
| 1202 ); | |
| 1203 if (!$this->findOption('-v')) { | |
| 1204 // short name is available, take it | |
| 1205 $versionOptionParams['short_name'] = '-v'; | |
| 1206 } | |
| 1207 $this->addOption('version', $versionOptionParams); | |
| 1208 } | |
| 1209 } | |
| 1210 | |
| 1211 // }}} | |
| 1212 // getArgcArgv() {{{ | |
| 1213 | |
| 1214 /** | |
| 1215 * Tries to return an array containing argc and argv, or trigger an error | |
| 1216 * if it fails to get them. | |
| 1217 * | |
| 1218 * @return array The argc/argv array | |
| 1219 * @throws Console_CommandLine_Exception | |
| 1220 */ | |
| 1221 protected function getArgcArgv() | |
| 1222 { | |
| 1223 if (php_sapi_name() != 'cli') { | |
| 1224 // we have a web request | |
| 1225 $argv = array($this->name); | |
| 1226 if (isset($_REQUEST)) { | |
| 1227 foreach ($_REQUEST as $key => $value) { | |
| 1228 if (!is_array($value)) { | |
| 1229 $value = array($value); | |
| 1230 } | |
| 1231 $opt = $this->findOption($key); | |
| 1232 if ($opt instanceof Console_CommandLine_Option) { | |
| 1233 // match a configured option | |
| 1234 $argv[] = $opt->short_name ? | |
| 1235 $opt->short_name : $opt->long_name; | |
| 1236 foreach ($value as $v) { | |
| 1237 if ($opt->expectsArgument()) { | |
| 1238 $argv[] = isset($_REQUEST[$key]) ? urldecode($v) : $v; | |
| 1239 } else if ($v == '0' || $v == 'false') { | |
| 1240 array_pop($argv); | |
| 1241 } | |
| 1242 } | |
| 1243 } else if (isset($this->args[$key])) { | |
| 1244 // match a configured argument | |
| 1245 foreach ($value as $v) { | |
| 1246 $argv[] = isset($_REQUEST[$key]) ? urldecode($v) : $v; | |
| 1247 } | |
| 1248 } | |
| 1249 } | |
| 1250 } | |
| 1251 return array(count($argv), $argv); | |
| 1252 } | |
| 1253 if (isset($argc) && isset($argv)) { | |
| 1254 // case of register_argv_argc = 1 | |
| 1255 return array($argc, $argv); | |
| 1256 } | |
| 1257 if (isset($_SERVER['argc']) && isset($_SERVER['argv'])) { | |
| 1258 return array($_SERVER['argc'], $_SERVER['argv']); | |
| 1259 } | |
| 1260 return array(0, array()); | |
| 1261 } | |
| 1262 | |
| 1263 // }}} | |
| 1264 // _dispatchAction() {{{ | |
| 1265 | |
| 1266 /** | |
| 1267 * Dispatches the given option or store the option to dispatch it later. | |
| 1268 * | |
| 1269 * @param Console_CommandLine_Option $option The option instance | |
| 1270 * @param string $token Command line token to parse | |
| 1271 * @param Console_CommandLine_Result $result The result instance | |
| 1272 * | |
| 1273 * @return void | |
| 1274 */ | |
| 1275 private function _dispatchAction($option, $token, $result) | |
| 1276 { | |
| 1277 if ($option->action == 'Password') { | |
| 1278 $this->_dispatchLater[] = array($option, $token, $result); | |
| 1279 } else { | |
| 1280 $option->dispatchAction($token, $result, $this); | |
| 1281 } | |
| 1282 } | |
| 1283 // }}} | |
| 1284 // _getSubCommand() {{{ | |
| 1285 | |
| 1286 /** | |
| 1287 * Tries to return the subcommand that matches the given token or returns | |
| 1288 * false if no subcommand was found. | |
| 1289 * | |
| 1290 * @param string $token Current command line token | |
| 1291 * | |
| 1292 * @return mixed An instance of Console_CommandLine_Command or false | |
| 1293 */ | |
| 1294 private function _getSubCommand($token) | |
| 1295 { | |
| 1296 foreach ($this->commands as $cmd) { | |
| 1297 if ($cmd->name == $token || in_array($token, $cmd->aliases)) { | |
| 1298 return $cmd; | |
| 1299 } | |
| 1300 } | |
| 1301 return false; | |
| 1302 } | |
| 1303 | |
| 1304 // }}} | |
| 1305 } |
