1290 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			1290 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			PHP
		
	
	
	
<?php
 | 
						|
 | 
						|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
 | 
						|
 | 
						|
/**
 | 
						|
 * This file is part of the PEAR Console_CommandLine package.
 | 
						|
 *
 | 
						|
 * A full featured package for managing command-line options and arguments 
 | 
						|
 * hightly inspired from python optparse module, it allows the developper to 
 | 
						|
 * easily build complex command line interfaces.
 | 
						|
 *
 | 
						|
 * PHP version 5
 | 
						|
 *
 | 
						|
 * LICENSE: This source file is subject to the MIT license that is available
 | 
						|
 * through the world-wide-web at the following URI:
 | 
						|
 * http://opensource.org/licenses/mit-license.php
 | 
						|
 *
 | 
						|
 * @category  Console 
 | 
						|
 * @package   Console_CommandLine
 | 
						|
 * @author    David JEAN LOUIS <izimobil@gmail.com>
 | 
						|
 * @copyright 2007 David JEAN LOUIS
 | 
						|
 * @license   http://opensource.org/licenses/mit-license.php MIT License 
 | 
						|
 * @version   CVS: $Id$
 | 
						|
 * @link      http://pear.php.net/package/Console_CommandLine
 | 
						|
 * @since     Class available since release 0.1.0
 | 
						|
 * @filesource
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * Required unconditionally
 | 
						|
 */
 | 
						|
require_once 'Console/CommandLine/Exception.php';
 | 
						|
require_once 'Console/CommandLine/Outputter/Default.php';
 | 
						|
require_once 'Console/CommandLine/Renderer/Default.php';
 | 
						|
require_once 'Console/CommandLine/MessageProvider/Default.php';
 | 
						|
 | 
						|
/**
 | 
						|
 * Main class for parsing command line options and arguments.
 | 
						|
 * 
 | 
						|
 * There are three ways to create parsers with this class:
 | 
						|
 * <code>
 | 
						|
 * // direct usage
 | 
						|
 * $parser = new Console_CommandLine();
 | 
						|
 *
 | 
						|
 * // with an xml definition file
 | 
						|
 * $parser = Console_CommandLine::fromXmlFile('path/to/file.xml');
 | 
						|
 *
 | 
						|
 * // with an xml definition string
 | 
						|
 * $validXmlString = '..your xml string...';
 | 
						|
 * $parser = Console_CommandLine::fromXmlString($validXmlString);
 | 
						|
 * </code>
 | 
						|
 *
 | 
						|
 * @category  Console
 | 
						|
 * @package   Console_CommandLine
 | 
						|
 * @author    David JEAN LOUIS <izimobil@gmail.com>
 | 
						|
 * @copyright 2007 David JEAN LOUIS
 | 
						|
 * @license   http://opensource.org/licenses/mit-license.php MIT License 
 | 
						|
 * @version   Release: 1.2.0
 | 
						|
 * @link      http://pear.php.net/package/Console_CommandLine
 | 
						|
 * @since     File available since release 0.1.0
 | 
						|
 * @example   docs/examples/ex1.php
 | 
						|
 * @example   docs/examples/ex2.php
 | 
						|
 */
 | 
						|
