0
|
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 }
|