2015-08-18 00:00:26 +00: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 ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Console\Command\Command ;
use Symfony\Component\Console\Command\HelpCommand ;
use Symfony\Component\Console\Command\ListCommand ;
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface ;
use Symfony\Component\Console\Event\ConsoleCommandEvent ;
use Symfony\Component\Console\Event\ConsoleErrorEvent ;
use Symfony\Component\Console\Event\ConsoleExceptionEvent ;
use Symfony\Component\Console\Event\ConsoleTerminateEvent ;
use Symfony\Component\Console\Exception\CommandNotFoundException ;
2016-04-20 16:56:34 +00:00
use Symfony\Component\Console\Exception\ExceptionInterface ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Console\Exception\LogicException ;
2017-04-13 14:53:35 +00:00
use Symfony\Component\Console\Formatter\OutputFormatter ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\Console\Helper\DebugFormatterHelper ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Console\Helper\FormatterHelper ;
2017-07-03 15:47:07 +00:00
use Symfony\Component\Console\Helper\Helper ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Console\Helper\HelperSet ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\Console\Helper\ProcessHelper ;
use Symfony\Component\Console\Helper\QuestionHelper ;
use Symfony\Component\Console\Input\ArgvInput ;
use Symfony\Component\Console\Input\ArrayInput ;
use Symfony\Component\Console\Input\InputArgument ;
use Symfony\Component\Console\Input\InputAwareInterface ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Console\Input\InputDefinition ;
use Symfony\Component\Console\Input\InputInterface ;
use Symfony\Component\Console\Input\InputOption ;
use Symfony\Component\Console\Input\StreamableInputInterface ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\Console\Output\ConsoleOutput ;
use Symfony\Component\Console\Output\ConsoleOutputInterface ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Console\Output\OutputInterface ;
use Symfony\Component\Debug\ErrorHandler ;
2017-02-03 00:28:38 +00:00
use Symfony\Component\Debug\Exception\FatalThrowableError ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\EventDispatcher\EventDispatcherInterface ;
/**
* An Application is the container for a collection of commands .
*
* It is the main entry point of a Console application .
*
* This class is optimized for a standard CLI environment .
*
* Usage :
*
* $app = new Application ( 'myapp' , '1.0 (stable)' );
* $app -> add ( new SimpleCommand ());
* $app -> run ();
*
* @ author Fabien Potencier < fabien @ symfony . com >
*/
class Application
{
private $commands = array ();
private $wantHelps = false ;
private $runningCommand ;
private $name ;
private $version ;
2018-11-23 12:29:20 +00:00
private $commandLoader ;
2015-08-18 00:00:26 +00:00
private $catchExceptions = true ;
private $autoExit = true ;
private $definition ;
private $helperSet ;
private $dispatcher ;
2018-11-23 12:29:20 +00:00
private $terminal ;
2015-08-18 00:00:26 +00:00
private $defaultCommand ;
2018-11-23 12:29:20 +00:00
private $singleCommand ;
private $initialized ;
2015-08-18 00:00:26 +00:00
/**
* @ param string $name The name of the application
* @ param string $version The version of the application
*/
public function __construct ( $name = 'UNKNOWN' , $version = 'UNKNOWN' )
{
$this -> name = $name ;
$this -> version = $version ;
2018-11-23 12:29:20 +00:00
$this -> terminal = new Terminal ();
2015-08-18 00:00:26 +00:00
$this -> defaultCommand = 'list' ;
}
public function setDispatcher ( EventDispatcherInterface $dispatcher )
{
$this -> dispatcher = $dispatcher ;
}
2018-11-23 12:29:20 +00:00
public function setCommandLoader ( CommandLoaderInterface $commandLoader )
{
$this -> commandLoader = $commandLoader ;
}
2015-08-18 00:00:26 +00:00
/**
* Runs the current application .
*
* @ return int 0 if everything went fine , or an error code
2017-07-03 15:47:07 +00:00
*
* @ throws \Exception When running fails . Bypass this when { @ link setCatchExceptions ()} .
2015-08-18 00:00:26 +00:00
*/
public function run ( InputInterface $input = null , OutputInterface $output = null )
{
2018-11-23 12:29:20 +00:00
putenv ( 'LINES=' . $this -> terminal -> getHeight ());
putenv ( 'COLUMNS=' . $this -> terminal -> getWidth ());
2015-08-18 00:00:26 +00:00
if ( null === $input ) {
$input = new ArgvInput ();
}
if ( null === $output ) {
$output = new ConsoleOutput ();
}
2018-11-23 12:29:20 +00:00
$renderException = function ( $e ) use ( $output ) {
if ( ! $e instanceof \Exception ) {
$e = class_exists ( FatalThrowableError :: class ) ? new FatalThrowableError ( $e ) : new \ErrorException ( $e -> getMessage (), $e -> getCode (), E_ERROR , $e -> getFile (), $e -> getLine ());
2015-08-18 00:00:26 +00:00
}
if ( $output instanceof ConsoleOutputInterface ) {
$this -> renderException ( $e , $output -> getErrorOutput ());
} else {
$this -> renderException ( $e , $output );
}
2018-11-23 12:29:20 +00:00
};
if ( $phpHandler = set_exception_handler ( $renderException )) {
restore_exception_handler ();
if ( ! \is_array ( $phpHandler ) || ! $phpHandler [ 0 ] instanceof ErrorHandler ) {
$debugHandler = true ;
} elseif ( $debugHandler = $phpHandler [ 0 ] -> setExceptionHandler ( $renderException )) {
$phpHandler [ 0 ] -> setExceptionHandler ( $debugHandler );
}
}
if ( null !== $this -> dispatcher && $this -> dispatcher -> hasListeners ( ConsoleEvents :: EXCEPTION )) {
@ trigger_error ( sprintf ( 'The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.' ), E_USER_DEPRECATED );
}
$this -> configureIO ( $input , $output );
try {
$exitCode = $this -> doRun ( $input , $output );
} catch ( \Exception $e ) {
if ( ! $this -> catchExceptions ) {
throw $e ;
}
$renderException ( $e );
2015-08-18 00:00:26 +00:00
$exitCode = $e -> getCode ();
if ( is_numeric ( $exitCode )) {
$exitCode = ( int ) $exitCode ;
if ( 0 === $exitCode ) {
$exitCode = 1 ;
}
} else {
$exitCode = 1 ;
}
2018-11-23 12:29:20 +00:00
} finally {
// if the exception handler changed, keep it
// otherwise, unregister $renderException
if ( ! $phpHandler ) {
if ( set_exception_handler ( $renderException ) === $renderException ) {
restore_exception_handler ();
}
restore_exception_handler ();
} elseif ( ! $debugHandler ) {
$finalHandler = $phpHandler [ 0 ] -> setExceptionHandler ( null );
if ( $finalHandler !== $renderException ) {
$phpHandler [ 0 ] -> setExceptionHandler ( $finalHandler );
}
}
2015-08-18 00:00:26 +00:00
}
if ( $this -> autoExit ) {
if ( $exitCode > 255 ) {
$exitCode = 255 ;
}
exit ( $exitCode );
}
return $exitCode ;
}
/**
* Runs the current application .
*
* @ return int 0 if everything went fine , or an error code
*/
public function doRun ( InputInterface $input , OutputInterface $output )
{
2018-11-23 12:29:20 +00:00
if ( true === $input -> hasParameterOption ( array ( '--version' , '-V' ), true )) {
2015-08-18 00:00:26 +00:00
$output -> writeln ( $this -> getLongVersion ());
return 0 ;
}
$name = $this -> getCommandName ( $input );
2018-11-23 12:29:20 +00:00
if ( true === $input -> hasParameterOption ( array ( '--help' , '-h' ), true )) {
2015-08-18 00:00:26 +00:00
if ( ! $name ) {
$name = 'help' ;
2018-11-23 12:29:20 +00:00
$input = new ArrayInput ( array ( 'command_name' => $this -> defaultCommand ));
2015-08-18 00:00:26 +00:00
} else {
$this -> wantHelps = true ;
}
}
if ( ! $name ) {
$name = $this -> defaultCommand ;
2018-11-23 12:29:20 +00:00
$definition = $this -> getDefinition ();
$definition -> setArguments ( array_merge (
$definition -> getArguments (),
array (
'command' => new InputArgument ( 'command' , InputArgument :: OPTIONAL , $definition -> getArgument ( 'command' ) -> getDescription (), $name ),
)
));
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
try {
$e = $this -> runningCommand = null ;
// the command name MUST be the first element of the input
$command = $this -> find ( $name );
} catch ( \Exception $e ) {
} catch ( \Throwable $e ) {
}
if ( null !== $e ) {
if ( null !== $this -> dispatcher ) {
$event = new ConsoleErrorEvent ( $input , $output , $e );
$this -> dispatcher -> dispatch ( ConsoleEvents :: ERROR , $event );
$e = $event -> getError ();
if ( 0 === $event -> getExitCode ()) {
return 0 ;
}
}
throw $e ;
}
2015-08-18 00:00:26 +00:00
$this -> runningCommand = $command ;
$exitCode = $this -> doRunCommand ( $command , $input , $output );
$this -> runningCommand = null ;
return $exitCode ;
}
public function setHelperSet ( HelperSet $helperSet )
{
$this -> helperSet = $helperSet ;
}
/**
* Get the helper set associated with the command .
*
* @ return HelperSet The HelperSet instance associated with this command
*/
public function getHelperSet ()
{
2018-11-23 12:29:20 +00:00
if ( ! $this -> helperSet ) {
$this -> helperSet = $this -> getDefaultHelperSet ();
}
2015-08-18 00:00:26 +00:00
return $this -> helperSet ;
}
public function setDefinition ( InputDefinition $definition )
{
$this -> definition = $definition ;
}
/**
* Gets the InputDefinition related to this Application .
*
* @ return InputDefinition The InputDefinition instance
*/
public function getDefinition ()
{
2018-11-23 12:29:20 +00:00
if ( ! $this -> definition ) {
$this -> definition = $this -> getDefaultInputDefinition ();
}
if ( $this -> singleCommand ) {
$inputDefinition = $this -> definition ;
$inputDefinition -> setArguments ();
return $inputDefinition ;
}
2015-08-18 00:00:26 +00:00
return $this -> definition ;
}
/**
* Gets the help message .
*
2017-02-03 00:28:38 +00:00
* @ return string A help message
2015-08-18 00:00:26 +00:00
*/
public function getHelp ()
{
return $this -> getLongVersion ();
}
2018-11-23 12:29:20 +00:00
/**
* Gets whether to catch exceptions or not during commands execution .
*
* @ return bool Whether to catch exceptions or not during commands execution
*/
public function areExceptionsCaught ()
{
return $this -> catchExceptions ;
}
2015-08-18 00:00:26 +00:00
/**
* Sets whether to catch exceptions or not during commands execution .
*
* @ param bool $boolean Whether to catch exceptions or not during commands execution
*/
public function setCatchExceptions ( $boolean )
{
$this -> catchExceptions = ( bool ) $boolean ;
}
2018-11-23 12:29:20 +00:00
/**
* Gets whether to automatically exit after a command execution or not .
*
* @ return bool Whether to automatically exit after a command execution or not
*/
public function isAutoExitEnabled ()
{
return $this -> autoExit ;
}
2015-08-18 00:00:26 +00:00
/**
* Sets whether to automatically exit after a command execution or not .
*
* @ param bool $boolean Whether to automatically exit after a command execution or not
*/
public function setAutoExit ( $boolean )
{
$this -> autoExit = ( bool ) $boolean ;
}
/**
* Gets the name of the application .
*
* @ return string The application name
*/
public function getName ()
{
return $this -> name ;
}
/**
* Sets the application name .
*
* @ param string $name The application name
*/
public function setName ( $name )
{
$this -> name = $name ;
}
/**
* Gets the application version .
*
* @ return string The application version
*/
public function getVersion ()
{
return $this -> version ;
}
/**
* Sets the application version .
*
* @ param string $version The application version
*/
public function setVersion ( $version )
{
$this -> version = $version ;
}
/**
* Returns the long version of the application .
*
* @ return string The long application version
*/
public function getLongVersion ()
{
2016-04-20 16:56:34 +00:00
if ( 'UNKNOWN' !== $this -> getName ()) {
if ( 'UNKNOWN' !== $this -> getVersion ()) {
2018-11-23 12:29:20 +00:00
return sprintf ( '%s <info>%s</info>' , $this -> getName (), $this -> getVersion ());
2016-04-20 16:56:34 +00:00
}
2018-11-23 12:29:20 +00:00
return $this -> getName ();
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
return 'Console Tool' ;
2015-08-18 00:00:26 +00:00
}
/**
* Registers a new command .
*
* @ param string $name The command name
*
* @ return Command The newly created command
*/
public function register ( $name )
{
return $this -> add ( new Command ( $name ));
}
/**
* Adds an array of command objects .
*
2017-02-03 00:28:38 +00:00
* If a Command is not enabled it will not be added .
*
2015-08-18 00:00:26 +00:00
* @ param Command [] $commands An array of commands
*/
public function addCommands ( array $commands )
{
foreach ( $commands as $command ) {
$this -> add ( $command );
}
}
/**
* Adds a command object .
*
* If a command with the same name already exists , it will be overridden .
2017-02-03 00:28:38 +00:00
* If the command is not enabled it will not be added .
2015-08-18 00:00:26 +00:00
*
2017-02-03 00:28:38 +00:00
* @ return Command | null The registered command if enabled or null
2015-08-18 00:00:26 +00:00
*/
public function add ( Command $command )
{
2018-11-23 12:29:20 +00:00
$this -> init ();
2015-08-18 00:00:26 +00:00
$command -> setApplication ( $this );
if ( ! $command -> isEnabled ()) {
$command -> setApplication ( null );
return ;
}
if ( null === $command -> getDefinition ()) {
2018-11-23 12:29:20 +00:00
throw new LogicException ( sprintf ( 'Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.' , \get_class ( $command )));
}
if ( ! $command -> getName ()) {
throw new LogicException ( sprintf ( 'The command defined in "%s" cannot have an empty name.' , \get_class ( $command )));
2015-08-18 00:00:26 +00:00
}
$this -> commands [ $command -> getName ()] = $command ;
foreach ( $command -> getAliases () as $alias ) {
$this -> commands [ $alias ] = $command ;
}
return $command ;
}
/**
* Returns a registered command by name or alias .
*
* @ param string $name The command name or alias
*
* @ return Command A Command object
*
2017-02-03 00:28:38 +00:00
* @ throws CommandNotFoundException When given command name does not exist
2015-08-18 00:00:26 +00:00
*/
public function get ( $name )
{
2018-11-23 12:29:20 +00:00
$this -> init ();
if ( ! $this -> has ( $name )) {
2016-04-20 16:56:34 +00:00
throw new CommandNotFoundException ( sprintf ( 'The command "%s" does not exist.' , $name ));
2015-08-18 00:00:26 +00:00
}
$command = $this -> commands [ $name ];
if ( $this -> wantHelps ) {
$this -> wantHelps = false ;
$helpCommand = $this -> get ( 'help' );
$helpCommand -> setCommand ( $command );
return $helpCommand ;
}
return $command ;
}
/**
* Returns true if the command exists , false otherwise .
*
* @ param string $name The command name or alias
*
* @ return bool true if the command exists , false otherwise
*/
public function has ( $name )
{
2018-11-23 12:29:20 +00:00
$this -> init ();
return isset ( $this -> commands [ $name ]) || ( $this -> commandLoader && $this -> commandLoader -> has ( $name ) && $this -> add ( $this -> commandLoader -> get ( $name )));
2015-08-18 00:00:26 +00:00
}
/**
* Returns an array of all unique namespaces used by currently registered commands .
*
2017-02-03 00:28:38 +00:00
* It does not return the global namespace which always exists .
2015-08-18 00:00:26 +00:00
*
2017-02-03 00:28:38 +00:00
* @ return string [] An array of namespaces
2015-08-18 00:00:26 +00:00
*/
public function getNamespaces ()
{
$namespaces = array ();
2016-04-20 16:56:34 +00:00
foreach ( $this -> all () as $command ) {
2015-08-18 00:00:26 +00:00
$namespaces = array_merge ( $namespaces , $this -> extractAllNamespaces ( $command -> getName ()));
foreach ( $command -> getAliases () as $alias ) {
$namespaces = array_merge ( $namespaces , $this -> extractAllNamespaces ( $alias ));
}
}
return array_values ( array_unique ( array_filter ( $namespaces )));
}
/**
* Finds a registered namespace by a name or an abbreviation .
*
* @ param string $namespace A namespace or abbreviation to search for
*
* @ return string A registered namespace
*
2016-04-20 16:56:34 +00:00
* @ throws CommandNotFoundException When namespace is incorrect or ambiguous
2015-08-18 00:00:26 +00:00
*/
public function findNamespace ( $namespace )
{
$allNamespaces = $this -> getNamespaces ();
$expr = preg_replace_callback ( '{([^:]+|)}' , function ( $matches ) { return preg_quote ( $matches [ 1 ]) . '[^:]*' ; }, $namespace );
$namespaces = preg_grep ( '{^' . $expr . '}' , $allNamespaces );
if ( empty ( $namespaces )) {
$message = sprintf ( 'There are no commands defined in the "%s" namespace.' , $namespace );
2015-08-27 19:03:05 +00:00
if ( $alternatives = $this -> findAlternatives ( $namespace , $allNamespaces )) {
2018-11-23 12:29:20 +00:00
if ( 1 == \count ( $alternatives )) {
2015-08-18 00:00:26 +00:00
$message .= " \n \n Did you mean this? \n " ;
} else {
$message .= " \n \n Did you mean one of these? \n " ;
}
$message .= implode ( " \n " , $alternatives );
}
2016-04-20 16:56:34 +00:00
throw new CommandNotFoundException ( $message , $alternatives );
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
$exact = \in_array ( $namespace , $namespaces , true );
if ( \count ( $namespaces ) > 1 && ! $exact ) {
throw new CommandNotFoundException ( sprintf ( " The namespace \" %s \" is ambiguous. \n Did you mean one of these? \n %s " , $namespace , $this -> getAbbreviationSuggestions ( array_values ( $namespaces ))), array_values ( $namespaces ));
2015-08-18 00:00:26 +00:00
}
return $exact ? $namespace : reset ( $namespaces );
}
/**
* Finds a command by name or alias .
*
* Contrary to get , this command tries to find the best
* match if you give it an abbreviation of a name or alias .
*
* @ param string $name A command name or a command alias
*
* @ return Command A Command instance
*
2016-04-20 16:56:34 +00:00
* @ throws CommandNotFoundException When command name is incorrect or ambiguous
2015-08-18 00:00:26 +00:00
*/
public function find ( $name )
{
2018-11-23 12:29:20 +00:00
$this -> init ();
$aliases = array ();
$allCommands = $this -> commandLoader ? array_merge ( $this -> commandLoader -> getNames (), array_keys ( $this -> commands )) : array_keys ( $this -> commands );
2015-08-18 00:00:26 +00:00
$expr = preg_replace_callback ( '{([^:]+|)}' , function ( $matches ) { return preg_quote ( $matches [ 1 ]) . '[^:]*' ; }, $name );
$commands = preg_grep ( '{^' . $expr . '}' , $allCommands );
2018-11-23 12:29:20 +00:00
if ( empty ( $commands )) {
$commands = preg_grep ( '{^' . $expr . '}i' , $allCommands );
}
// if no commands matched or we just matched namespaces
if ( empty ( $commands ) || \count ( preg_grep ( '{^' . $expr . '$}i' , $commands )) < 1 ) {
2015-08-18 00:00:26 +00:00
if ( false !== $pos = strrpos ( $name , ':' )) {
// check if a namespace exists and contains commands
$this -> findNamespace ( substr ( $name , 0 , $pos ));
}
$message = sprintf ( 'Command "%s" is not defined.' , $name );
2015-08-27 19:03:05 +00:00
if ( $alternatives = $this -> findAlternatives ( $name , $allCommands )) {
2018-11-23 12:29:20 +00:00
if ( 1 == \count ( $alternatives )) {
2015-08-18 00:00:26 +00:00
$message .= " \n \n Did you mean this? \n " ;
} else {
$message .= " \n \n Did you mean one of these? \n " ;
}
$message .= implode ( " \n " , $alternatives );
}
2016-04-20 16:56:34 +00:00
throw new CommandNotFoundException ( $message , $alternatives );
2015-08-18 00:00:26 +00:00
}
// filter out aliases for commands which are already on the list
2018-11-23 12:29:20 +00:00
if ( \count ( $commands ) > 1 ) {
$commandList = $this -> commandLoader ? array_merge ( array_flip ( $this -> commandLoader -> getNames ()), $this -> commands ) : $this -> commands ;
$commands = array_unique ( array_filter ( $commands , function ( $nameOrAlias ) use ( $commandList , $commands , & $aliases ) {
$commandName = $commandList [ $nameOrAlias ] instanceof Command ? $commandList [ $nameOrAlias ] -> getName () : $nameOrAlias ;
$aliases [ $nameOrAlias ] = $commandName ;
return $commandName === $nameOrAlias || ! \in_array ( $commandName , $commands );
}));
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
$exact = \in_array ( $name , $commands , true ) || isset ( $aliases [ $name ]);
if ( \count ( $commands ) > 1 && ! $exact ) {
$usableWidth = $this -> terminal -> getWidth () - 10 ;
$abbrevs = array_values ( $commands );
$maxLen = 0 ;
foreach ( $abbrevs as $abbrev ) {
$maxLen = max ( Helper :: strlen ( $abbrev ), $maxLen );
}
$abbrevs = array_map ( function ( $cmd ) use ( $commandList , $usableWidth , $maxLen ) {
if ( ! $commandList [ $cmd ] instanceof Command ) {
return $cmd ;
}
$abbrev = str_pad ( $cmd , $maxLen , ' ' ) . ' ' . $commandList [ $cmd ] -> getDescription ();
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
return Helper :: strlen ( $abbrev ) > $usableWidth ? Helper :: substr ( $abbrev , 0 , $usableWidth - 3 ) . '...' : $abbrev ;
}, array_values ( $commands ));
$suggestions = $this -> getAbbreviationSuggestions ( $abbrevs );
throw new CommandNotFoundException ( sprintf ( " Command \" %s \" is ambiguous. \n Did you mean one of these? \n %s " , $name , $suggestions ), array_values ( $commands ));
2015-08-18 00:00:26 +00:00
}
return $this -> get ( $exact ? $name : reset ( $commands ));
}
/**
* Gets the commands ( registered in the given namespace if provided ) .
*
* The array keys are the full names and the values the command instances .
*
* @ param string $namespace A namespace name
*
* @ return Command [] An array of Command instances
*/
public function all ( $namespace = null )
{
2018-11-23 12:29:20 +00:00
$this -> init ();
2015-08-18 00:00:26 +00:00
if ( null === $namespace ) {
2018-11-23 12:29:20 +00:00
if ( ! $this -> commandLoader ) {
return $this -> commands ;
}
$commands = $this -> commands ;
foreach ( $this -> commandLoader -> getNames () as $name ) {
if ( ! isset ( $commands [ $name ]) && $this -> has ( $name )) {
$commands [ $name ] = $this -> get ( $name );
}
}
return $commands ;
2015-08-18 00:00:26 +00:00
}
$commands = array ();
foreach ( $this -> commands as $name => $command ) {
if ( $namespace === $this -> extractNamespace ( $name , substr_count ( $namespace , ':' ) + 1 )) {
$commands [ $name ] = $command ;
}
}
2018-11-23 12:29:20 +00:00
if ( $this -> commandLoader ) {
foreach ( $this -> commandLoader -> getNames () as $name ) {
if ( ! isset ( $commands [ $name ]) && $namespace === $this -> extractNamespace ( $name , substr_count ( $namespace , ':' ) + 1 ) && $this -> has ( $name )) {
$commands [ $name ] = $this -> get ( $name );
}
}
}
2015-08-18 00:00:26 +00:00
return $commands ;
}
/**
* Returns an array of possible abbreviations given a set of names .
*
* @ param array $names An array of names
*
* @ return array An array of abbreviations
*/
public static function getAbbreviations ( $names )
{
$abbrevs = array ();
foreach ( $names as $name ) {
2018-11-23 12:29:20 +00:00
for ( $len = \strlen ( $name ); $len > 0 ; -- $len ) {
2015-08-18 00:00:26 +00:00
$abbrev = substr ( $name , 0 , $len );
$abbrevs [ $abbrev ][] = $name ;
}
}
return $abbrevs ;
}
/**
2018-11-23 12:29:20 +00:00
* Renders a caught exception .
2015-08-18 00:00:26 +00:00
*/
2018-11-23 12:29:20 +00:00
public function renderException ( \Exception $e , OutputInterface $output )
2015-08-18 00:00:26 +00:00
{
2018-11-23 12:29:20 +00:00
$output -> writeln ( '' , OutputInterface :: VERBOSITY_QUIET );
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
$this -> doRenderException ( $e , $output );
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
if ( null !== $this -> runningCommand ) {
$output -> writeln ( sprintf ( '<info>%s</info>' , sprintf ( $this -> runningCommand -> getSynopsis (), $this -> getName ())), OutputInterface :: VERBOSITY_QUIET );
$output -> writeln ( '' , OutputInterface :: VERBOSITY_QUIET );
2015-08-18 00:00:26 +00:00
}
}
2018-11-23 12:29:20 +00:00
protected function doRenderException ( \Exception $e , OutputInterface $output )
2015-08-18 00:00:26 +00:00
{
do {
2018-11-23 12:29:20 +00:00
$message = trim ( $e -> getMessage ());
if ( '' === $message || OutputInterface :: VERBOSITY_VERBOSE <= $output -> getVerbosity ()) {
$title = sprintf ( ' [%s%s] ' , \get_class ( $e ), 0 !== ( $code = $e -> getCode ()) ? ' (' . $code . ')' : '' );
$len = Helper :: strlen ( $title );
} else {
$len = 0 ;
}
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
$width = $this -> terminal -> getWidth () ? $this -> terminal -> getWidth () - 1 : PHP_INT_MAX ;
2015-08-18 00:00:26 +00:00
// HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
2018-11-23 12:29:20 +00:00
if ( \defined ( 'HHVM_VERSION' ) && $width > 1 << 31 ) {
2015-08-18 00:00:26 +00:00
$width = 1 << 31 ;
}
$lines = array ();
2018-11-23 12:29:20 +00:00
foreach ( '' !== $message ? preg_split ( '/\r?\n/' , $message ) : array () as $line ) {
2015-08-18 00:00:26 +00:00
foreach ( $this -> splitStringByWidth ( $line , $width - 4 ) as $line ) {
// pre-format lines to get the right string length
2017-07-03 15:47:07 +00:00
$lineLength = Helper :: strlen ( $line ) + 4 ;
2015-08-18 00:00:26 +00:00
$lines [] = array ( $line , $lineLength );
$len = max ( $lineLength , $len );
}
}
2016-04-20 16:56:34 +00:00
$messages = array ();
2018-11-23 12:29:20 +00:00
if ( ! $e instanceof ExceptionInterface || OutputInterface :: VERBOSITY_VERBOSE <= $output -> getVerbosity ()) {
$messages [] = sprintf ( '<comment>%s</comment>' , OutputFormatter :: escape ( sprintf ( 'In %s line %s:' , basename ( $e -> getFile ()) ? : 'n/a' , $e -> getLine () ? : 'n/a' )));
}
2017-04-13 14:53:35 +00:00
$messages [] = $emptyLine = sprintf ( '<error>%s</error>' , str_repeat ( ' ' , $len ));
2018-11-23 12:29:20 +00:00
if ( '' === $message || OutputInterface :: VERBOSITY_VERBOSE <= $output -> getVerbosity ()) {
$messages [] = sprintf ( '<error>%s%s</error>' , $title , str_repeat ( ' ' , max ( 0 , $len - Helper :: strlen ( $title ))));
}
2015-08-18 00:00:26 +00:00
foreach ( $lines as $line ) {
2017-04-13 14:53:35 +00:00
$messages [] = sprintf ( '<error> %s %s</error>' , OutputFormatter :: escape ( $line [ 0 ]), str_repeat ( ' ' , $len - $line [ 1 ]));
2015-08-18 00:00:26 +00:00
}
$messages [] = $emptyLine ;
$messages [] = '' ;
2017-04-13 14:53:35 +00:00
$output -> writeln ( $messages , OutputInterface :: VERBOSITY_QUIET );
2015-08-18 00:00:26 +00:00
if ( OutputInterface :: VERBOSITY_VERBOSE <= $output -> getVerbosity ()) {
2016-04-20 16:56:34 +00:00
$output -> writeln ( '<comment>Exception trace:</comment>' , OutputInterface :: VERBOSITY_QUIET );
2015-08-18 00:00:26 +00:00
// exception related properties
$trace = $e -> getTrace ();
2018-11-23 12:29:20 +00:00
for ( $i = 0 , $count = \count ( $trace ); $i < $count ; ++ $i ) {
2015-08-18 00:00:26 +00:00
$class = isset ( $trace [ $i ][ 'class' ]) ? $trace [ $i ][ 'class' ] : '' ;
$type = isset ( $trace [ $i ][ 'type' ]) ? $trace [ $i ][ 'type' ] : '' ;
$function = $trace [ $i ][ 'function' ];
$file = isset ( $trace [ $i ][ 'file' ]) ? $trace [ $i ][ 'file' ] : 'n/a' ;
$line = isset ( $trace [ $i ][ 'line' ]) ? $trace [ $i ][ 'line' ] : 'n/a' ;
2016-04-20 16:56:34 +00:00
$output -> writeln ( sprintf ( ' %s%s%s() at <info>%s:%s</info>' , $class , $type , $function , $file , $line ), OutputInterface :: VERBOSITY_QUIET );
2015-08-18 00:00:26 +00:00
}
2016-04-20 16:56:34 +00:00
$output -> writeln ( '' , OutputInterface :: VERBOSITY_QUIET );
2015-08-18 00:00:26 +00:00
}
} while ( $e = $e -> getPrevious ());
}
/**
* Tries to figure out the terminal width in which this application runs .
*
* @ return int | null
2018-11-23 12:29:20 +00:00
*
* @ deprecated since version 3.2 , to be removed in 4.0 . Create a Terminal instance instead .
2015-08-18 00:00:26 +00:00
*/
protected function getTerminalWidth ()
{
2018-11-23 12:29:20 +00:00
@ trigger_error ( sprintf ( 'The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.' , __METHOD__ ), E_USER_DEPRECATED );
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
return $this -> terminal -> getWidth ();
2015-08-18 00:00:26 +00:00
}
/**
* Tries to figure out the terminal height in which this application runs .
*
* @ return int | null
2018-11-23 12:29:20 +00:00
*
* @ deprecated since version 3.2 , to be removed in 4.0 . Create a Terminal instance instead .
2015-08-18 00:00:26 +00:00
*/
protected function getTerminalHeight ()
{
2018-11-23 12:29:20 +00:00
@ trigger_error ( sprintf ( 'The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.' , __METHOD__ ), E_USER_DEPRECATED );
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
return $this -> terminal -> getHeight ();
2015-08-18 00:00:26 +00:00
}
/**
* Tries to figure out the terminal dimensions based on the current environment .
*
* @ return array Array containing width and height
2018-11-23 12:29:20 +00:00
*
* @ deprecated since version 3.2 , to be removed in 4.0 . Create a Terminal instance instead .
2015-08-18 00:00:26 +00:00
*/
public function getTerminalDimensions ()
{
2018-11-23 12:29:20 +00:00
@ trigger_error ( sprintf ( 'The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.' , __METHOD__ ), E_USER_DEPRECATED );
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
return array ( $this -> terminal -> getWidth (), $this -> terminal -> getHeight ());
2015-08-18 00:00:26 +00:00
}
/**
* Sets terminal dimensions .
*
* Can be useful to force terminal dimensions for functional tests .
*
* @ param int $width The width
* @ param int $height The height
*
2017-02-03 00:28:38 +00:00
* @ return $this
2018-11-23 12:29:20 +00:00
*
* @ deprecated since version 3.2 , to be removed in 4.0 . Set the COLUMNS and LINES env vars instead .
2015-08-18 00:00:26 +00:00
*/
public function setTerminalDimensions ( $width , $height )
{
2018-11-23 12:29:20 +00:00
@ trigger_error ( sprintf ( 'The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.' , __METHOD__ ), E_USER_DEPRECATED );
putenv ( 'COLUMNS=' . $width );
putenv ( 'LINES=' . $height );
2015-08-18 00:00:26 +00:00
return $this ;
}
/**
* Configures the input and output instances based on the user arguments and options .
*/
protected function configureIO ( InputInterface $input , OutputInterface $output )
{
2018-11-23 12:29:20 +00:00
if ( true === $input -> hasParameterOption ( array ( '--ansi' ), true )) {
2015-08-18 00:00:26 +00:00
$output -> setDecorated ( true );
2018-11-23 12:29:20 +00:00
} elseif ( true === $input -> hasParameterOption ( array ( '--no-ansi' ), true )) {
2015-08-18 00:00:26 +00:00
$output -> setDecorated ( false );
}
2018-11-23 12:29:20 +00:00
if ( true === $input -> hasParameterOption ( array ( '--no-interaction' , '-n' ), true )) {
2015-08-18 00:00:26 +00:00
$input -> setInteractive ( false );
2018-11-23 12:29:20 +00:00
} elseif ( \function_exists ( 'posix_isatty' )) {
$inputStream = null ;
if ( $input instanceof StreamableInputInterface ) {
$inputStream = $input -> getStream ();
}
// This check ensures that calling QuestionHelper::setInputStream() works
// To be removed in 4.0 (in the same time as QuestionHelper::setInputStream)
if ( ! $inputStream && $this -> getHelperSet () -> has ( 'question' )) {
$inputStream = $this -> getHelperSet () -> get ( 'question' ) -> getInputStream ( false );
}
2015-08-18 00:00:26 +00:00
if ( !@ posix_isatty ( $inputStream ) && false === getenv ( 'SHELL_INTERACTIVE' )) {
$input -> setInteractive ( false );
}
}
2018-11-23 12:29:20 +00:00
switch ( $shellVerbosity = ( int ) getenv ( 'SHELL_VERBOSITY' )) {
case - 1 : $output -> setVerbosity ( OutputInterface :: VERBOSITY_QUIET ); break ;
case 1 : $output -> setVerbosity ( OutputInterface :: VERBOSITY_VERBOSE ); break ;
case 2 : $output -> setVerbosity ( OutputInterface :: VERBOSITY_VERY_VERBOSE ); break ;
case 3 : $output -> setVerbosity ( OutputInterface :: VERBOSITY_DEBUG ); break ;
default : $shellVerbosity = 0 ; break ;
}
if ( true === $input -> hasParameterOption ( array ( '--quiet' , '-q' ), true )) {
2015-08-18 00:00:26 +00:00
$output -> setVerbosity ( OutputInterface :: VERBOSITY_QUIET );
2018-11-23 12:29:20 +00:00
$shellVerbosity = - 1 ;
2015-08-18 00:00:26 +00:00
} else {
2018-11-23 12:29:20 +00:00
if ( $input -> hasParameterOption ( '-vvv' , true ) || $input -> hasParameterOption ( '--verbose=3' , true ) || 3 === $input -> getParameterOption ( '--verbose' , false , true )) {
2015-08-18 00:00:26 +00:00
$output -> setVerbosity ( OutputInterface :: VERBOSITY_DEBUG );
2018-11-23 12:29:20 +00:00
$shellVerbosity = 3 ;
} elseif ( $input -> hasParameterOption ( '-vv' , true ) || $input -> hasParameterOption ( '--verbose=2' , true ) || 2 === $input -> getParameterOption ( '--verbose' , false , true )) {
2015-08-18 00:00:26 +00:00
$output -> setVerbosity ( OutputInterface :: VERBOSITY_VERY_VERBOSE );
2018-11-23 12:29:20 +00:00
$shellVerbosity = 2 ;
} elseif ( $input -> hasParameterOption ( '-v' , true ) || $input -> hasParameterOption ( '--verbose=1' , true ) || $input -> hasParameterOption ( '--verbose' , true ) || $input -> getParameterOption ( '--verbose' , false , true )) {
2015-08-18 00:00:26 +00:00
$output -> setVerbosity ( OutputInterface :: VERBOSITY_VERBOSE );
2018-11-23 12:29:20 +00:00
$shellVerbosity = 1 ;
2015-08-18 00:00:26 +00:00
}
}
2018-11-23 12:29:20 +00:00
if ( - 1 === $shellVerbosity ) {
$input -> setInteractive ( false );
}
putenv ( 'SHELL_VERBOSITY=' . $shellVerbosity );
$_ENV [ 'SHELL_VERBOSITY' ] = $shellVerbosity ;
$_SERVER [ 'SHELL_VERBOSITY' ] = $shellVerbosity ;
2015-08-18 00:00:26 +00:00
}
/**
* Runs the current command .
*
* If an event dispatcher has been attached to the application ,
* events are also dispatched during the life - cycle of the command .
*
* @ return int 0 if everything went fine , or an error code
*/
protected function doRunCommand ( Command $command , InputInterface $input , OutputInterface $output )
{
foreach ( $command -> getHelperSet () as $helper ) {
if ( $helper instanceof InputAwareInterface ) {
$helper -> setInput ( $input );
}
}
if ( null === $this -> dispatcher ) {
2017-07-03 15:47:07 +00:00
return $command -> run ( $input , $output );
2015-08-18 00:00:26 +00:00
}
2016-04-20 16:56:34 +00:00
// bind before the console.command event, so the listeners have access to input options/arguments
try {
$command -> mergeApplicationDefinition ();
$input -> bind ( $command -> getDefinition ());
} catch ( ExceptionInterface $e ) {
// ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
}
2015-08-18 00:00:26 +00:00
$event = new ConsoleCommandEvent ( $command , $input , $output );
2017-07-03 15:47:07 +00:00
$e = null ;
2015-08-18 00:00:26 +00:00
2017-07-03 15:47:07 +00:00
try {
$this -> dispatcher -> dispatch ( ConsoleEvents :: COMMAND , $event );
if ( $event -> commandShouldRun ()) {
2015-08-18 00:00:26 +00:00
$exitCode = $command -> run ( $input , $output );
2017-07-03 15:47:07 +00:00
} else {
$exitCode = ConsoleCommandEvent :: RETURN_CODE_DISABLED ;
2017-02-03 00:28:38 +00:00
}
2017-07-03 15:47:07 +00:00
} catch ( \Exception $e ) {
} catch ( \Throwable $e ) {
}
if ( null !== $e ) {
2018-11-23 12:29:20 +00:00
if ( $this -> dispatcher -> hasListeners ( ConsoleEvents :: EXCEPTION )) {
$x = $e instanceof \Exception ? $e : new FatalThrowableError ( $e );
$event = new ConsoleExceptionEvent ( $command , $input , $output , $x , $x -> getCode ());
$this -> dispatcher -> dispatch ( ConsoleEvents :: EXCEPTION , $event );
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
if ( $x !== $event -> getException ()) {
$e = $event -> getException ();
}
}
$event = new ConsoleErrorEvent ( $input , $output , $e , $command );
$this -> dispatcher -> dispatch ( ConsoleEvents :: ERROR , $event );
$e = $event -> getError ();
if ( 0 === $exitCode = $event -> getExitCode ()) {
$e = null ;
2015-08-18 00:00:26 +00:00
}
}
$event = new ConsoleTerminateEvent ( $command , $input , $output , $exitCode );
$this -> dispatcher -> dispatch ( ConsoleEvents :: TERMINATE , $event );
2017-07-03 15:47:07 +00:00
if ( null !== $e ) {
throw $e ;
}
2015-08-18 00:00:26 +00:00
return $event -> getExitCode ();
}
/**
* Gets the name of the command based on input .
*
* @ return string The command name
*/
protected function getCommandName ( InputInterface $input )
{
2018-11-23 12:29:20 +00:00
return $this -> singleCommand ? $this -> defaultCommand : $input -> getFirstArgument ();
2015-08-18 00:00:26 +00:00
}
/**
* Gets the default input definition .
*
* @ return InputDefinition An InputDefinition instance
*/
protected function getDefaultInputDefinition ()
{
return new InputDefinition ( array (
new InputArgument ( 'command' , InputArgument :: REQUIRED , 'The command to execute' ),
new InputOption ( '--help' , '-h' , InputOption :: VALUE_NONE , 'Display this help message' ),
new InputOption ( '--quiet' , '-q' , InputOption :: VALUE_NONE , 'Do not output any message' ),
new InputOption ( '--verbose' , '-v|vv|vvv' , InputOption :: VALUE_NONE , 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug' ),
new InputOption ( '--version' , '-V' , InputOption :: VALUE_NONE , 'Display this application version' ),
new InputOption ( '--ansi' , '' , InputOption :: VALUE_NONE , 'Force ANSI output' ),
new InputOption ( '--no-ansi' , '' , InputOption :: VALUE_NONE , 'Disable ANSI output' ),
new InputOption ( '--no-interaction' , '-n' , InputOption :: VALUE_NONE , 'Do not ask any interactive question' ),
));
}
/**
* Gets the default commands that should always be available .
*
* @ return Command [] An array of default Command instances
*/
protected function getDefaultCommands ()
{
return array ( new HelpCommand (), new ListCommand ());
}
/**
* Gets the default helper set with the helpers that should always be available .
*
* @ return HelperSet A HelperSet instance
*/
protected function getDefaultHelperSet ()
{
return new HelperSet ( array (
new FormatterHelper (),
new DebugFormatterHelper (),
new ProcessHelper (),
new QuestionHelper (),
));
}
/**
* Returns abbreviated suggestions in string format .
*
* @ param array $abbrevs Abbreviated suggestions to convert
*
* @ return string A formatted string of abbreviated suggestions
*/
private function getAbbreviationSuggestions ( $abbrevs )
{
2018-11-23 12:29:20 +00:00
return ' ' . implode ( " \n " , $abbrevs );
2015-08-18 00:00:26 +00:00
}
/**
* Returns the namespace part of the command name .
*
* This method is not part of public API and should not be used directly .
*
* @ param string $name The full name of the command
* @ param string $limit The maximum number of parts of the namespace
*
* @ return string The namespace of the command
*/
public function extractNamespace ( $name , $limit = null )
{
$parts = explode ( ':' , $name );
array_pop ( $parts );
2018-11-23 12:29:20 +00:00
return implode ( ':' , null === $limit ? $parts : \array_slice ( $parts , 0 , $limit ));
2015-08-18 00:00:26 +00:00
}
/**
* Finds alternative of $name among $collection ,
* if nothing is found in $collection , try in $abbrevs .
*
2018-11-23 12:29:20 +00:00
* @ param string $name The string
* @ param iterable $collection The collection
2015-08-18 00:00:26 +00:00
*
2017-02-03 00:28:38 +00:00
* @ return string [] A sorted array of similar string
2015-08-18 00:00:26 +00:00
*/
private function findAlternatives ( $name , $collection )
{
$threshold = 1e3 ;
$alternatives = array ();
$collectionParts = array ();
foreach ( $collection as $item ) {
$collectionParts [ $item ] = explode ( ':' , $item );
}
foreach ( explode ( ':' , $name ) as $i => $subname ) {
foreach ( $collectionParts as $collectionName => $parts ) {
$exists = isset ( $alternatives [ $collectionName ]);
if ( ! isset ( $parts [ $i ]) && $exists ) {
$alternatives [ $collectionName ] += $threshold ;
continue ;
} elseif ( ! isset ( $parts [ $i ])) {
continue ;
}
$lev = levenshtein ( $subname , $parts [ $i ]);
2018-11-23 12:29:20 +00:00
if ( $lev <= \strlen ( $subname ) / 3 || '' !== $subname && false !== strpos ( $parts [ $i ], $subname )) {
2015-08-18 00:00:26 +00:00
$alternatives [ $collectionName ] = $exists ? $alternatives [ $collectionName ] + $lev : $lev ;
} elseif ( $exists ) {
$alternatives [ $collectionName ] += $threshold ;
}
}
}
foreach ( $collection as $item ) {
$lev = levenshtein ( $name , $item );
2018-11-23 12:29:20 +00:00
if ( $lev <= \strlen ( $name ) / 3 || false !== strpos ( $item , $name )) {
2015-08-18 00:00:26 +00:00
$alternatives [ $item ] = isset ( $alternatives [ $item ]) ? $alternatives [ $item ] - $lev : $lev ;
}
}
2015-08-27 19:03:05 +00:00
$alternatives = array_filter ( $alternatives , function ( $lev ) use ( $threshold ) { return $lev < 2 * $threshold ; });
2018-11-23 12:29:20 +00:00
ksort ( $alternatives , SORT_NATURAL | SORT_FLAG_CASE );
2015-08-18 00:00:26 +00:00
return array_keys ( $alternatives );
}
/**
* Sets the default Command name .
*
2018-11-23 12:29:20 +00:00
* @ param string $commandName The Command name
* @ param bool $isSingleCommand Set to true if there is only one command in this application
*
* @ return self
2015-08-18 00:00:26 +00:00
*/
2018-11-23 12:29:20 +00:00
public function setDefaultCommand ( $commandName , $isSingleCommand = false )
2015-08-18 00:00:26 +00:00
{
$this -> defaultCommand = $commandName ;
2018-11-23 12:29:20 +00:00
if ( $isSingleCommand ) {
// Ensure the command exist
$this -> find ( $commandName );
$this -> singleCommand = true ;
}
return $this ;
2015-08-18 00:00:26 +00:00
}
private function splitStringByWidth ( $string , $width )
{
// str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
// additionally, array_slice() is not enough as some character has doubled width.
// we need a function to split string not by character count but by string width
2016-04-20 16:56:34 +00:00
if ( false === $encoding = mb_detect_encoding ( $string , null , true )) {
2015-08-18 00:00:26 +00:00
return str_split ( $string , $width );
}
$utf8String = mb_convert_encoding ( $string , 'utf8' , $encoding );
$lines = array ();
$line = '' ;
foreach ( preg_split ( '//u' , $utf8String ) as $char ) {
// test if $char could be appended to current line
if ( mb_strwidth ( $line . $char , 'utf8' ) <= $width ) {
$line .= $char ;
continue ;
}
// if not, push current line to array and make new line
$lines [] = str_pad ( $line , $width );
$line = $char ;
}
2018-11-23 12:29:20 +00:00
$lines [] = \count ( $lines ) ? str_pad ( $line , $width ) : $line ;
2015-08-18 00:00:26 +00:00
mb_convert_variables ( $encoding , 'utf8' , $lines );
return $lines ;
}
/**
* Returns all namespaces of the command name .
*
* @ param string $name The full name of the command
*
2017-02-03 00:28:38 +00:00
* @ return string [] The namespaces of the command
2015-08-18 00:00:26 +00:00
*/
private function extractAllNamespaces ( $name )
{
// -1 as third argument is needed to skip the command short name when exploding
$parts = explode ( ':' , $name , - 1 );
$namespaces = array ();
foreach ( $parts as $part ) {
2018-11-23 12:29:20 +00:00
if ( \count ( $namespaces )) {
2015-08-18 00:00:26 +00:00
$namespaces [] = end ( $namespaces ) . ':' . $part ;
} else {
$namespaces [] = $part ;
}
}
return $namespaces ;
}
2018-11-23 12:29:20 +00:00
private function init ()
{
if ( $this -> initialized ) {
return ;
}
$this -> initialized = true ;
foreach ( $this -> getDefaultCommands () as $command ) {
$this -> add ( $command );
}
}
2015-08-18 00:00:26 +00:00
}