class Console_CommandLine
 | 
						|
{
 | 
						|
    // Public properties {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Error messages.
 | 
						|
     *
 | 
						|
     * @var array $errors Error messages
 | 
						|
     * @todo move this to Console_CommandLine_MessageProvider
 | 
						|
     */
 | 
						|
    public static $errors = array(
 | 
						|
        'option_bad_name'                    => 'option name must be a valid php variable name (got: {$name})',
 | 
						|
        'argument_bad_name'                  => 'argument name must be a valid php variable name (got: {$name})',
 | 
						|
        'argument_no_default'                => 'only optional arguments can have a default value',
 | 
						|
        'option_long_and_short_name_missing' => 'you must provide at least an option short name or long name for option "{$name}"',
 | 
						|
        'option_bad_short_name'              => 'option "{$name}" short name must be a dash followed by a letter (got: "{$short_name}")',
 | 
						|
        'option_bad_long_name'               => 'option "{$name}" long name must be 2 dashes followed by a word (got: "{$long_name}")',
 | 
						|
        'option_unregistered_action'         => 'unregistered action "{$action}" for option "{$name}".',
 | 
						|
        'option_bad_action'                  => 'invalid action for option "{$name}".',
 | 
						|
        'option_invalid_callback'            => 'you must provide a valid callback for option "{$name}"',
 | 
						|
        'action_class_does_not_exists'       => 'action "{$name}" class "{$class}" not found, make sure that your class is available before calling Console_CommandLine::registerAction()',
 | 
						|
        'invalid_xml_file'                   => 'XML definition file "{$file}" does not exists or is not readable',
 | 
						|
        'invalid_rng_file'                   => 'RNG file "{$file}" does not exists or is not readable'
 | 
						|
    );
 | 
						|
 | 
						|
    /**
 | 
						|
     * The name of the program, if not given it defaults to argv[0].
 | 
						|
     *
 | 
						|
     * @var string $name Name of your program
 | 
						|
     */
 | 
						|
    public $name;
 | 
						|
 | 
						|
    /**
 | 
						|
     * A description text that will be displayed in the help message.
 | 
						|
     *
 | 
						|
     * @var string $description Description of your program
 | 
						|
     */
 | 
						|
    public $description = '';
 | 
						|
 | 
						|
    /**
 | 
						|
     * A string that represents the version of the program, if this property is 
 | 
						|
     * not empty and property add_version_option is not set to false, the
 | 
						|
     * command line parser will add a --version option, that will display the
 | 
						|
     * property content.
 | 
						|
     *
 | 
						|
     * @var    string $version
 | 
						|
     * @access public
 | 
						|
     */
 | 
						|
    public $version = '';
 | 
						|
 | 
						|
    /**
 | 
						|
     * Boolean that determine if the command line parser should add the help
 | 
						|
     * (-h, --help) option automatically.
 | 
						|
     *
 | 
						|
     * @var bool $add_help_option Whether to add a help option or not
 | 
						|
     */
 | 
						|
    public $add_help_option = true;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Boolean that determine if the command line parser should add the version
 | 
						|
     * (-v, --version) option automatically.
 | 
						|
     * Note that the version option is also generated only if the version 
 | 
						|
     * property is not empty, it's up to you to provide a version string of 
 | 
						|
     * course.
 | 
						|
     *
 | 
						|
     * @var bool $add_version_option Whether to add a version option or not
 | 
						|
     */
 | 
						|
    public $add_version_option = true;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Boolean that determine if providing a subcommand is mandatory.
 | 
						|
     *
 | 
						|
     * @var bool $subcommand_required Whether a subcommand is required or not
 | 
						|
     */
 | 
						|
    public $subcommand_required = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The command line parser renderer instance.
 | 
						|
     *
 | 
						|
     * @var    object that implements Console_CommandLine_Renderer interface
 | 
						|
     * @access protected
 | 
						|
     */
 | 
						|
    public $renderer = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The command line parser outputter instance.
 | 
						|
     *
 | 
						|
     * @var Console_CommandLine_Outputter An outputter
 | 
						|
     */
 | 
						|
    public $outputter = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The command line message provider instance.
 | 
						|
     *
 | 
						|
     * @var Console_CommandLine_MessageProvider A message provider instance
 | 
						|
     */
 | 
						|
    public $message_provider = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Boolean that tells the parser to be POSIX compliant, POSIX demands the 
 | 
						|
     * following behavior: the first non-option stops option processing.
 | 
						|
     *
 | 
						|
     * @var bool $force_posix Whether to force posix compliance or not
 | 
						|
     */
 | 
						|
    public $force_posix = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Boolean that tells the parser to set relevant options default values, 
 | 
						|
     * according to the option action.
 | 
						|
     *
 | 
						|
     * @see Console_CommandLine_Option::setDefaults()
 | 
						|
     * @var bool $force_options_defaults Whether to force option default values
 | 
						|
     */
 | 
						|
    public $force_options_defaults = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * An array of Console_CommandLine_Option objects.
 | 
						|
     *
 | 
						|
     * @var array $options The options array
 | 
						|
     */
 | 
						|
    public $options = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * An array of Console_CommandLine_Argument objects.
 | 
						|
     *
 | 
						|
     * @var array $args The arguments array
 | 
						|
     */
 | 
						|
    public $args = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * An array of Console_CommandLine_Command objects (sub commands).
 | 
						|
     *
 | 
						|
     * @var array $commands The commands array
 | 
						|
     */
 | 
						|
    public $commands = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * Parent, only relevant in Command objects but left here for interface 
 | 
						|
     * convenience.
 | 
						|
     *
 | 
						|
     * @var Console_CommandLine The parent instance
 | 
						|
     * @todo move Console_CommandLine::parent to Console_CommandLine_Command
 | 
						|
     */
 | 
						|
    public $parent = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Array of valid actions for an option, this array will also store user 
 | 
						|
     * registered actions.
 | 
						|
     *
 | 
						|
     * The array format is:
 | 
						|
     * <pre>
 | 
						|
     * array(
 | 
						|
     *     <ActionName:string> => array(<ActionClass:string>, <builtin:bool>)
 | 
						|
     * )
 | 
						|
     * </pre>
 | 
						|
     *
 | 
						|
     * @var array $actions List of valid actions
 | 
						|
     */
 | 
						|
    public static $actions = array(
 | 
						|
        'StoreTrue'   => array('Console_CommandLine_Action_StoreTrue', true),
 | 
						|
        'StoreFalse'  => array('Console_CommandLine_Action_StoreFalse', true),
 | 
						|
        'StoreString' => array('Console_CommandLine_Action_StoreString', true),
 | 
						|
        'StoreInt'    => array('Console_CommandLine_Action_StoreInt', true),
 | 
						|
        'StoreFloat'  => array('Console_CommandLine_Action_StoreFloat', true),
 | 
						|
        'StoreArray'  => array('Console_CommandLine_Action_StoreArray', true),
 | 
						|
        'Callback'    => array('Console_CommandLine_Action_Callback', true),
 | 
						|
        'Counter'     => array('Console_CommandLine_Action_Counter', true),
 | 
						|
        'Help'        => array('Console_CommandLine_Action_Help', true),
 | 
						|
        'Version'     => array('Console_CommandLine_Action_Version', true),
 | 
						|
        'Password'    => array('Console_CommandLine_Action_Password', true),
 | 
						|
        'List'        => array('Console_CommandLine_Action_List', true),
 | 
						|
    );
 | 
						|
 | 
						|
    /**
 | 
						|
     * Custom errors messages for this command
 | 
						|
     *
 | 
						|
     * This array is of the form:
 | 
						|
     * <code>
 | 
						|
     * <?php
 | 
						|
     * array(
 | 
						|
     *     $messageName => $messageText,
 | 
						|
     *     $messageName => $messageText,
 | 
						|
     *     ...
 | 
						|
     * );
 | 
						|
     * ?>
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * If specified, these messages override the messages provided by the
 | 
						|
     * default message provider. For example:
 | 
						|
     * <code>
 | 
						|
     * <?php
 | 
						|
     * $messages = array(
 | 
						|
     *     'ARGUMENT_REQUIRED' => 'The argument foo is required.',
 | 
						|
     * );
 | 
						|
     * ?>
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * @var array
 | 
						|
     * @see Console_CommandLine_MessageProvider_Default
 | 
						|
     */
 | 
						|
    public $messages = array();
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // {{{ Private properties
 | 
						|
 | 
						|
    /**
 | 
						|
     * Array of options that must be dispatched at the end.
 | 
						|
     *
 | 
						|
     * @var array $_dispatchLater Options to be dispatched
 | 
						|
     */
 | 
						|
    private $_dispatchLater = array();
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // __construct() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Constructor.
 | 
						|
     * Example:
 | 
						|
     *
 | 
						|
     * <code>
 | 
						|
     * $parser = new Console_CommandLine(array(
 | 
						|
     *     'name'               => 'yourprogram', // defaults to argv[0]
 | 
						|
     *     'description'        => 'Description of your program',
 | 
						|
     *     'version'            => '0.0.1', // your program version
 | 
						|
     *     'add_help_option'    => true, // or false to disable --help option
 | 
						|
     *     'add_version_option' => true, // or false to disable --version option
 | 
						|
     *     'force_posix'        => false // or true to force posix compliance
 | 
						|
     * ));
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * @param array $params An optional array of parameters
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function __construct(array $params = array()) 
 | 
						|
    {
 | 
						|
        if (isset($params['name'])) {
 | 
						|
            $this->name = $params['name'];
 | 
						|
        } else if (isset($argv) && count($argv) > 0) {
 | 
						|
            $this->name = $argv[0];
 | 
						|
        } else if (isset($_SERVER['argv']) && count($_SERVER['argv']) > 0) {
 | 
						|
            $this->name = $_SERVER['argv'][0];
 | 
						|
        } else if (isset($_SERVER['SCRIPT_NAME'])) {
 | 
						|
            $this->name = basename($_SERVER['SCRIPT_NAME']);
 | 
						|
        }
 | 
						|
        if (isset($params['description'])) {
 | 
						|
            $this->description = $params['description'];
 | 
						|
        }
 | 
						|
        if (isset($params['version'])) {
 | 
						|
            $this->version = $params['version'];
 | 
						|
        }
 | 
						|
        if (isset($params['add_version_option'])) {
 | 
						|
            $this->add_version_option = $params['add_version_option'];
 | 
						|
        }
 | 
						|
        if (isset($params['add_help_option'])) {
 | 
						|
            $this->add_help_option = $params['add_help_option'];
 | 
						|
        }
 | 
						|
        if (isset($params['subcommand_required'])) {
 | 
						|
            $this->subcommand_required = $params['subcommand_required'];
 | 
						|
        }
 | 
						|
        if (isset($params['force_posix'])) {
 | 
						|
            $this->force_posix = $params['force_posix'];
 | 
						|
        } else if (getenv('POSIXLY_CORRECT')) {
 | 
						|
            $this->force_posix = true;
 | 
						|
        }
 | 
						|
        if (isset($params['messages']) && is_array($params['messages'])) {
 | 
						|
            $this->messages = $params['messages'];
 | 
						|
        }
 | 
						|
        // set default instances
 | 
						|
        $this->renderer         = new Console_CommandLine_Renderer_Default($this);
 | 
						|
        $this->outputter        = new Console_CommandLine_Outputter_Default();
 | 
						|
        $this->message_provider = new Console_CommandLine_MessageProvider_Default();
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // accept() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Method to allow Console_CommandLine to accept either:
 | 
						|
     *  + a custom renderer, 
 | 
						|
     *  + a custom outputter,
 | 
						|
     *  + or a custom message provider
 | 
						|
     *
 | 
						|
     * @param mixed $instance The custom instance
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     * @throws Console_CommandLine_Exception if wrong argument passed
 | 
						|
     */
 | 
						|
    public function accept($instance) 
 | 
						|
    {
 | 
						|
        if ($instance instanceof Console_CommandLine_Renderer) {
 | 
						|
            if (property_exists($instance, 'parser') && !$instance->parser) {
 | 
						|
                $instance->parser = $this;
 | 
						|
            }
 | 
						|
            $this->renderer = $instance;
 | 
						|
        } else if ($instance instanceof Console_CommandLine_Outputter) {
 | 
						|
            $this->outputter = $instance;
 | 
						|
        } else if ($instance instanceof Console_CommandLine_MessageProvider) {
 | 
						|
            $this->message_provider = $instance;
 | 
						|
        } else {
 | 
						|
            throw Console_CommandLine_Exception::factory(
 | 
						|
                'INVALID_CUSTOM_INSTANCE',
 | 
						|
                array(),
 | 
						|
                $this,
 | 
						|
                $this->messages
 | 
						|
            );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // fromXmlFile() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns a command line parser instance built from an xml file.
 | 
						|
     *
 | 
						|
     * Example:
 | 
						|
     * <code>
 | 
						|
     * require_once 'Console/CommandLine.php';
 | 
						|
     * $parser = Console_CommandLine::fromXmlFile('path/to/file.xml');
 | 
						|
     * $result = $parser->parse();
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * @param string $file Path to the xml file
 | 
						|
     *
 | 
						|
     * @return Console_CommandLine The parser instance
 | 
						|
     */
 | 
						|
    public static function fromXmlFile($file) 
 | 
						|
    {
 | 
						|
        include_once 'Console/CommandLine/XmlParser.php';
 | 
						|
        return Console_CommandLine_XmlParser::parse($file);
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // fromXmlString() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns a command line parser instance built from an xml string.
 | 
						|
     *
 | 
						|
     * Example:
 | 
						|
     * <code>
 | 
						|
     * require_once 'Console/CommandLine.php';
 | 
						|
     * $xmldata = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
 | 
						|
     * <command>
 | 
						|
     *   <description>Compress files</description>
 | 
						|
     *   <option name="quiet">
 | 
						|
     *     <short_name>-q</short_name>
 | 
						|
     *     <long_name>--quiet</long_name>
 | 
						|
     *     <description>be quiet when run</description>
 | 
						|
     *     <action>StoreTrue/action>
 | 
						|
     *   </option>
 | 
						|
     *   <argument name="files">
 | 
						|
     *     <description>a list of files</description>
 | 
						|
     *     <multiple>true</multiple>
 | 
						|
     *   </argument>
 | 
						|
     * </command>';
 | 
						|
     * $parser = Console_CommandLine::fromXmlString($xmldata);
 | 
						|
     * $result = $parser->parse();
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * @param string $string The xml data
 | 
						|
     *
 | 
						|
     * @return Console_CommandLine The parser instance
 | 
						|
     */
 | 
						|
    public static function fromXmlString($string) 
 | 
						|
    {
 | 
						|
        include_once 'Console/CommandLine/XmlParser.php';
 | 
						|
        return Console_CommandLine_XmlParser::parseString($string);
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // addArgument() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Adds an argument to the command line parser and returns it.
 | 
						|
     *
 | 
						|
     * Adds an argument with the name $name and set its attributes with the
 | 
						|
     * array $params, then return the Console_CommandLine_Argument instance
 | 
						|
     * created.
 | 
						|
     * The method accepts another form: you can directly pass a 
 | 
						|
     * Console_CommandLine_Argument object as the sole argument, this allows
 | 
						|
     * you to contruct the argument separately, in order to reuse it in
 | 
						|
     * different command line parsers or commands for example.
 | 
						|
     *
 | 
						|
     * Example:
 | 
						|
     * <code>
 | 
						|
     * $parser = new Console_CommandLine();
 | 
						|
     * // add an array argument
 | 
						|
     * $parser->addArgument('input_files', array('multiple'=>true));
 | 
						|
     * // add a simple argument
 | 
						|
     * $parser->addArgument('output_file');
 | 
						|
     * $result = $parser->parse();
 | 
						|
     * print_r($result->args['input_files']);
 | 
						|
     * print_r($result->args['output_file']);
 | 
						|
     * // will print:
 | 
						|
     * // array('file1', 'file2')
 | 
						|
     * // 'file3'
 | 
						|
     * // if the command line was:
 | 
						|
     * // myscript.php file1 file2 file3
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * In a terminal, the help will be displayed like this:
 | 
						|
     * <code>
 | 
						|
     * $ myscript.php install -h
 | 
						|
     * Usage: myscript.php <input_files...> <output_file>
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * @param mixed $name   A string containing the argument name or an
 | 
						|
     *                      instance of Console_CommandLine_Argument
 | 
						|
     * @param array $params An array containing the argument attributes
 | 
						|
     *
 | 
						|
     * @return Console_CommandLine_Argument the added argument
 | 
						|
     * @see Console_CommandLine_Argument
 | 
						|
     */
 | 
						|
    public function addArgument($name, $params = array())
 | 
						|
    {
 | 
						|
        if ($name instanceof Console_CommandLine_Argument) {
 | 
						|
            $argument = $name;
 | 
						|
        } else {
 | 
						|
            include_once 'Console/CommandLine/Argument.php';
 | 
						|
            $argument = new Console_CommandLine_Argument($name, $params);
 | 
						|
        }
 | 
						|
        $argument->validate();
 | 
						|
        $this->args[$argument->name] = $argument;
 | 
						|
        return $argument;
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // addCommand() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Adds a sub-command to the command line parser.
 | 
						|
     *
 | 
						|
     * Adds a command with the given $name to the parser and returns the 
 | 
						|
     * Console_CommandLine_Command instance, you can then populate the command
 | 
						|
     * with options, configure it, etc... like you would do for the main parser
 | 
						|
     * because the class Console_CommandLine_Command inherits from
 | 
						|
     * Console_CommandLine.
 | 
						|
     *
 | 
						|
     * An example:
 | 
						|
     * <code>
 | 
						|
     * $parser = new Console_CommandLine();
 | 
						|
     * $install_cmd = $parser->addCommand('install');
 | 
						|
     * $install_cmd->addOption(
 | 
						|
     *     'verbose',
 | 
						|
     *     array(
 | 
						|
     *         'short_name'  => '-v',
 | 
						|
     *         'long_name'   => '--verbose',
 | 
						|
     *         'description' => 'be noisy when installing stuff',
 | 
						|
     *         'action'      => 'StoreTrue'
 | 
						|
     *      )
 | 
						|
     * );
 | 
						|
     * $parser->parse();
 | 
						|
     * </code>
 | 
						|
     * Then in a terminal:
 | 
						|
     * <code>
 | 
						|
     * $ myscript.php install -h
 | 
						|
     * Usage: myscript.php install [options]
 | 
						|
     *
 | 
						|
     * Options:
 | 
						|
     *   -h, --help     display this help message and exit
 | 
						|
     *   -v, --verbose  be noisy when installing stuff
 | 
						|
     *
 | 
						|
     * $ myscript.php install --verbose
 | 
						|
     * Installing whatever...
 | 
						|
     * $
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * @param mixed $name   A string containing the command name or an
 | 
						|
     *                      instance of Console_CommandLine_Command
 | 
						|
     * @param array $params An array containing the command attributes
 | 
						|
     *
 | 
						|
     * @return Console_CommandLine_Command the added subcommand
 | 
						|
     * @see    Console_CommandLine_Command
 | 
						|
     */
 | 
						|
    public function addCommand($name, $params = array())
 | 
						|
    {
 | 
						|
        if ($name instanceof Console_CommandLine_Command) {
 | 
						|
            $command = $name;
 | 
						|
        } else {
 | 
						|
            include_once 'Console/CommandLine/Command.php';
 | 
						|
            $params['name'] = $name;
 | 
						|
            $command        = new Console_CommandLine_Command($params);
 | 
						|
            // some properties must cascade to the child command if not 
 | 
						|
            // passed explicitely. This is done only in this case, because if 
 | 
						|
            // we have a Command object we have no way to determine if theses 
 | 
						|
            // properties have already been set
 | 
						|
            $cascade = array(
 | 
						|
                'add_help_option',
 | 
						|
                'add_version_option',
 | 
						|
                'outputter',
 | 
						|
                'message_provider',
 | 
						|
                'force_posix',
 | 
						|
                'force_options_defaults'
 | 
						|
            );
 | 
						|
            foreach ($cascade as $property) {
 | 
						|
                if (!isset($params[$property])) {
 | 
						|
                    $command->$property = $this->$property;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (!isset($params['renderer'])) {
 | 
						|
                $renderer          = clone $this->renderer;
 | 
						|
                $renderer->parser  = $command;
 | 
						|
                $command->renderer = $renderer;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $command->parent = $this;
 | 
						|
        $this->commands[$command->name] = $command;
 | 
						|
        return $command;
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // addOption() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Adds an option to the command line parser and returns it.
 | 
						|
     *
 | 
						|
     * Adds an option with the name $name and set its attributes with the
 | 
						|
     * array $params, then return the Console_CommandLine_Option instance
 | 
						|
     * created.
 | 
						|
     * The method accepts another form: you can directly pass a 
 | 
						|
     * Console_CommandLine_Option object as the sole argument, this allows
 | 
						|
     * you to contruct the option separately, in order to reuse it in different
 | 
						|
     * command line parsers or commands for example.
 | 
						|
     *
 | 
						|
     * Example:
 | 
						|
     * <code>
 | 
						|
     * $parser = new Console_CommandLine();
 | 
						|
     * $parser->addOption('path', array(
 | 
						|
     *     'short_name'  => '-p',  // a short name
 | 
						|
     *     'long_name'   => '--path', // a long name
 | 
						|
     *     'description' => 'path to the dir', // a description msg
 | 
						|
     *     'action'      => 'StoreString',
 | 
						|
     *     'default'     => '/tmp' // a default value
 | 
						|
     * ));
 | 
						|
     * $parser->parse();
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * In a terminal, the help will be displayed like this:
 | 
						|
     * <code>
 | 
						|
     * $ myscript.php --help
 | 
						|
     * Usage: myscript.php [options]
 | 
						|
     *
 | 
						|
     * Options:
 | 
						|
     *   -h, --help  display this help message and exit
 | 
						|
     *   -p, --path  path to the dir
 | 
						|
     *
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * Various methods to specify an option, these 3 commands are equivalent:
 | 
						|
     * <code>
 | 
						|
     * $ myscript.php --path=some/path
 | 
						|
     * $ myscript.php -p some/path
 | 
						|
     * $ myscript.php -psome/path
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * @param mixed $name   A string containing the option name or an
 | 
						|
     *                      instance of Console_CommandLine_Option
 | 
						|
     * @param array $params An array containing the option attributes
 | 
						|
     *
 | 
						|
     * @return Console_CommandLine_Option The added option
 | 
						|
     * @see    Console_CommandLine_Option
 | 
						|
     */
 | 
						|
    public function addOption($name, $params = array())
 | 
						|
    {
 | 
						|
        include_once 'Console/CommandLine/Option.php';
 | 
						|
        if ($name instanceof Console_CommandLine_Option) {
 | 
						|
            $opt = $name;
 | 
						|
        } else {
 | 
						|
            $opt = new Console_CommandLine_Option($name, $params);
 | 
						|
        }
 | 
						|
        $opt->validate();
 | 
						|
        if ($this->force_options_defaults) {
 | 
						|
            $opt->setDefaults();
 | 
						|
        }
 | 
						|
        $this->options[$opt->name] = $opt;
 | 
						|
        if (!empty($opt->choices) && $opt->add_list_option) {
 | 
						|
            $this->addOption('list_' . $opt->name, array(
 | 
						|
                'long_name'     => '--list-' . $opt->name,
 | 
						|
                'description'   => $this->message_provider->get(
 | 
						|
                    'LIST_OPTION_MESSAGE',
 | 
						|
                    array('name' => $opt->name)
 | 
						|
                ),
 | 
						|
                'action'        => 'List',
 | 
						|
                'action_params' => array('list' => $opt->choices),
 | 
						|
            ));
 | 
						|
        }
 | 
						|
        return $opt;
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // displayError() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Displays an error to the user via stderr and exit with $exitCode if its
 | 
						|
     * value is not equals to false.
 | 
						|
     *
 | 
						|
     * @param string $error    The error message
 | 
						|
     * @param int    $exitCode The exit code number (default: 1). If set to
 | 
						|
     *                         false, the exit() function will not be called
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function displayError($error, $exitCode = 1)
 | 
						|
    {
 | 
						|
        $this->outputter->stderr($this->renderer->error($error));
 | 
						|
        if ($exitCode !== false) {
 | 
						|
            exit($exitCode);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // displayUsage() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Displays the usage help message to the user via stdout and exit with
 | 
						|
     * $exitCode if its value is not equals to false.
 | 
						|
     *
 | 
						|
     * @param int $exitCode The exit code number (default: 0). If set to
 | 
						|
     *                      false, the exit() function will not be called
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function displayUsage($exitCode = 0)
 | 
						|
    {
 | 
						|
        $this->outputter->stdout($this->renderer->usage());
 | 
						|
        if ($exitCode !== false) {
 | 
						|
            exit($exitCode);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // displayVersion() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Displays the program version to the user via stdout and exit with
 | 
						|
     * $exitCode if its value is not equals to false.
 | 
						|
     *
 | 
						|
     *
 | 
						|
     * @param int $exitCode The exit code number (default: 0). If set to
 | 
						|
     *                      false, the exit() function will not be called
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function displayVersion($exitCode = 0)
 | 
						|
    {
 | 
						|
        $this->outputter->stdout($this->renderer->version());
 | 
						|
        if ($exitCode !== false) {
 | 
						|
            exit($exitCode);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // findOption() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Finds the option that matches the given short_name (ex: -v), long_name
 | 
						|
     * (ex: --verbose) or name (ex: verbose).
 | 
						|
     *
 | 
						|
     * @param string $str The option identifier
 | 
						|
     *
 | 
						|
     * @return mixed A Console_CommandLine_Option instance or false
 | 
						|
     */
 | 
						|
    public function findOption($str)
 | 
						|
    {
 | 
						|
        $str = trim($str);
 | 
						|
        if ($str === '') {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        $matches = array();
 | 
						|
        foreach ($this->options as $opt) {
 | 
						|
            if ($opt->short_name == $str || $opt->long_name == $str ||
 | 
						|
                $opt->name == $str) {
 | 
						|
                // exact match
 | 
						|
                return $opt;
 | 
						|
            }
 | 
						|
            if (substr($opt->long_name, 0, strlen($str)) === $str) {
 | 
						|
                // abbreviated long option
 | 
						|
                $matches[] = $opt;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if ($count = count($matches)) {
 | 
						|
            if ($count > 1) {
 | 
						|
                $matches_str = '';
 | 
						|
                $padding     = '';
 | 
						|
                foreach ($matches as $opt) {
 | 
						|
                    $matches_str .= $padding . $opt->long_name;
 | 
						|
                    $padding      = ', ';
 | 
						|
                }
 | 
						|
                throw Console_CommandLine_Exception::factory(
 | 
						|
                    'OPTION_AMBIGUOUS',
 | 
						|
                    array('name' => $str, 'matches' => $matches_str),
 | 
						|
                    $this,
 | 
						|
                    $this->messages
 | 
						|
                );
 | 
						|
            }
 | 
						|
            return $matches[0];
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    // }}}
 | 
						|
    // registerAction() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Registers a custom action for the parser, an example:
 | 
						|
     *
 | 
						|
     * <code>
 | 
						|
     *
 | 
						|
     * // in this example we create a "range" action:
 | 
						|
     * // the user will be able to enter something like:
 | 
						|
     * // $ <program> -r 1,5
 | 
						|
     * // and in the result we will have:
 | 
						|
     * // $result->options['range']: array(1, 5)
 | 
						|
     *
 | 
						|
     * require_once 'Console/CommandLine.php';
 | 
						|
     * require_once 'Console/CommandLine/Action.php';
 | 
						|
     *
 | 
						|
     * class ActionRange extends Console_CommandLine_Action
 | 
						|
     * {
 | 
						|
     *     public function execute($value=false, $params=array())
 | 
						|
     *     {
 | 
						|
     *         $range = explode(',', str_replace(' ', '', $value));
 | 
						|
     *         if (count($range) != 2) {
 | 
						|
     *             throw new Exception(sprintf(
 | 
						|
     *                 'Option "%s" must be 2 integers separated by a comma',
 | 
						|
     *                 $this->option->name
 | 
						|
     *             ));
 | 
						|
     *         }
 | 
						|
     *         $this->setResult($range);
 | 
						|
     *     }
 | 
						|
     * }
 | 
						|
     * // then we can register our action
 | 
						|
     * Console_CommandLine::registerAction('Range', 'ActionRange');
 | 
						|
     * // and now our action is available !
 | 
						|
     * $parser = new Console_CommandLine();
 | 
						|
     * $parser->addOption('range', array(
 | 
						|
     *     'short_name'  => '-r',
 | 
						|
     *     'long_name'   => '--range',
 | 
						|
     *     'action'      => 'Range', // note our custom action
 | 
						|
     *     'description' => 'A range of two integers separated by a comma'
 | 
						|
     * ));
 | 
						|
     * // etc...
 | 
						|
     *
 | 
						|
     * </code>
 | 
						|
     *
 | 
						|
     * @param string $name  The name of the custom action
 | 
						|
     * @param string $class The class name of the custom action
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public static function registerAction($name, $class) 
 | 
						|
    {
 | 
						|
        if (!isset(self::$actions[$name])) {
 | 
						|
            if (!class_exists($class)) {
 | 
						|
                self::triggerError('action_class_does_not_exists',
 | 
						|
                    E_USER_ERROR,
 | 
						|
                    array('{$name}' => $name, '{$class}' => $class));
 | 
						|
            }
 | 
						|
            self::$actions[$name] = array($class, false);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // triggerError() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * A wrapper for programming errors triggering.
 | 
						|
     *
 | 
						|
     * @param string $msgId  Identifier of the message
 | 
						|
     * @param int    $level  The php error level
 | 
						|
     * @param array  $params An array of search=>replaces entries
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     * @todo remove Console::triggerError() and use exceptions only
 | 
						|
     */
 | 
						|
    public static function triggerError($msgId, $level, $params=array()) 
 | 
						|
    {
 | 
						|
        if (isset(self::$errors[$msgId])) {
 | 
						|
            $msg = str_replace(array_keys($params),
 | 
						|
                array_values($params), self::$errors[$msgId]); 
 | 
						|
            trigger_error($msg, $level);
 | 
						|
        } else {
 | 
						|
            trigger_error('unknown error', $level);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // parse() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Parses the command line arguments and returns a
 | 
						|
     * Console_CommandLine_Result instance.
 | 
						|
     *
 | 
						|
     * @param integer $userArgc Number of arguments (optional)
 | 
						|
     * @param array   $userArgv Array containing arguments (optional)
 | 
						|
     *
 | 
						|
     * @return Console_CommandLine_Result The result instance
 | 
						|
     * @throws Exception on user errors
 | 
						|
     */
 | 
						|
    public function parse($userArgc=null, $userArgv=null)
 | 
						|
    {
 | 
						|
        $this->addBuiltinOptions();
 | 
						|
        if ($userArgc !== null && $userArgv !== null) {
 | 
						|
            $argc = $userArgc;
 | 
						|
            $argv = $userArgv;
 | 
						|
        } else {
 | 
						|
            list($argc, $argv) = $this->getArgcArgv();
 | 
						|
        }
 | 
						|
        // build an empty result
 | 
						|
        include_once 'Console/CommandLine/Result.php';
 | 
						|
        $result = new Console_CommandLine_Result();
 | 
						|
        if (!($this instanceof Console_CommandLine_Command)) {
 | 
						|
            // remove script name if we're not in a subcommand
 | 
						|
            array_shift($argv);
 | 
						|
            $argc--;
 | 
						|
        }
 | 
						|
        // will contain arguments
 | 
						|
        $args = array();
 | 
						|
        foreach ($this->options as $name=>$option) {
 | 
						|
            $result->options[$name] = $option->default;
 | 
						|
        }
 | 
						|
        // parse command line tokens
 | 
						|
        while ($argc--) {
 | 
						|
            $token = array_shift($argv);
 | 
						|
            try {
 | 
						|
                if ($cmd = $this->_getSubCommand($token)) {
 | 
						|
                    $result->command_name = $cmd->name;
 | 
						|
                    $result->command      = $cmd->parse($argc, $argv);
 | 
						|
                    break;
 | 
						|
                } else {
 | 
						|
                    $this->parseToken($token, $result, $args, $argc);
 | 
						|
                }
 | 
						|
            } catch (Exception $exc) {
 | 
						|
                throw $exc;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        // Parse a null token to allow any undespatched actions to be despatched.
 | 
						|
        $this->parseToken(null, $result, $args, 0);
 | 
						|
        // Check if an invalid subcommand was specified. If there are
 | 
						|
        // subcommands and no arguments, but an argument was provided, it is
 | 
						|
        // an invalid subcommand.
 | 
						|
        if (   count($this->commands) > 0
 | 
						|
            && count($this->args) === 0
 | 
						|
            && count($args) > 0
 | 
						|
        ) {
 | 
						|
            throw Console_CommandLine_Exception::factory(
 | 
						|
                'INVALID_SUBCOMMAND',
 | 
						|
                array('command' => $args[0]),
 | 
						|
                $this,
 | 
						|
                $this->messages
 | 
						|
            );
 | 
						|
        }
 | 
						|
        // if subcommand_required is set to true we must check that we have a
 | 
						|
        // subcommand.
 | 
						|
        if (   count($this->commands)
 | 
						|
            && $this->subcommand_required
 | 
						|
            && !$result->command_name
 | 
						|
        ) {
 | 
						|
            throw Console_CommandLine_Exception::factory(
 | 
						|
                'SUBCOMMAND_REQUIRED',
 | 
						|
                array('commands' => implode(array_keys($this->commands), ', ')),
 | 
						|
                $this,
 | 
						|
                $this->messages
 | 
						|
            );
 | 
						|
        }
 | 
						|
        // minimum argument number check
 | 
						|
        $argnum = 0;
 | 
						|
        foreach ($this->args as $name=>$arg) {
 | 
						|
            if (!$arg->optional) {
 | 
						|
                $argnum++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (count($args) < $argnum) {
 | 
						|
            throw Console_CommandLine_Exception::factory(
 | 
						|
                'ARGUMENT_REQUIRED',
 | 
						|
                array('argnum' => $argnum, 'plural' => $argnum>1 ? 's': ''),
 | 
						|
                $this,
 | 
						|
                $this->messages
 | 
						|
            );
 | 
						|
        }
 | 
						|
        // handle arguments
 | 
						|
        $c = count($this->args);
 | 
						|
        foreach ($this->args as $name=>$arg) {
 | 
						|
            $c--;
 | 
						|
            if ($arg->multiple) {
 | 
						|
                $result->args[$name] = $c ? array_splice($args, 0, -$c) : $args;
 | 
						|
            } else {
 | 
						|
                $result->args[$name] = array_shift($args);
 | 
						|
            }
 | 
						|
            if (!$result->args[$name] && $arg->optional && $arg->default) {
 | 
						|
                $result->args[$name] = $arg->default;
 | 
						|
            }
 | 
						|
            // check value is in argument choices
 | 
						|
            if (!empty($this->args[$name]->choices)) {
 | 
						|
                foreach ($result->args[$name] as $value) {
 | 
						|
                    if (!in_array($value, $arg->choices)) {
 | 
						|
                        throw Console_CommandLine_Exception::factory(
 | 
						|
                            'ARGUMENT_VALUE_NOT_VALID',
 | 
						|
                            array(
 | 
						|
                                'name'    => $name,
 | 
						|
                                'choices' => implode('", "', $arg->choices),
 | 
						|
                                'value'   => implode(' ', $result->args[$name]),
 | 
						|
                            ),
 | 
						|
                            $this,
 | 
						|
                            $arg->messages
 | 
						|
                        );
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        // dispatch deferred options
 | 
						|
        foreach ($this->_dispatchLater as $optArray) {
 | 
						|
            $optArray[0]->dispatchAction($optArray[1], $optArray[2], $this);
 | 
						|
        }
 | 
						|
        return $result;
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // parseToken() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Parses the command line token and modifies *by reference* the $options
 | 
						|
     * and $args arrays.
 | 
						|
     *
 | 
						|
     * @param string $token  The command line token to parse
 | 
						|
     * @param object $result The Console_CommandLine_Result instance
 | 
						|
     * @param array  &$args  The argv array
 | 
						|
     * @param int    $argc   Number of lasting args
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     * @access protected
 | 
						|
     * @throws Exception on user errors
 | 
						|
     */
 | 
						|
    protected function parseToken($token, $result, &$args, $argc)
 | 
						|
    {
 | 
						|
        static $lastopt  = false;
 | 
						|
        static $stopflag = false;
 | 
						|
        $last  = $argc === 0;
 | 
						|
        if (!$stopflag && $lastopt) {
 | 
						|
            if (substr($token, 0, 1) == '-') {
 | 
						|
                if ($lastopt->argument_optional) {
 | 
						|
                    $this->_dispatchAction($lastopt, '', $result);
 | 
						|
                    if ($lastopt->action != 'StoreArray') {
 | 
						|
                        $lastopt = false;
 | 
						|
                    }
 | 
						|
                } else if (isset($result->options[$lastopt->name])) {
 | 
						|
                    // case of an option that expect a list of args
 | 
						|
                    $lastopt = false;
 | 
						|
                } else {
 | 
						|
                    throw Console_CommandLine_Exception::factory(
 | 
						|
                        'OPTION_VALUE_REQUIRED',
 | 
						|
                        array('name' => $lastopt->name),
 | 
						|
                        $this,
 | 
						|
                        $this->messages
 | 
						|
                    );
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                // when a StoreArray option is positioned last, the behavior
 | 
						|
                // is to consider that if there's already an element in the
 | 
						|
                // array, and the commandline expects one or more args, we
 | 
						|
                // leave last tokens to arguments
 | 
						|
                if ($lastopt->action == 'StoreArray'
 | 
						|
                    && !empty($result->options[$lastopt->name])
 | 
						|
                    && count($this->args) > ($argc + count($args))
 | 
						|
                ) {
 | 
						|
                    if (!is_null($token)) {
 | 
						|
                        $args[] = $token;
 | 
						|
                    }
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                if (!is_null($token) || $lastopt->action == 'Password') {
 | 
						|
                    $this->_dispatchAction($lastopt, $token, $result);
 | 
						|
                }
 | 
						|
                if ($lastopt->action != 'StoreArray') {
 | 
						|
                    $lastopt = false;
 | 
						|
                }
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (!$stopflag && substr($token, 0, 2) == '--') {
 | 
						|
            // a long option
 | 
						|
            $optkv = explode('=', $token, 2);
 | 
						|
            if (trim($optkv[0]) == '--') {
 | 
						|
                // the special argument "--" forces in all cases the end of 
 | 
						|
                // option scanning.
 | 
						|
                $stopflag = true;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            $opt = $this->findOption($optkv[0]);
 | 
						|
            if (!$opt) {
 | 
						|
                throw Console_CommandLine_Exception::factory(
 | 
						|
                    'OPTION_UNKNOWN',
 | 
						|
                    array('name' => $optkv[0]),
 | 
						|
                    $this,
 | 
						|
                    $this->messages
 | 
						|
                );
 | 
						|
            }
 | 
						|
            $value = isset($optkv[1]) ? $optkv[1] : false;
 | 
						|
            if (!$opt->expectsArgument() && $value !== false) {
 | 
						|
                throw Console_CommandLine_Exception::factory(
 | 
						|
                    'OPTION_VALUE_UNEXPECTED',
 | 
						|
                    array('name' => $opt->name, 'value' => $value),
 | 
						|
                    $this,
 | 
						|
                    $this->messages
 | 
						|
                );
 | 
						|
            }
 | 
						|
            if ($opt->expectsArgument() && $value === false) {
 | 
						|
                // maybe the long option argument is separated by a space, if 
 | 
						|
                // this is the case it will be the next arg
 | 
						|
                if ($last && !$opt->argument_optional) {
 | 
						|
                    throw Console_CommandLine_Exception::factory(
 | 
						|
                        'OPTION_VALUE_REQUIRED',
 | 
						|
                        array('name' => $opt->name),
 | 
						|
                        $this,
 | 
						|
                        $this->messages
 | 
						|
                    );
 | 
						|
                }
 | 
						|
                // we will have a value next time
 | 
						|
                $lastopt = $opt;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            if ($opt->action == 'StoreArray') {
 | 
						|
                $lastopt = $opt;
 | 
						|
            }
 | 
						|
            $this->_dispatchAction($opt, $value, $result);
 | 
						|
        } else if (!$stopflag && substr($token, 0, 1) == '-') {
 | 
						|
            // a short option
 | 
						|
            $optname = substr($token, 0, 2);
 | 
						|
            if ($optname == '-') {
 | 
						|
                // special case of "-": try to read stdin
 | 
						|
                $args[] = file_get_contents('php://stdin');
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            $opt = $this->findOption($optname);
 | 
						|
            if (!$opt) {
 | 
						|
                throw Console_CommandLine_Exception::factory(
 | 
						|
                    'OPTION_UNKNOWN',
 | 
						|
                    array('name' => $optname),
 | 
						|
                    $this,
 | 
						|
                    $this->messages
 | 
						|
                );
 | 
						|
            }
 | 
						|
            // parse other options or set the value
 | 
						|
            // in short: handle -f<value> and -f <value>
 | 
						|
            $next = substr($token, 2, 1);
 | 
						|
            // check if we must wait for a value
 | 
						|
            if ($next === false) {
 | 
						|
                if ($opt->expectsArgument()) {
 | 
						|
                    if ($last && !$opt->argument_optional) {
 | 
						|
                        throw Console_CommandLine_Exception::factory(
 | 
						|
                            'OPTION_VALUE_REQUIRED',
 | 
						|
                            array('name' => $opt->name),
 | 
						|
                            $this,
 | 
						|
                            $this->messages
 | 
						|
                        );
 | 
						|
                    }
 | 
						|
                    // we will have a value next time
 | 
						|
                    $lastopt = $opt;
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                $value = false;
 | 
						|
            } else {
 | 
						|
                if (!$opt->expectsArgument()) { 
 | 
						|
                    if ($nextopt = $this->findOption('-' . $next)) {
 | 
						|
                        $this->_dispatchAction($opt, false, $result);
 | 
						|
                        $this->parseToken('-' . substr($token, 2), $result,
 | 
						|
                            $args, $last);
 | 
						|
                        return;
 | 
						|
                    } else {
 | 
						|
                        throw Console_CommandLine_Exception::factory(
 | 
						|
                            'OPTION_UNKNOWN',
 | 
						|
                            array('name' => $next),
 | 
						|
                            $this,
 | 
						|
                            $this->messages
 | 
						|
                        );
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if ($opt->action == 'StoreArray') {
 | 
						|
                    $lastopt = $opt;
 | 
						|
                }
 | 
						|
                $value = substr($token, 2);
 | 
						|
            }
 | 
						|
            $this->_dispatchAction($opt, $value, $result);
 | 
						|
        } else {
 | 
						|
            // We have an argument.
 | 
						|
            // if we are in POSIX compliant mode, we must set the stop flag to 
 | 
						|
            // true in order to stop option parsing.
 | 
						|
            if (!$stopflag && $this->force_posix) {
 | 
						|
                $stopflag = true;
 | 
						|
            }
 | 
						|
            if (!is_null($token)) {
 | 
						|
                $args[] = $token;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // addBuiltinOptions() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Adds the builtin "Help" and "Version" options if needed.
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function addBuiltinOptions()
 | 
						|
    {
 | 
						|
        if ($this->add_help_option) {
 | 
						|
            $helpOptionParams = array(
 | 
						|
                'long_name'   => '--help',
 | 
						|
                'description' => 'show this help message and exit',
 | 
						|
                'action'      => 'Help'   
 | 
						|
            );
 | 
						|
            if (!($option = $this->findOption('-h')) || $option->action == 'Help') {
 | 
						|
                // short name is available, take it
 | 
						|
                $helpOptionParams['short_name'] = '-h';
 | 
						|
            }
 | 
						|
            $this->addOption('help', $helpOptionParams);
 | 
						|
        }
 | 
						|
        if ($this->add_version_option && !empty($this->version)) {
 | 
						|
            $versionOptionParams = array(
 | 
						|
                'long_name'   => '--version',
 | 
						|
                'description' => 'show the program version and exit',
 | 
						|
                'action'      => 'Version'   
 | 
						|
            );
 | 
						|
            if (!$this->findOption('-v')) {
 | 
						|
                // short name is available, take it
 | 
						|
                $versionOptionParams['short_name'] = '-v';
 | 
						|
            }
 | 
						|
            $this->addOption('version', $versionOptionParams);
 | 
						|
        }
 | 
						|
    } 
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // getArgcArgv() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Tries to return an array containing argc and argv, or trigger an error
 | 
						|
     * if it fails to get them.
 | 
						|
     *
 | 
						|
     * @return array The argc/argv array
 | 
						|
     * @throws Console_CommandLine_Exception 
 | 
						|
     */
 | 
						|
    protected function getArgcArgv()
 | 
						|
    {
 | 
						|
        if (php_sapi_name() != 'cli') {
 | 
						|
            // we have a web request
 | 
						|
            $argv = array($this->name);
 | 
						|
            if (isset($_REQUEST)) {
 | 
						|
                foreach ($_REQUEST as $key => $value) {
 | 
						|
                    if (!is_array($value)) {
 | 
						|
                        $value = array($value);
 | 
						|
                    }
 | 
						|
                    $opt = $this->findOption($key);
 | 
						|
                    if ($opt instanceof Console_CommandLine_Option) {
 | 
						|
                        // match a configured option
 | 
						|
                        $argv[] = $opt->short_name ? 
 | 
						|
                            $opt->short_name : $opt->long_name;
 | 
						|
                        foreach ($value as $v) {
 | 
						|
                            if ($opt->expectsArgument()) {
 | 
						|
                                $argv[] = isset($_REQUEST[$key]) ? urldecode($v) : $v;
 | 
						|
                            } else if ($v == '0' || $v == 'false') {
 | 
						|
                                array_pop($argv);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    } else if (isset($this->args[$key])) {
 | 
						|
                        // match a configured argument
 | 
						|
                        foreach ($value as $v) {
 | 
						|
                            $argv[] = isset($_REQUEST[$key]) ? urldecode($v) : $v;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return array(count($argv), $argv);
 | 
						|
        }
 | 
						|
        if (isset($argc) && isset($argv)) {
 | 
						|
            // case of register_argv_argc = 1
 | 
						|
            return array($argc, $argv);
 | 
						|
        }
 | 
						|
        if (isset($_SERVER['argc']) && isset($_SERVER['argv'])) {
 | 
						|
            return array($_SERVER['argc'], $_SERVER['argv']);
 | 
						|
        }
 | 
						|
        return array(0, array());
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
    // _dispatchAction() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Dispatches the given option or store the option to dispatch it later.
 | 
						|
     *
 | 
						|
     * @param Console_CommandLine_Option $option The option instance
 | 
						|
     * @param string                     $token  Command line token to parse
 | 
						|
     * @param Console_CommandLine_Result $result The result instance
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    private function _dispatchAction($option, $token, $result)
 | 
						|
    {
 | 
						|
        if ($option->action == 'Password') {
 | 
						|
            $this->_dispatchLater[] = array($option, $token, $result);
 | 
						|
        } else {
 | 
						|
            $option->dispatchAction($token, $result, $this);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // }}}
 | 
						|
    // _getSubCommand() {{{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Tries to return the subcommand that matches the given token or returns
 | 
						|
     * false if no subcommand was found.
 | 
						|
     *
 | 
						|
     * @param string $token Current command line token
 | 
						|
     *
 | 
						|
     * @return mixed An instance of Console_CommandLine_Command or false
 | 
						|
     */
 | 
						|
    private function _getSubCommand($token)
 | 
						|
    {
 | 
						|
        foreach ($this->commands as $cmd) {
 | 
						|
            if ($cmd->name == $token || in_array($token, $cmd->aliases)) {
 | 
						|
                return $cmd;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // }}}
 | 
						|
}
 |