2015-08-17 17:00:26 -07:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Symfony\Component\Console\Input ;
2016-04-20 09:56:34 -07:00
use Symfony\Component\Console\Exception\RuntimeException ;
2015-08-17 17:00:26 -07:00
/**
* ArgvInput represents an input coming from the CLI arguments .
*
* Usage :
*
* $input = new ArgvInput ();
*
* By default , the `$_SERVER['argv']` array is used for the input values .
*
* This can be overridden by explicitly passing the input values in the constructor :
*
* $input = new ArgvInput ( $_SERVER [ 'argv' ]);
*
* If you pass it yourself , don ' t forget that the first element of the array
* is the name of the running application .
*
* When passing an argument to the constructor , be sure that it respects
* the same rules as the argv one . It ' s almost always better to use the
* `StringInput` when you want to provide your own input .
*
* @ author Fabien Potencier < fabien @ symfony . com >
*
* @ see http :// www . gnu . org / software / libc / manual / html_node / Argument - Syntax . html
* @ see http :// www . opengroup . org / onlinepubs / 00 9695399 / basedefs / xbd_chap12 . html #tag_12_02
*/
class ArgvInput extends Input
{
private $tokens ;
private $parsed ;
/**
* Constructor .
*
2017-02-02 16:28:38 -08:00
* @ param array | null $argv An array of parameters from the CLI ( in the argv format )
* @ param InputDefinition | null $definition A InputDefinition instance
2015-08-17 17:00:26 -07:00
*/
public function __construct ( array $argv = null , InputDefinition $definition = null )
{
if ( null === $argv ) {
$argv = $_SERVER [ 'argv' ];
}
// strip the application name
array_shift ( $argv );
$this -> tokens = $argv ;
parent :: __construct ( $definition );
}
protected function setTokens ( array $tokens )
{
$this -> tokens = $tokens ;
}
/**
2017-02-02 16:28:38 -08:00
* { @ inheritdoc }
2015-08-17 17:00:26 -07:00
*/
protected function parse ()
{
$parseOptions = true ;
$this -> parsed = $this -> tokens ;
while ( null !== $token = array_shift ( $this -> parsed )) {
if ( $parseOptions && '' == $token ) {
$this -> parseArgument ( $token );
} elseif ( $parseOptions && '--' == $token ) {
$parseOptions = false ;
} elseif ( $parseOptions && 0 === strpos ( $token , '--' )) {
$this -> parseLongOption ( $token );
} elseif ( $parseOptions && '-' === $token [ 0 ] && '-' !== $token ) {
$this -> parseShortOption ( $token );
} else {
$this -> parseArgument ( $token );
}
}
}
/**
* Parses a short option .
*
2017-02-02 16:28:38 -08:00
* @ param string $token The current token
2015-08-17 17:00:26 -07:00
*/
private function parseShortOption ( $token )
{
$name = substr ( $token , 1 );
if ( strlen ( $name ) > 1 ) {
if ( $this -> definition -> hasShortcut ( $name [ 0 ]) && $this -> definition -> getOptionForShortcut ( $name [ 0 ]) -> acceptValue ()) {
// an option with a value (with no space)
$this -> addShortOption ( $name [ 0 ], substr ( $name , 1 ));
} else {
$this -> parseShortOptionSet ( $name );
}
} else {
$this -> addShortOption ( $name , null );
}
}
/**
* Parses a short option set .
*
* @ param string $name The current token
*
2016-04-20 09:56:34 -07:00
* @ throws RuntimeException When option given doesn ' t exist
2015-08-17 17:00:26 -07:00
*/
private function parseShortOptionSet ( $name )
{
$len = strlen ( $name );
for ( $i = 0 ; $i < $len ; ++ $i ) {
if ( ! $this -> definition -> hasShortcut ( $name [ $i ])) {
2016-04-20 09:56:34 -07:00
throw new RuntimeException ( sprintf ( 'The "-%s" option does not exist.' , $name [ $i ]));
2015-08-17 17:00:26 -07:00
}
$option = $this -> definition -> getOptionForShortcut ( $name [ $i ]);
if ( $option -> acceptValue ()) {
$this -> addLongOption ( $option -> getName (), $i === $len - 1 ? null : substr ( $name , $i + 1 ));
break ;
} else {
$this -> addLongOption ( $option -> getName (), null );
}
}
}
/**
* Parses a long option .
*
* @ param string $token The current token
*/
private function parseLongOption ( $token )
{
$name = substr ( $token , 2 );
if ( false !== $pos = strpos ( $name , '=' )) {
2017-02-02 16:28:38 -08:00
if ( 0 === strlen ( $value = substr ( $name , $pos + 1 ))) {
array_unshift ( $this -> parsed , null );
}
$this -> addLongOption ( substr ( $name , 0 , $pos ), $value );
2015-08-17 17:00:26 -07:00
} else {
$this -> addLongOption ( $name , null );
}
}
/**
* Parses an argument .
*
* @ param string $token The current token
*
2016-04-20 09:56:34 -07:00
* @ throws RuntimeException When too many arguments are given
2015-08-17 17:00:26 -07:00
*/
private function parseArgument ( $token )
{
$c = count ( $this -> arguments );
// if input is expecting another argument, add it
if ( $this -> definition -> hasArgument ( $c )) {
$arg = $this -> definition -> getArgument ( $c );
$this -> arguments [ $arg -> getName ()] = $arg -> isArray () ? array ( $token ) : $token ;
// if last argument isArray(), append token to last argument
} elseif ( $this -> definition -> hasArgument ( $c - 1 ) && $this -> definition -> getArgument ( $c - 1 ) -> isArray ()) {
$arg = $this -> definition -> getArgument ( $c - 1 );
$this -> arguments [ $arg -> getName ()][] = $token ;
// unexpected argument
} else {
2017-02-02 16:28:38 -08:00
$all = $this -> definition -> getArguments ();
if ( count ( $all )) {
throw new RuntimeException ( sprintf ( 'Too many arguments, expected arguments "%s".' , implode ( '" "' , array_keys ( $all ))));
}
throw new RuntimeException ( sprintf ( 'No arguments expected, got "%s".' , $token ));
2015-08-17 17:00:26 -07:00
}
}
/**
* Adds a short option value .
*
* @ param string $shortcut The short option key
* @ param mixed $value The value for the option
*
2016-04-20 09:56:34 -07:00
* @ throws RuntimeException When option given doesn ' t exist
2015-08-17 17:00:26 -07:00
*/
private function addShortOption ( $shortcut , $value )
{
if ( ! $this -> definition -> hasShortcut ( $shortcut )) {
2016-04-20 09:56:34 -07:00
throw new RuntimeException ( sprintf ( 'The "-%s" option does not exist.' , $shortcut ));
2015-08-17 17:00:26 -07:00
}
$this -> addLongOption ( $this -> definition -> getOptionForShortcut ( $shortcut ) -> getName (), $value );
}
/**
* Adds a long option value .
*
* @ param string $name The long option key
* @ param mixed $value The value for the option
*
2016-04-20 09:56:34 -07:00
* @ throws RuntimeException When option given doesn ' t exist
2015-08-17 17:00:26 -07:00
*/
private function addLongOption ( $name , $value )
{
if ( ! $this -> definition -> hasOption ( $name )) {
2016-04-20 09:56:34 -07:00
throw new RuntimeException ( sprintf ( 'The "--%s" option does not exist.' , $name ));
2015-08-17 17:00:26 -07:00
}
$option = $this -> definition -> getOption ( $name );
2015-09-04 13:20:09 -07:00
// Convert empty values to null
if ( ! isset ( $value [ 0 ])) {
2015-08-17 17:00:26 -07:00
$value = null ;
}
if ( null !== $value && ! $option -> acceptValue ()) {
2016-04-20 09:56:34 -07:00
throw new RuntimeException ( sprintf ( 'The "--%s" option does not accept a value.' , $name ));
2015-08-17 17:00:26 -07:00
}
if ( null === $value && $option -> acceptValue () && count ( $this -> parsed )) {
// if option accepts an optional or mandatory argument
// let's see if there is one provided
$next = array_shift ( $this -> parsed );
if ( isset ( $next [ 0 ]) && '-' !== $next [ 0 ]) {
$value = $next ;
} elseif ( empty ( $next )) {
2017-02-02 16:28:38 -08:00
$value = null ;
2015-08-17 17:00:26 -07:00
} else {
array_unshift ( $this -> parsed , $next );
}
}
if ( null === $value ) {
if ( $option -> isValueRequired ()) {
2016-04-20 09:56:34 -07:00
throw new RuntimeException ( sprintf ( 'The "--%s" option requires a value.' , $name ));
2015-08-17 17:00:26 -07:00
}
if ( ! $option -> isArray ()) {
$value = $option -> isValueOptional () ? $option -> getDefault () : true ;
}
}
if ( $option -> isArray ()) {
$this -> options [ $name ][] = $value ;
} else {
$this -> options [ $name ] = $value ;
}
}
/**
2017-02-02 16:28:38 -08:00
* { @ inheritdoc }
2015-08-17 17:00:26 -07:00
*/
public function getFirstArgument ()
{
foreach ( $this -> tokens as $token ) {
if ( $token && '-' === $token [ 0 ]) {
continue ;
}
return $token ;
}
}
/**
2017-02-02 16:28:38 -08:00
* { @ inheritdoc }
2015-08-17 17:00:26 -07:00
*/
public function hasParameterOption ( $values )
{
$values = ( array ) $values ;
foreach ( $this -> tokens as $token ) {
foreach ( $values as $value ) {
if ( $token === $value || 0 === strpos ( $token , $value . '=' )) {
return true ;
}
}
}
return false ;
}
/**
2017-02-02 16:28:38 -08:00
* { @ inheritdoc }
2015-08-17 17:00:26 -07:00
*/
public function getParameterOption ( $values , $default = false )
{
$values = ( array ) $values ;
$tokens = $this -> tokens ;
while ( 0 < count ( $tokens )) {
$token = array_shift ( $tokens );
foreach ( $values as $value ) {
if ( $token === $value || 0 === strpos ( $token , $value . '=' )) {
if ( false !== $pos = strpos ( $token , '=' )) {
return substr ( $token , $pos + 1 );
}
return array_shift ( $tokens );
}
}
}
return $default ;
}
/**
* Returns a stringified representation of the args passed to the command .
*
* @ return string
*/
public function __toString ()
{
$self = $this ;
$tokens = array_map ( function ( $token ) use ( $self ) {
if ( preg_match ( '{^(-[^=]+=)(.+)}' , $token , $match )) {
return $match [ 1 ] . $self -> escapeToken ( $match [ 2 ]);
}
if ( $token && $token [ 0 ] !== '-' ) {
return $self -> escapeToken ( $token );
}
return $token ;
}, $this -> tokens );
return implode ( ' ' , $tokens );
}
}