Apache Zeta Components Manual :: File Source for input.php
Source for file input.php
Documentation is available at input.php
* File containing the ezcConsoleInput class.
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* @version //autogentag//
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* The ezcConsoleInput class handles the given options and arguments on the console.
* This class allows the complete handling of options and arguments submitted
* to a console based application.
* The next example demonstrate how to capture the console options:
* $optionHandler = new ezcConsoleInput();
* // Register simple parameter -h/--help
* $optionHandler->registerOption( new ezcConsoleOption( 'h', 'help' ) );
* // Register complex parameter -f/--file
* $file = new ezcConsoleOption(
* ezcConsoleInput::TYPE_STRING,
* 'Processes a single file.'
* $optionHandler->registerOption( $file );
* // Manipulate parameter -f/--file after registration
* $file->multiple = true;
* // Register another complex parameter that depends on -f and excludes -h
* $dir = new ezcConsoleOption(
* ezcConsoleInput::TYPE_STRING,
* 'Process a directory.',
* 'Processes a complete directory.',
* array( new ezcConsoleOptionRule( $optionHandler->getOption( 'f' ) ) ),
* array( new ezcConsoleOptionRule( $optionHandler->getOption( 'h' ) ) )
* $optionHandler->registerOption( $dir );
* // Register an alias for this parameter
* $optionHandler->registerAlias( 'e', 'extended-dir', $dir );
* // Process registered parameters and handle errors
* $optionHandler->process( array( 'example_input.php', '-h' ) );
* catch ( ezcConsoleOptionException $e )
* // Process a single parameter
* $file = $optionHandler->getOption( 'f' );
* if ( $file->value === false )
* echo "Parameter -{$file->short}/--{$file->long} was not submitted.\n";
* elseif ( $file->value === true )
* echo "Parameter -{$file->short}/--{$file->long} was submitted without value.\n";
* echo "Parameter -{$file->short}/--{$file->long} was submitted with value '".var_export($file->value, true)."'.\n";
* // Process all parameters at once:
* foreach ( $optionHandler->getOptionValues() as $paramShort => $val )
* echo "Parameter $paramShort was not submitted.\n";
* echo "Parameter $paramShort was submitted without a value.\n";
* echo "Parameter $paramShort was submitted multiple times with value: '".implode(', ', $val)."'.\n";
* echo "Parameter $paramShort was submitted with value: '$val'.\n";
* @property ezcConsoleArguments $argumentDefinition Optional argument definition.
* Option does not carry a value.
* Option takes an integer value.
* Option takes a string value.
* Array of option definitions, indexed by number.
* This array stores the ezcConsoleOption objects representing
* For lookup of an option after its short or long values the attributes
* {@link ezcConsoleInput::$optionShort}
* {@link ezcConsoleInput::$optionLong}
private $options =
array();
* Each references a key in {@link ezcConsoleInput::$options}.
* @var array(string=>int)
private $optionShort =
array();
* Each references a key in {@link ezcConsoleInput::$options}.
* @var array(string=>int)
private $optionLong =
array();
* Arguments, if submitted, are stored here.
private $arguments =
array();
* Wether the process() method has already been called.
private $processed =
false;
* Indicates if an option was submitted, that has the isHelpOption flag set.
private $helpOptionSet =
false;
* Tool object for multi-byte encoding safe string operations.
* @var ezcConsoleStringTool
* @var ezcConsoleInputValidator
* @var ezcConsoleInputHelpGenerator
* Collection of properties.
* @var array(string=>mixed)
* Creates an input handler.
$this->argumentDefinition =
null;
$this->stringTool =
new ezcConsoleStringTool();
// @TODO Verify interface and make plugable
$this->validator =
new ezcConsoleStandardInputValidator();
$this->helpGenerator =
new ezcConsoleInputStandardHelpGenerator( $this );
* Registers the new option $option.
* This method adds the new option $option to your option collection. If
* already an option with the assigned short or long value exists, an
* exception will be thrown.
* @see ezcConsoleInput::unregisterOption()
* @param ezcConsoleOption $option
* @return ezcConsoleOption The recently registered option.
foreach ( $this->optionShort as $short =>
$ref )
if ( $short ===
$option->short )
foreach ( $this->optionLong as $long =>
$ref )
if ( $long ===
$option->long )
$this->options[] =
$option;
$this->optionLong[$option->long] =
$option;
if ( $option->short !==
"" )
$this->optionShort[$option->short] =
$option;
* Registers an alias for an option.
* Registers a new alias for an existing option. Aliases can
* be used as if they were a normal option.
* The alias is registered with the short option name $short and the
* long option name $long. The alias references to the existing
* @see ezcConsoleInput::unregisterAlias()
* @param ezcConsoleOption $option
* @throws ezcConsoleOptionNotExistsException
* If the referenced option is not registered.
* @throws ezcConsoleOptionAlreadyRegisteredException
* If another option/alias has taken the provided short or long name.
public function registerAlias( $short, $long, ezcConsoleOption $option )
if ( !isset
( $this->optionShort[$option->short] ) ||
!isset
( $this->optionLong[$option->long] ) )
if ( isset
( $this->optionShort[$short] ) || isset
( $this->optionLong[$long] ) )
$this->optionShort[$short] =
$option;
$this->optionLong[$long] =
$option;
* Registers options according to a string specification.
* Accepts a string to define parameters and registers all parameters as
* options accordingly. String definition, specified in $optionDef, looks
* [s:|size:][u:|user:][a:|all:]
* This string registers 3 parameters:
* @param string $optionDef
* @throws ezcConsoleOptionStringNotWellformedException
* If provided string does not have the correct format.
$regex =
'\[([a-z0-9-]+)([:?*+])?([^|]*)\|([a-z0-9-]+)([:?*+])?\]';
// Check string for wellformedness
if ( preg_match( "/^($regex)+$/", $optionDef ) ==
0 )
foreach ( $matches[1] as $id =>
$short )
if ( !empty( $matches[2][$id] ) ||
!empty( $matches[5][$id] ) )
switch ( !empty( $matches[2][$id] ) ?
$matches[2][$id] :
$matches[5][$id] )
// Allows 0 or more occurances
$option->multiple =
true;
// Allows 1 or more occurances
$option->multiple =
true;
$option->type =
self::TYPE_STRING;
$option->type =
self::TYPE_STRING;
if ( !empty( $matches[3][$id] ) )
$option->default =
$matches[3][$id];
* This function removes an option. All dependencies to that
* specific option are removed completely from every other registered
* @see ezcConsoleInput::registerOption()
* @param ezcConsoleOption $option The option object to unregister.
* @throws ezcConsoleOptionNotExistsException
* If requesting a not registered option.
foreach ( $this->options as $id =>
$existParam )
if ( $existParam ===
$option )
unset
( $this->options[$id] );
$existParam->removeAllExclusions( $option );
$existParam->removeAllDependencies( $option );
foreach ( $this->optionLong as $name =>
$existParam )
if ( $existParam ===
$option )
unset
( $this->optionLong[$name] );
foreach ( $this->optionShort as $name =>
$existParam )
if ( $existParam ===
$option )
unset
( $this->optionShort[$name] );
* Removes an alias to an option.
* This function removes an alias with the short name $short and long
* @see ezcConsoleInput::registerAlias()
* @throws ezcConsoleOptionNoAliasException
* If the requested short/long name belongs to a real parameter instead.
* @todo Check if $short and $long refer to the same option!
foreach ( $this->options as $id =>
$option )
if ( $option->short ===
$short )
if ( $option->long ===
$long )
if ( isset
( $this->optionShort[$short] ) )
unset
( $this->optionShort[$short] );
if ( isset
( $this->optionLong[$long] ) )
unset
( $this->optionLong[$long] );
* Returns the definition object for the option with the name $name.
* This method receives the long or short name of an option and
* returns the ezcConsoleOption object.
* @param string $name Short or long name of the option (without - or --).
* @return ezcConsoleOption
* @throws ezcConsoleOptionNotExistsException
* If requesting a not registered parameter.
if ( isset
( $this->optionShort[$name] ) )
return $this->optionShort[$name];
if ( isset
( $this->optionLong[$name] ) )
return $this->optionLong[$name];
* Process the input parameters.
* Actually process the input options and arguments according to the actual
* Per default this method uses $argc and $argv for processing. You can
* override this setting with your own input, if necessary, using the
* parameters of this method. (Attention, first argument is always the pro
* All exceptions thrown by this method contain an additional attribute "option"
* which specifies the parameter on which the error occurred.
* @param array(string) $args The arguments
* @throws ezcConsoleOptionNotExistsException
* If an option that was submitted does not exist.
* @throws ezcConsoleOptionDependencyViolationException
* If a dependency rule was violated.
* @throws ezcConsoleOptionExclusionViolationException
* If an exclusion rule was violated.
* @throws ezcConsoleOptionTypeViolationException
* If the type of a submitted value violates the options type rule.
* @throws ezcConsoleOptionArgumentsViolationException
* If arguments are passed although a parameter disallowed them.
* @see ezcConsoleOptionException
public function process( array $args =
null )
$args = isset
( $argv ) ?
$argv : isset
( $_SERVER['argv'] ) ?
$_SERVER['argv'] :
array();
$nextIndex =
$this->processOptions( $args );
// No need to parse arguments
$this->processArguments( $args, $nextIndex );
$this->setOptionDefaults();
* Sets defaults for options that have not been submitted.
* Checks all options if they have been submited. If not and a default
* values is present, this is set as the options value.
private function setOptionDefaults()
foreach ( $this->options as $option )
if ( $option->value ===
false ||
$option->value ===
array() )
if ( $option->default !==
null )
$option->value =
$option->default;
* Reads the submitted options from $args array.
* Returns the next index to check for arguments.
* @param array(string) $args
* @throws ezcConsoleOptionNotExistsException
* if a submitted option does not exist.
* @throws ezcConsoleOptionTooManyValuesException
* if an option that expects only a single value was submitted
* @throws ezcConsoleOptionTypeViolationException
* if an option was submitted with a value of the wrong type.
* @throws ezcConsoleOptionMissingValueException
* if an option thats expects a value was submitted without.
private function processOptions( array $args )
$numArgs =
count( $args );
if ( $args[$i] ===
'--' )
// Equalize parameter handling (long params with =)
$this->preprocessLongOption( $args, $i );
// Update number of args, changed by preprocessLongOption()
$numArgs =
count( $args );
$this->processOption( $args, $i );
// Move pointer over argument sign
isset
( $args[$i] ) &&
$args[$i] ==
'--' ? ++
$i :
$i;
* Resets all option and argument values.
* This method is called automatically by {@link process()}, if this method
* is called twice or more, and may also be used to manually reset the
* values of all registered {@ezcConsoleOption} and {@link }
* ezcConsoleArgument} objects.
foreach ( $this->options as $option )
if ( $this->argumentDefinition !==
null )
foreach ( $this->argumentDefinition as $argument )
$this->arguments =
array();
* Returns true if an option with the given name exists, otherwise false.
* Checks if an option with the given name is registered.
* @param string $name Short or long name of the option.
* @return bool True if option exists, otherwise false.
* Returns an array of all registered options.
* Returns an array of all registered options in the following format:
* @return array(string=>ezcConsoleOption) Registered options.
* Returns the values of all submitted options.
* Returns an array of all values submitted to the options. The array is
* indexed by the parameters short name (excluding the '-' prefix). The array
* does not contain any parameter, which value is 'false' (meaning: the
* parameter was not submitted).
* @param bool $longnames Wheather to use longnames for indexing.
* @return array(string=>mixed)
foreach ( $this->options as $param )
if ( $param->value !==
false )
$res[( $longnames ===
true ) ?
$param->long :
$param->short] =
$param->value;
* Returns arguments provided to the program.
* This method returns all arguments provided to a program in an
* int indexed array. Arguments are sorted in the way
* they are submitted to the program. You can disable arguments
* through the 'arguments' flag of a parameter, if you want
* Arguments are either the last part of the program call (if the
* last parameter is not a 'multiple' one) or divided via the '--'
* method which is commonly used on Unix (if the last parameter
* accepts multiple values this is required).
* @return array(string) Arguments.
* Get help information for your options.
* This method returns an array of help information for your options,
* indexed by int. Each help info has 2 fields:
* 0 => The options names ("<short> / <long>")
* 1 => The help text (depending on the $long parameter)
* The $long options determines if you want to get the short or long help
* texts. The array returned can be used by {@link ezcConsoleTable}.
* If using the second options, you can filter the options shown in the
* help output (e.g. to show short help for related options). Provide
* as simple number indexed array of short and/or long values to set a filter.
* The $paramGrouping option can be used to group options in the help
* output. The structure of this array parameter is as follows:
* 'First section' => array(
* 'Second section' => array(
* As can be seen, short option names are possible as well as long ones.
* The key of the first array level is the name of the section, which is
* assigned to an array of options to group under this section. The $params
* parameter still influences if an option is displayed at all.
* @param array(string) $params
* @param array(string=>array(string)) $paramGrouping
* @return array(array(string)) Table structure as explained.
* @apichange In future versions, the default values of $params will change
* to null instead of an empty array. Giving an empty array for
* these will then be taken literally.
public function getHelp( $long =
false, array $params =
array(), array $paramGrouping =
null )
$params =
( $params ===
array() ||
$params ===
null ?
null :
$params );
if ( $paramGrouping ===
null )
$help =
$this->getOptionHelpWithoutGrouping( $long, $params );
$help =
$this->getOptionHelpWithGrouping( $long, $params, $paramGrouping );
if ( $this->argumentDefinition !==
null )
$help[] =
array( "Arguments:", '' );
$argumentsHelp =
$this->helpGenerator->generateArgumentHelp( $long );
if ( $argumentsHelp ===
array() )
$help[] =
array( '', "No arguments available." );
* Creates the option help array in the original, ungrouped way.
* Creates the original help array generated by {@link getHelp()}. The
* $long and $params options are the same as they are for this method.
private function getOptionHelpWithoutGrouping( $long, $params )
return $this->helpGenerator->generateUngroupedOptionHelp(
* Generates options helo array with ordering and grouping.
* @param mixed $paramGrouping
private function getOptionHelpWithGrouping( $long, $params, $paramGrouping )
$rawHelp =
$this->helpGenerator->generateGroupedOptionHelp(
foreach ( $rawHelp as $category =>
$optionsHelp )
$help[] =
array( '', '' );
$help[] =
array( $category, '' );
* Get help information for your options as a table.
* This method provides the information returned by
* {@link ezcConsoleInput::getHelp()} in a table.
* The $paramGrouping option can be used to group options in the help
* output. The structure of this array parameter is as follows:
* 'First section' => array(
* 'Second section' => array(
* As can be seen, short option names are possible as well as long ones.
* The key of the first array level is the name of the section, which is
* assigned to an array of options to group under this section. The $params
* parameter still influences if an option as displayed at all.
* @param ezcConsoleTable $table The table object to fill.
* @param bool $long Set this to true for getting the
* @param array(string) $params Set of option names to generate help
* @param array(string=>array(string)) $paramGrouping
* @return ezcConsoleTable The filled table.
public function getHelpTable( ezcConsoleTable $table, $long =
false, array $params =
array(), $paramGrouping =
null )
$help =
$this->getHelp( $long, $params, $paramGrouping );
foreach ( $help as $row )
$table[$i][0]->content =
$row[0];
$table[$i++
][1]->content =
$row[1];
* Returns a standard help output for your program.
* This method generates a help text as it's commonly known from Unix
* command line programs. The output will contain the synopsis, your
* provided program description and the selected parameter help
* as also provided by {@link ezcConsoleInput::getHelp()}. The returned
* string can directly be printed to the console.
* The $paramGrouping option can be used to group options in the help
* output. The structure of this array parameter is as follows:
* 'First section' => array(
* 'Second section' => array(
* As can be seen, short option names are possible as well as long ones.
* The key of the first array level is the name of the section, which is
* assigned to an array of options to group under this section. The $params
* parameter still influences if an option as displayed at all.
* @param string $programDesc The description of your program.
* @param int $width The width to adjust the output text to.
* @param bool $long Set this to true for getting the long
* @param array(string) $params Set of option names to generate help
* @param array(string=>array(string)) $paramGrouping
* @return string The generated help text.
public function getHelpText( $programDesc, $width =
80, $long =
false, array $params =
null, $paramGrouping =
null )
$help =
$this->getHelp( $long, ( $params ==
null ?
array() :
$params ), $paramGrouping );
// Determine max length of first column text.
foreach ( $help as $row )
$leftColWidth =
$maxLength +
2;
$rightColWidth =
$width -
$leftColWidth;
$res =
'Usage: ' .
$this->getSynopsis( $params ) .
PHP_EOL;
$res .=
$this->stringTool->wordwrap( $programDesc, $width, PHP_EOL );
$res .=
PHP_EOL .
PHP_EOL;
foreach ( $help as $row )
$this->stringTool->wordwrap( $row[1], $rightColWidth )
$res .=
$this->stringTool->strPad( $row[0], $leftColWidth, ' ' );
$res .=
$rowParts[0] .
PHP_EOL;
// @TODO: Fix function call in loop header
for ( $i =
1; $i <
sizeof( $rowParts ); $i++
)
$res .=
str_repeat( ' ', $leftColWidth ) .
$rowParts[$i] .
PHP_EOL;
* Returns the synopsis string for the program.
* This gives you a synopsis definition for the options and arguments
* defined with this instance of ezcConsoleInput. You can filter the
* options named in the synopsis by submitting their short names in an
* array as the parameter of this method. If the parameter $optionNames
* is set, only those options are listed in the synopsis.
* @param array(string) $optionNames
public function getSynopsis( array $optionNames =
null )
return $this->helpGenerator->generateSynopsis( $optionNames );
* Returns if a help option was set.
* This method returns if an option was submitted, which was defined to be
* a help option, using the isHelpOption flag.
* @return bool If a help option was set.
* @throws ezcBasePropertyNotFoundException
* If the the desired property is not found.
* @param string $propertyName Name of the property.
* @return mixed Value of the property or null.
public function __get( $propertyName )
if ( !isset
( $this->$propertyName ) )
* @param string $propertyName
* @param string $propertyValue
public function __set( $propertyName, $propertyValue )
case "argumentDefinition":
$this->properties[$propertyName] =
$propertyValue;
* @param string $propertyName Name of the property.
* @return bool True if the property is set, otherwise false.
public function __isset( $propertyName )
* Returns the synopsis string for a single option and its dependencies.
* This method returns a part of the program synopsis, specifically for a
* certain parameter. The method recursively adds depending parameters up
* to the 2nd depth level to the synopsis. The second parameter is used
* to store the short names of all options that have already been used in
* the synopsis (to avoid adding an option twice). The 3rd parameter
* determines the actual deps in the option dependency recursion to
* terminate that after 2 recursions.
* @param ezcConsoleOption $option The option to include.
* @param array(string) $usedOptions Array of used option short names.
* @param int $depth Current recursion depth.
* @return string The synopsis for this parameter.
* @apichange This method is deprecates. Implement your own {@link }
* ezcConsoleInputHelpGenerator} instead, as soon as the
* interface is made public.
// Break after a nesting level of 2
if ( $depth++ >
2 ||
( in_array( $option->short, $usedOptions['short'] ) &&
in_array( $option->long, $usedOptions['long'] ) ) ) return $synopsis;
$usedOptions['short'][] =
$option->short;
$usedOptions['long'][] =
$option->long;
$synopsis .=
$option->short !==
"" ?
"-{$option->short}" :
"--{$option->long}";
if ( isset
( $option->default ) )
$synopsis .=
" " .
( $option->type ===
ezcConsoleInput::TYPE_STRING ?
'"' :
'' ) .
$option->default .
( $option->type ===
ezcConsoleInput::TYPE_STRING ?
'"' :
'' );
foreach ( $option->getDependencies() as $rule )
if ( $option->arguments ===
false )
// Make the whole thing optional?
if ( $option->mandatory ===
false )
$synopsis =
"[$synopsis]";
* This method does the processing of a single option.
* @param array(string) $args The arguments array.
* @param int $i The current position in the arguments array.
* @throws ezcConsoleOptionTooManyValuesException
* If an option that expects only a single value was submitted
* @throws ezcConsoleOptionTypeViolationException
* If an option was submitted with a value of the wrong type.
* @throws ezcConsoleOptionMissingValueException
* If an option thats expects a value was submitted without.
private function processOption( array $args, &$i )
$option =
$this->getOption( preg_replace( '/^-+/', '', $args[$i++
] ) );
// Is the actual option a help option?
if ( $option->isHelpOption ===
true )
if ( isset
( $args[$i] ) &&
iconv_substr( $args[$i], 0, 1, 'UTF-8' ) !==
'-' &&
sizeof( $args ) >
( $i +
1 ) )
// Multiple occurance possible
if ( $option->multiple ===
true )
// Everything fine, nothing to do
// Value expected, check for it
if ( isset
( $args[$i] ) &&
iconv_substr( $args[$i], 0, 1, 'UTF-8' ) !==
'-' )
if ( $this->isCorrectType( $option->type, $args[$i] ) ===
false )
// Multiple values possible
if ( $option->multiple ===
true )
$option->value[] =
$args[$i];
// Only single value expected, check for multiple
elseif ( isset
( $option->value ) &&
$option->value !==
false )
$option->value =
$args[$i];
// Value found? If not, use default, if available
if ( !isset
( $option->value ) ||
$option->value ===
false ||
( is_array( $option->value ) &&
count( $option->value ) ===
0) )
* Process arguments given to the program.
* @param array(string) $args The arguments array.
* @param int $i Current index in arguments array.
private function processArguments( array $args, &$i )
$numArgs =
count( $args );
if ( $this->argumentDefinition ===
null ||
$this->argumentsAllowed() ===
false )
// Old argument handling, also used of a set option sets disallowing arguments
$this->arguments[] =
$args[$i++
];
foreach ( $this->argumentDefinition as $arg )
// Check if all followinga arguments are optional
if ( $arg->mandatory ===
false )
// Check if the current argument is present and mandatory
if ( $mandatory ===
true )
if ( !isset
( $args[$i] ) )
// Arguments are optional, if no more left: return.
if ( !isset
( $args[$i] ) )
// Optional and no more arguments left, assign default
$arg->value =
$arg->default;
if ( $arg->multiple ===
true )
for ( $i =
$i; $i <
$numArgs; ++
$i )
if ( $this->isCorrectType( $arg->type, $args[$i] ) ===
false )
$arg->value =
array_merge( $arg->value, array( $args[$i] ) );
// Keep old handling, too
$this->arguments[] =
$args[$i];
if ( $this->isCorrectType( $arg->type, $args[$i] ) ===
false )
// Keep old handling, too
$this->arguments[] =
$args[$i];
* Returns if arguments are allowed with the current option submition.
* @return bool If arguments allowed.
foreach ( $this->options as $id =>
$option )
if ( $option->value !==
false &&
$option->arguments ===
false )
* Check the rules that may be associated with an option.
* Options are allowed to have rules associated for dependencies to other
* options and exclusion of other options or arguments. This method
* @throws ezcConsoleException
* in case validation fails.
private function checkRules()
// If a help option is set, skip rule checking
$this->validator->validateOptions(
( $this->arguments !==
array() )
* Checks if a value is of a given type. Converts the value to the
* correct PHP type on success.
* @param int $type The type to check for. One of self::TYPE_*.
* @param string $val The value to check. Will possibly altered!
* @return bool True on succesful check, otherwise false.
private function isCorrectType( $type, &$val )
$res =
preg_match( '/^[0-9]+$/', $val ) ?
true :
false;
* Split parameter and value for long option names.
* This method checks for long options, if the value is passed using =. If
* this is the case parameter and value get split and replaced in the
* @param array(string) $args The arguments array
* @param int $i Current arguments array position
private function preprocessLongOption( array &$args, $i )
if ( preg_match( '/^--\w+\=[^ ]/i', $args[$i] ) )
// Split param and value and replace current param
$parts =
explode( '=', $args[$i], 2 );