2010-01-04 14:42:28 +00:00
< ? php
2011-01-15 13:29:43 +00:00
/*
* This file is part of the Symfony package .
*
2011-03-06 11:40:06 +00:00
* ( c ) Fabien Potencier < fabien @ symfony . com >
2011-01-15 13:29:43 +00:00
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
2010-08-20 22:09:55 +01:00
namespace Symfony\Component\Console ;
2010-01-09 11:57:15 +00:00
2013-03-22 13:40:47 +00:00
use Symfony\Component\Console\Descriptor\TextDescriptor ;
use Symfony\Component\Console\Descriptor\XmlDescriptor ;
2010-08-20 22:09:55 +01:00
use Symfony\Component\Console\Input\InputInterface ;
use Symfony\Component\Console\Input\ArgvInput ;
use Symfony\Component\Console\Input\ArrayInput ;
use Symfony\Component\Console\Input\InputDefinition ;
use Symfony\Component\Console\Input\InputOption ;
use Symfony\Component\Console\Input\InputArgument ;
use Symfony\Component\Console\Output\OutputInterface ;
use Symfony\Component\Console\Output\ConsoleOutput ;
2011-12-16 14:08:35 +00:00
use Symfony\Component\Console\Output\ConsoleOutputInterface ;
2010-08-20 22:09:55 +01:00
use Symfony\Component\Console\Command\Command ;
use Symfony\Component\Console\Command\HelpCommand ;
use Symfony\Component\Console\Command\ListCommand ;
use Symfony\Component\Console\Helper\HelperSet ;
use Symfony\Component\Console\Helper\FormatterHelper ;
use Symfony\Component\Console\Helper\DialogHelper ;
2012-09-29 21:11:59 +01:00
use Symfony\Component\Console\Helper\ProgressHelper ;
2012-12-15 15:08:23 +00:00
use Symfony\Component\Console\Helper\TableHelper ;
2013-03-24 09:08:12 +00:00
use Symfony\Component\Console\Event\ConsoleCommandEvent ;
2013-05-27 11:36:30 +01:00
use Symfony\Component\Console\Event\ConsoleExceptionEvent ;
2013-03-24 09:08:12 +00:00
use Symfony\Component\Console\Event\ConsoleTerminateEvent ;
2013-05-28 20:36:15 +01:00
use Symfony\Component\EventDispatcher\EventDispatcherInterface ;
2010-01-04 14:42:28 +00:00
/**
2010-01-04 18:51:21 +00:00
* An Application is the container for a collection of commands .
2010-01-04 14:42:28 +00:00
*
2010-01-09 11:57:15 +00:00
* It is the main entry point of a Console application .
2010-01-04 14:42:28 +00:00
*
* This class is optimized for a standard CLI environment .
*
* Usage :
*
* $app = new Application ( 'myapp' , '1.0 (stable)' );
2010-11-23 08:42:19 +00:00
* $app -> add ( new SimpleCommand ());
2010-01-04 14:42:28 +00:00
* $app -> run ();
*
2011-03-06 11:40:06 +00:00
* @ author Fabien Potencier < fabien @ symfony . com >
2011-03-24 08:39:53 +00:00
*
* @ api
2010-01-04 14:42:28 +00:00
*/
class Application
{
2011-03-11 11:53:42 +00:00
private $commands ;
private $wantHelps = false ;
private $runningCommand ;
private $name ;
private $version ;
private $catchExceptions ;
private $autoExit ;
private $definition ;
private $helperSet ;
2013-03-24 09:08:12 +00:00
private $dispatcher ;
2010-05-06 12:25:53 +01:00
/**
* Constructor .
*
2012-05-15 21:19:31 +01:00
* @ param string $name The name of the application
* @ param string $version The version of the application
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function __construct ( $name = 'UNKNOWN' , $version = 'UNKNOWN' )
{
$this -> name = $name ;
$this -> version = $version ;
$this -> catchExceptions = true ;
$this -> autoExit = true ;
$this -> commands = array ();
2011-10-25 16:11:49 +01:00
$this -> helperSet = $this -> getDefaultHelperSet ();
$this -> definition = $this -> getDefaultInputDefinition ();
2010-05-06 12:25:53 +01:00
2011-10-25 16:11:49 +01:00
foreach ( $this -> getDefaultCommands () as $command ) {
$this -> add ( $command );
}
2010-05-06 12:25:53 +01:00
}
2013-05-28 20:36:15 +01:00
public function setDispatcher ( EventDispatcherInterface $dispatcher )
2013-03-24 09:08:12 +00:00
{
$this -> dispatcher = $dispatcher ;
}
2010-05-06 12:25:53 +01:00
/**
* Runs the current application .
*
* @ param InputInterface $input An Input instance
* @ param OutputInterface $output An Output instance
*
* @ return integer 0 if everything went fine , or an error code
*
* @ throws \Exception When doRun returns Exception
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function run ( InputInterface $input = null , OutputInterface $output = null )
{
2010-05-07 15:09:11 +01:00
if ( null === $input ) {
2010-05-06 12:25:53 +01:00
$input = new ArgvInput ();
}
2010-01-04 14:42:28 +00:00
2010-05-07 15:09:11 +01:00
if ( null === $output ) {
2010-05-06 12:25:53 +01:00
$output = new ConsoleOutput ();
}
2010-01-04 14:42:28 +00:00
2013-05-09 09:57:19 +01:00
$this -> configureIO ( $input , $output );
2010-05-07 15:09:11 +01:00
try {
2013-03-24 09:08:12 +00:00
$exitCode = $this -> doRun ( $input , $output );
2010-05-07 15:09:11 +01:00
} catch ( \Exception $e ) {
2010-05-08 14:32:30 +01:00
if ( ! $this -> catchExceptions ) {
2010-05-06 12:25:53 +01:00
throw $e ;
}
2011-12-16 14:08:35 +00:00
if ( $output instanceof ConsoleOutputInterface ) {
$this -> renderException ( $e , $output -> getErrorOutput ());
} else {
$this -> renderException ( $e , $output );
}
2010-05-06 12:25:53 +01:00
2013-06-11 08:15:14 +01:00
$exitCode = $e -> getCode ();
if ( is_numeric ( $exitCode )) {
$exitCode = ( int ) $exitCode ;
if ( 0 === $exitCode ) {
$exitCode = 1 ;
2013-06-05 09:14:54 +01:00
}
} else {
2013-06-11 08:15:14 +01:00
$exitCode = 1 ;
2013-06-05 09:14:54 +01:00
}
2010-05-06 12:25:53 +01:00
}
2010-05-07 15:09:11 +01:00
if ( $this -> autoExit ) {
2013-03-24 09:08:12 +00:00
if ( $exitCode > 255 ) {
$exitCode = 255 ;
2010-10-12 11:57:22 +01:00
}
2010-05-06 12:25:53 +01:00
// @codeCoverageIgnoreStart
2013-03-24 09:08:12 +00:00
exit ( $exitCode );
2010-05-06 12:25:53 +01:00
// @codeCoverageIgnoreEnd
}
2011-02-27 16:48:41 +00:00
2013-03-24 09:08:12 +00:00
return $exitCode ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Runs the current application .
*
* @ param InputInterface $input An Input instance
* @ param OutputInterface $output An Output instance
*
* @ return integer 0 if everything went fine , or an error code
*/
public function doRun ( InputInterface $input , OutputInterface $output )
2010-01-04 14:42:28 +00:00
{
2010-05-07 15:09:11 +01:00
if ( true === $input -> hasParameterOption ( array ( '--version' , '-V' ))) {
2010-05-06 12:25:53 +01:00
$output -> writeln ( $this -> getLongVersion ());
return 0 ;
}
2013-05-09 09:40:45 +01:00
$name = $this -> getCommandName ( $input );
if ( true === $input -> hasParameterOption ( array ( '--help' , '-h' ))) {
if ( ! $name ) {
$name = 'help' ;
$input = new ArrayInput ( array ( 'command' => 'help' ));
} else {
$this -> wantHelps = true ;
}
}
2010-05-07 15:09:11 +01:00
if ( ! $name ) {
2010-05-06 12:25:53 +01:00
$name = 'list' ;
$input = new ArrayInput ( array ( 'command' => 'list' ));
}
2010-01-04 14:42:28 +00:00
2010-05-06 12:25:53 +01:00
// the command name MUST be the first element of the input
2010-11-23 08:42:19 +00:00
$command = $this -> find ( $name );
2010-01-04 14:42:28 +00:00
2010-05-06 12:25:53 +01:00
$this -> runningCommand = $command ;
2013-03-24 09:08:12 +00:00
$exitCode = $this -> doRunCommand ( $command , $input , $output );
2010-05-06 12:25:53 +01:00
$this -> runningCommand = null ;
2013-05-19 20:06:00 +01:00
return $exitCode ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Set a helper set to be used with the command .
*
* @ param HelperSet $helperSet The helper set
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function setHelperSet ( HelperSet $helperSet )
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$this -> helperSet = $helperSet ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
2011-02-07 00:34:24 +00:00
* Get the helper set associated with the command .
2010-05-06 12:25:53 +01:00
*
* @ return HelperSet The HelperSet instance associated with this command
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function getHelperSet ()
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
return $this -> helperSet ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
2012-10-01 14:15:04 +01:00
/**
* Set an input definition set to be used with this application
*
* @ param InputDefinition $definition The input definition
*
* @ api
*/
public function setDefinition ( InputDefinition $definition )
{
$this -> definition = $definition ;
}
2010-05-06 12:25:53 +01:00
/**
* Gets the InputDefinition related to this Application .
*
* @ return InputDefinition The InputDefinition instance
*/
public function getDefinition ()
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
return $this -> definition ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Gets the help message .
*
* @ return string A help message .
*/
public function getHelp ()
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$messages = array (
$this -> getLongVersion (),
'' ,
'<comment>Usage:</comment>' ,
2013-01-18 07:38:59 +00:00
' [options] command [arguments]' ,
'' ,
2010-05-06 12:25:53 +01:00
'<comment>Options:</comment>' ,
);
2011-03-12 11:59:51 +00:00
foreach ( $this -> getDefinition () -> getOptions () as $option ) {
2010-05-06 12:25:53 +01:00
$messages [] = sprintf ( ' %-29s %s %s' ,
'<info>--' . $option -> getName () . '</info>' ,
$option -> getShortcut () ? '<info>-' . $option -> getShortcut () . '</info>' : ' ' ,
$option -> getDescription ()
);
}
2012-01-09 16:05:16 +00:00
return implode ( PHP_EOL , $messages );
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Sets whether to catch exceptions or not during commands execution .
*
* @ param Boolean $boolean Whether to catch exceptions or not during commands execution
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function setCatchExceptions ( $boolean )
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$this -> catchExceptions = ( Boolean ) $boolean ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Sets whether to automatically exit after a command execution or not .
*
* @ param Boolean $boolean Whether to automatically exit after a command execution or not
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function setAutoExit ( $boolean )
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$this -> autoExit = ( Boolean ) $boolean ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Gets the name of the application .
*
* @ return string The application name
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function getName ()
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
return $this -> name ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Sets the application name .
*
* @ param string $name The application name
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function setName ( $name )
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$this -> name = $name ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Gets the application version .
*
* @ return string The application version
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function getVersion ()
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
return $this -> version ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Sets the application version .
*
* @ param string $version The application version
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function setVersion ( $version )
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$this -> version = $version ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Returns the long version of the application .
*
* @ return string The long application version
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function getLongVersion ()
2010-01-04 19:01:46 +00:00
{
2010-05-07 15:09:11 +01:00
if ( 'UNKNOWN' !== $this -> getName () && 'UNKNOWN' !== $this -> getVersion ()) {
2010-05-06 12:25:53 +01:00
return sprintf ( '<info>%s</info> version <comment>%s</comment>' , $this -> getName (), $this -> getVersion ());
}
2011-02-27 16:48:41 +00:00
return '<info>Console Tool</info>' ;
2010-01-04 19:01:46 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Registers a new command .
*
* @ param string $name The command name
*
* @ return Command The newly created command
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function register ( $name )
2010-01-04 19:01:46 +00:00
{
2010-11-23 08:42:19 +00:00
return $this -> add ( new Command ( $name ));
2010-01-04 19:01:46 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Adds an array of command objects .
*
* @ param Command [] $commands An array of commands
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
public function addCommands ( array $commands )
2010-01-04 14:42:28 +00:00
{
2010-05-07 15:09:11 +01:00
foreach ( $commands as $command ) {
2010-11-23 08:42:19 +00:00
$this -> add ( $command );
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Adds a command object .
*
* If a command with the same name already exists , it will be overridden .
*
* @ param Command $command A Command object
*
* @ return Command The registered command
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
2010-11-23 08:42:19 +00:00
public function add ( Command $command )
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$command -> setApplication ( $this );
2011-06-28 23:18:03 +01:00
if ( ! $command -> isEnabled ()) {
$command -> setApplication ( null );
2011-10-29 11:05:45 +01:00
2011-06-28 23:18:03 +01:00
return ;
}
2011-06-07 16:51:43 +01:00
$this -> commands [ $command -> getName ()] = $command ;
2010-05-06 12:25:53 +01:00
2010-05-07 15:09:11 +01:00
foreach ( $command -> getAliases () as $alias ) {
2011-06-07 17:14:15 +01:00
$this -> commands [ $alias ] = $command ;
2010-05-06 12:25:53 +01:00
}
return $command ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Returns a registered command by name or alias .
*
* @ param string $name The command name or alias
*
* @ return Command A Command object
*
* @ throws \InvalidArgumentException When command name given does not exist
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
2010-11-23 08:42:19 +00:00
public function get ( $name )
2010-01-04 14:42:28 +00:00
{
2011-06-07 17:14:15 +01:00
if ( ! isset ( $this -> commands [ $name ])) {
2010-05-06 12:25:53 +01:00
throw new \InvalidArgumentException ( sprintf ( 'The command "%s" does not exist.' , $name ));
}
2010-01-04 14:42:28 +00:00
2011-06-07 17:14:15 +01:00
$command = $this -> commands [ $name ];
2010-01-04 14:42:28 +00:00
2010-05-07 15:09:11 +01:00
if ( $this -> wantHelps ) {
2010-05-06 12:25:53 +01:00
$this -> wantHelps = false ;
2010-01-04 14:42:28 +00:00
2010-11-23 08:42:19 +00:00
$helpCommand = $this -> get ( 'help' );
2010-05-06 12:25:53 +01:00
$helpCommand -> setCommand ( $command );
2010-01-04 14:42:28 +00:00
2010-05-06 12:25:53 +01:00
return $helpCommand ;
}
2010-01-04 14:42:28 +00:00
2010-05-06 12:25:53 +01:00
return $command ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
2011-02-07 00:34:24 +00:00
* Returns true if the command exists , false otherwise .
2010-05-06 12:25:53 +01:00
*
* @ param string $name The command name or alias
*
* @ return Boolean true if the command exists , false otherwise
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
2010-11-23 08:42:19 +00:00
public function has ( $name )
2010-01-04 14:42:28 +00:00
{
2011-06-07 17:14:15 +01:00
return isset ( $this -> commands [ $name ]);
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Returns an array of all unique namespaces used by currently registered commands .
*
* It does not returns the global namespace which always exists .
*
* @ return array An array of namespaces
*/
public function getNamespaces ()
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$namespaces = array ();
2010-05-07 15:09:11 +01:00
foreach ( $this -> commands as $command ) {
2011-06-07 17:14:15 +01:00
$namespaces [] = $this -> extractNamespace ( $command -> getName ());
2011-06-07 16:51:43 +01:00
foreach ( $command -> getAliases () as $alias ) {
2011-06-07 17:14:15 +01:00
$namespaces [] = $this -> extractNamespace ( $alias );
2010-05-06 12:25:53 +01:00
}
}
2011-06-07 17:26:00 +01:00
return array_values ( array_unique ( array_filter ( $namespaces )));
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Finds a registered namespace by a name or an abbreviation .
*
2011-02-07 00:34:24 +00:00
* @ param string $namespace A namespace or abbreviation to search for
*
2010-05-06 12:25:53 +01:00
* @ return string A registered namespace
*
* @ throws \InvalidArgumentException When namespace is incorrect or ambiguous
*/
public function findNamespace ( $namespace )
2010-01-04 14:42:28 +00:00
{
2013-04-07 15:34:20 +01:00
$allNamespaces = $this -> getNamespaces ();
$found = '' ;
2011-06-07 16:51:43 +01:00
foreach ( explode ( ':' , $namespace ) as $i => $part ) {
2013-04-07 15:34:20 +01:00
// select sub-namespaces matching the current namespace we found
$namespaces = array ();
foreach ( $allNamespaces as $n ) {
if ( '' === $found || 0 === strpos ( $n , $found )) {
$namespaces [ $n ] = explode ( ':' , $n );
}
}
$abbrevs = static :: getAbbreviations ( array_unique ( array_values ( array_filter ( array_map ( function ( $p ) use ( $i ) { return isset ( $p [ $i ]) ? $p [ $i ] : '' ; }, $namespaces )))));
2011-06-07 16:51:43 +01:00
if ( ! isset ( $abbrevs [ $part ])) {
2012-02-11 19:38:08 +00:00
$message = sprintf ( 'There are no commands defined in the "%s" namespace.' , $namespace );
2012-02-12 16:53:56 +00:00
if ( 1 <= $i ) {
2013-04-07 15:34:20 +01:00
$part = $found . ':' . $part ;
2012-02-12 16:53:56 +00:00
}
if ( $alternatives = $this -> findAlternativeNamespace ( $part , $abbrevs )) {
2012-08-07 15:16:59 +01:00
if ( 1 == count ( $alternatives )) {
$message .= " \n \n Did you mean this? \n " ;
} else {
$message .= " \n \n Did you mean one of these? \n " ;
}
2012-02-11 19:38:08 +00:00
$message .= implode ( " \n " , $alternatives );
}
throw new \InvalidArgumentException ( $message );
2011-06-07 16:51:43 +01:00
}
2013-04-07 15:34:20 +01:00
// there are multiple matches, but $part is an exact match of one of them so we select it
if ( in_array ( $part , $abbrevs [ $part ])) {
$abbrevs [ $part ] = array ( $part );
}
2011-06-07 16:51:43 +01:00
if ( count ( $abbrevs [ $part ]) > 1 ) {
2011-10-11 11:56:40 +01:00
throw new \InvalidArgumentException ( sprintf ( 'The namespace "%s" is ambiguous (%s).' , $namespace , $this -> getAbbreviationSuggestions ( $abbrevs [ $part ])));
2011-06-07 16:51:43 +01:00
}
2013-04-07 15:34:20 +01:00
$found .= $found ? ':' . $abbrevs [ $part ][ 0 ] : $abbrevs [ $part ][ 0 ];
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:42:28 +00:00
2013-04-07 15:34:20 +01:00
return $found ;
2010-05-06 12:25:53 +01:00
}
/**
* Finds a command by name or alias .
*
2010-11-23 08:42:19 +00:00
* Contrary to get , this command tries to find the best
2010-05-06 12:25:53 +01:00
* match if you give it an abbreviation of a name or alias .
*
2012-05-15 21:19:31 +01:00
* @ param string $name A command name or a command alias
2010-05-06 12:25:53 +01:00
*
* @ return Command A Command instance
*
* @ throws \InvalidArgumentException When command name is incorrect or ambiguous
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
2010-11-23 08:42:19 +00:00
public function find ( $name )
2010-05-06 12:25:53 +01:00
{
// namespace
$namespace = '' ;
2011-06-07 16:51:43 +01:00
$searchName = $name ;
2010-05-07 15:09:11 +01:00
if ( false !== $pos = strrpos ( $name , ':' )) {
2010-05-06 12:25:53 +01:00
$namespace = $this -> findNamespace ( substr ( $name , 0 , $pos ));
2011-06-07 16:51:43 +01:00
$searchName = $namespace . substr ( $name , $pos );
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:42:28 +00:00
2010-05-06 12:25:53 +01:00
// name
$commands = array ();
2010-05-07 15:09:11 +01:00
foreach ( $this -> commands as $command ) {
2012-10-09 21:33:47 +01:00
$extractedNamespace = $this -> extractNamespace ( $command -> getName ());
if ( $extractedNamespace === $namespace
|| ! empty ( $namespace ) && 0 === strpos ( $extractedNamespace , $namespace )
) {
2010-05-06 12:25:53 +01:00
$commands [] = $command -> getName ();
}
}
2010-01-04 14:42:28 +00:00
2011-06-07 17:14:15 +01:00
$abbrevs = static :: getAbbreviations ( array_unique ( $commands ));
2011-06-07 16:51:43 +01:00
if ( isset ( $abbrevs [ $searchName ]) && 1 == count ( $abbrevs [ $searchName ])) {
return $this -> get ( $abbrevs [ $searchName ][ 0 ]);
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:42:28 +00:00
2013-04-26 23:56:13 +01:00
if ( isset ( $abbrevs [ $searchName ]) && in_array ( $searchName , $abbrevs [ $searchName ])) {
return $this -> get ( $searchName );
}
2011-06-07 16:51:43 +01:00
if ( isset ( $abbrevs [ $searchName ]) && count ( $abbrevs [ $searchName ]) > 1 ) {
$suggestions = $this -> getAbbreviationSuggestions ( $abbrevs [ $searchName ]);
2010-01-04 14:42:28 +00:00
2011-06-07 16:51:43 +01:00
throw new \InvalidArgumentException ( sprintf ( 'Command "%s" is ambiguous (%s).' , $name , $suggestions ));
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:42:28 +00:00
2010-05-06 12:25:53 +01:00
// aliases
2011-06-07 17:14:15 +01:00
$aliases = array ();
foreach ( $this -> commands as $command ) {
foreach ( $command -> getAliases () as $alias ) {
2012-10-09 21:33:47 +01:00
$extractedNamespace = $this -> extractNamespace ( $alias );
if ( $extractedNamespace === $namespace
|| ! empty ( $namespace ) && 0 === strpos ( $extractedNamespace , $namespace )
) {
2011-06-07 17:14:15 +01:00
$aliases [] = $alias ;
}
}
}
2012-02-12 16:53:56 +00:00
$aliases = static :: getAbbreviations ( array_unique ( $aliases ));
if ( ! isset ( $aliases [ $searchName ])) {
2012-02-11 01:58:39 +00:00
$message = sprintf ( 'Command "%s" is not defined.' , $name );
2012-02-12 16:53:56 +00:00
if ( $alternatives = $this -> findAlternativeCommands ( $searchName , $abbrevs )) {
2012-08-07 15:16:59 +01:00
if ( 1 == count ( $alternatives )) {
$message .= " \n \n Did you mean this? \n " ;
} else {
$message .= " \n \n Did you mean one of these? \n " ;
}
2012-02-11 15:33:06 +00:00
$message .= implode ( " \n " , $alternatives );
2012-02-11 01:58:39 +00:00
}
throw new \InvalidArgumentException ( $message );
2010-05-06 12:25:53 +01:00
}
2012-02-12 16:53:56 +00:00
if ( count ( $aliases [ $searchName ]) > 1 ) {
throw new \InvalidArgumentException ( sprintf ( 'Command "%s" is ambiguous (%s).' , $name , $this -> getAbbreviationSuggestions ( $aliases [ $searchName ])));
2010-05-06 12:25:53 +01:00
}
2012-02-12 16:53:56 +00:00
return $this -> get ( $aliases [ $searchName ][ 0 ]);
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Gets the commands ( registered in the given namespace if provided ) .
*
* The array keys are the full names and the values the command instances .
*
2012-05-15 21:19:31 +01:00
* @ param string $namespace A namespace name
2010-05-06 12:25:53 +01:00
*
2012-11-01 15:08:59 +00:00
* @ return Command [] An array of Command instances
2011-03-24 08:39:53 +00:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
2010-11-23 08:42:19 +00:00
public function all ( $namespace = null )
2010-01-04 14:42:28 +00:00
{
2010-05-07 15:09:11 +01:00
if ( null === $namespace ) {
2010-05-06 12:25:53 +01:00
return $this -> commands ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
$commands = array ();
2010-05-07 15:09:11 +01:00
foreach ( $this -> commands as $name => $command ) {
2011-09-26 00:05:02 +01:00
if ( $namespace === $this -> extractNamespace ( $name , substr_count ( $namespace , ':' ) + 1 )) {
2010-05-06 12:25:53 +01:00
$commands [ $name ] = $command ;
}
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
return $commands ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Returns an array of possible abbreviations given a set of names .
*
2010-07-01 18:38:34 +01:00
* @ param array $names An array of names
2010-05-06 12:25:53 +01:00
*
* @ return array An array of abbreviations
*/
2012-07-09 13:50:58 +01:00
public static function getAbbreviations ( $names )
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
$abbrevs = array ();
2010-05-07 15:09:11 +01:00
foreach ( $names as $name ) {
2013-04-07 15:34:20 +01:00
for ( $len = strlen ( $name ); $len > 0 ; -- $len ) {
2010-05-06 12:25:53 +01:00
$abbrev = substr ( $name , 0 , $len );
2013-04-07 15:34:20 +01:00
$abbrevs [ $abbrev ][] = $name ;
2010-05-06 12:25:53 +01:00
}
}
2010-01-04 14:42:28 +00:00
2010-05-06 12:25:53 +01:00
return $abbrevs ;
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Returns a text representation of the Application .
*
2011-12-18 13:32:45 +00:00
* @ param string $namespace An optional namespace name
* @ param boolean $raw Whether to return raw command list
2010-05-06 12:25:53 +01:00
*
* @ return string A string representing the Application
2013-03-22 13:40:47 +00:00
*
* @ deprecated Deprecated since version 2.3 , to be removed in 3.0 .
2010-05-06 12:25:53 +01:00
*/
2011-12-17 23:19:10 +00:00
public function asText ( $namespace = null , $raw = false )
2010-01-04 14:42:28 +00:00
{
2013-03-22 13:40:47 +00:00
$descriptor = new TextDescriptor ();
2010-01-04 14:42:28 +00:00
2013-03-22 13:40:47 +00:00
return $descriptor -> describe ( $this , array ( 'namespace' => $namespace , 'raw_text' => $raw ));
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
* Returns an XML representation of the Application .
*
2011-04-23 16:05:44 +01:00
* @ param string $namespace An optional namespace name
* @ param Boolean $asDom Whether to return a DOM or an XML string
2010-05-06 12:25:53 +01:00
*
2013-03-22 13:40:47 +00:00
* @ return string | \DOMDocument An XML string representing the Application
*
* @ deprecated Deprecated since version 2.3 , to be removed in 3.0 .
2010-05-06 12:25:53 +01:00
*/
public function asXml ( $namespace = null , $asDom = false )
2010-01-04 14:42:28 +00:00
{
2013-03-22 13:40:47 +00:00
$descriptor = new XmlDescriptor ();
2010-05-06 12:25:53 +01:00
2013-03-22 13:40:47 +00:00
return $descriptor -> describe ( $this , array ( 'namespace' => $namespace , 'as_dom' => $asDom ));
2010-01-04 14:42:28 +00:00
}
2010-05-06 12:25:53 +01:00
/**
2012-05-09 17:42:13 +01:00
* Renders a caught exception .
2010-05-06 12:25:53 +01:00
*
2013-09-18 13:41:53 +01:00
* @ param \Exception $e An exception instance
2010-05-06 12:25:53 +01:00
* @ param OutputInterface $output An OutputInterface instance
*/
public function renderException ( $e , $output )
2010-01-04 14:42:28 +00:00
{
2011-09-16 13:38:31 +01:00
$strlen = function ( $string ) {
if ( ! function_exists ( 'mb_strlen' )) {
return strlen ( $string );
}
2011-09-16 13:27:56 +01:00
if ( false === $encoding = mb_detect_encoding ( $string )) {
return strlen ( $string );
}
2011-09-16 13:38:31 +01:00
return mb_strlen ( $string , $encoding );
2010-05-06 12:25:53 +01:00
};
2010-01-04 14:42:28 +00:00
2011-01-11 07:49:57 +00:00
do {
$title = sprintf ( ' [%s] ' , get_class ( $e ));
$len = $strlen ( $title );
2012-04-06 13:21:18 +01:00
$width = $this -> getTerminalWidth () ? $this -> getTerminalWidth () - 1 : PHP_INT_MAX ;
2013-09-17 13:23:45 +01:00
$formatter = $output -> getFormatter ();
2011-01-11 07:49:57 +00:00
$lines = array ();
2013-01-05 17:54:53 +00:00
foreach ( preg_split ( '/\r?\n/' , $e -> getMessage ()) as $line ) {
2012-04-06 13:21:18 +01:00
foreach ( str_split ( $line , $width - 4 ) as $line ) {
2013-09-17 13:23:45 +01:00
// pre-format lines to get the right string length
$lineLength = $strlen ( preg_replace ( '/ \[[^m]*m/' , '' , $formatter -> format ( $line ))) + 4 ;
$lines [] = array ( $line , $lineLength );
$len = max ( $lineLength , $len );
2012-04-06 13:21:18 +01:00
}
2011-01-11 07:49:57 +00:00
}
2010-01-04 14:42:28 +00:00
2013-09-17 13:23:45 +01:00
$messages = array ( '' , '' );
$messages [] = $emptyLine = $formatter -> format ( sprintf ( '<error>%s</error>' , str_repeat ( ' ' , $len )));
$messages [] = $formatter -> format ( sprintf ( '<error>%s%s</error>' , $title , str_repeat ( ' ' , max ( 0 , $len - $strlen ( $title )))));
2011-01-11 07:49:57 +00:00
foreach ( $lines as $line ) {
2013-09-17 13:23:45 +01:00
$messages [] = $formatter -> format ( sprintf ( '<error> %s %s</error>' , $line [ 0 ], str_repeat ( ' ' , $len - $line [ 1 ])));
2011-01-11 07:49:57 +00:00
}
2013-09-17 13:23:45 +01:00
$messages [] = $emptyLine ;
$messages [] = '' ;
$messages [] = '' ;
2010-01-04 14:42:28 +00:00
2013-09-17 13:23:45 +01:00
$output -> writeln ( $messages , OutputInterface :: OUTPUT_RAW );
2010-05-06 12:25:53 +01:00
2013-04-25 11:13:01 +01:00
if ( OutputInterface :: VERBOSITY_VERBOSE <= $output -> getVerbosity ()) {
2011-05-27 14:34:13 +01:00
$output -> writeln ( '<comment>Exception trace:</comment>' );
2011-01-11 07:49:57 +00:00
// exception related properties
$trace = $e -> getTrace ();
array_unshift ( $trace , array (
'function' => '' ,
'file' => $e -> getFile () != null ? $e -> getFile () : 'n/a' ,
'line' => $e -> getLine () != null ? $e -> getLine () : 'n/a' ,
'args' => array (),
));
for ( $i = 0 , $count = count ( $trace ); $i < $count ; $i ++ ) {
$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' ;
$output -> writeln ( sprintf ( ' %s%s%s() at <info>%s:%s</info>' , $class , $type , $function , $file , $line ));
}
2010-05-06 12:25:53 +01:00
2012-01-09 16:05:16 +00:00
$output -> writeln ( " " );
$output -> writeln ( " " );
2010-05-06 12:25:53 +01:00
}
2011-01-11 07:49:57 +00:00
} while ( $e = $e -> getPrevious ());
2010-05-06 12:25:53 +01:00
2011-01-11 07:49:57 +00:00
if ( null !== $this -> runningCommand ) {
$output -> writeln ( sprintf ( '<info>%s</info>' , sprintf ( $this -> runningCommand -> getSynopsis (), $this -> getName ())));
2012-01-08 22:59:26 +00:00
$output -> writeln ( " " );
$output -> writeln ( " " );
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:42:28 +00:00
}
2012-04-06 17:25:51 +01:00
/**
* Tries to figure out the terminal width in which this application runs
*
* @ return int | null
*/
2013-01-05 20:32:06 +00:00
protected function getTerminalWidth ()
2012-04-06 13:21:18 +01:00
{
2013-01-05 17:54:53 +00:00
$dimensions = $this -> getTerminalDimensions ();
2012-04-06 13:21:18 +01:00
2013-01-05 17:54:53 +00:00
return $dimensions [ 0 ];
2012-04-06 13:21:18 +01:00
}
2012-04-06 17:25:51 +01:00
/**
* Tries to figure out the terminal height in which this application runs
*
* @ return int | null
*/
2013-01-05 20:32:06 +00:00
protected function getTerminalHeight ()
2013-01-05 17:54:53 +00:00
{
$dimensions = $this -> getTerminalDimensions ();
return $dimensions [ 1 ];
}
/**
* Tries to figure out the terminal dimensions based on the current environment
*
* @ return array Array containing width and height
*/
2013-01-05 20:33:45 +00:00
public function getTerminalDimensions ()
2012-04-06 13:21:18 +01:00
{
2012-06-16 09:57:49 +01:00
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
2013-01-05 17:54:53 +00:00
// extract [w, H] from "wxh (WxH)"
if ( preg_match ( '/^(\d+)x\d+ \(\d+x(\d+)\)$/' , trim ( getenv ( 'ANSICON' )), $matches )) {
return array (( int ) $matches [ 1 ], ( int ) $matches [ 2 ]);
2012-06-16 09:57:49 +01:00
}
2013-01-05 17:54:53 +00:00
// extract [w, h] from "wxh"
if ( preg_match ( '/^(\d+)x(\d+)$/' , $this -> getConsoleMode (), $matches )) {
return array (( int ) $matches [ 1 ], ( int ) $matches [ 2 ]);
2012-06-16 09:57:49 +01:00
}
2012-04-06 13:21:18 +01:00
}
2013-01-05 17:54:53 +00:00
if ( $sttyString = $this -> getSttyColumns ()) {
// extract [w, h] from "rows h; columns w;"
if ( preg_match ( '/rows.(\d+);.columns.(\d+);/i' , $sttyString , $matches )) {
return array (( int ) $matches [ 2 ], ( int ) $matches [ 1 ]);
}
// extract [w, h] from "; h rows; w columns"
if ( preg_match ( '/;.(\d+).rows;.(\d+).columns/i' , $sttyString , $matches )) {
return array (( int ) $matches [ 2 ], ( int ) $matches [ 1 ]);
}
2012-04-06 13:21:18 +01:00
}
2013-01-05 17:54:53 +00:00
return array ( null , null );
2012-04-06 13:21:18 +01:00
}
2013-05-09 09:57:19 +01:00
/**
* Configures the input and output instances based on the user arguments and options .
*
* @ param InputInterface $input An InputInterface instance
* @ param OutputInterface $output An OutputInterface instance
*/
protected function configureIO ( InputInterface $input , OutputInterface $output )
{
if ( true === $input -> hasParameterOption ( array ( '--ansi' ))) {
$output -> setDecorated ( true );
} elseif ( true === $input -> hasParameterOption ( array ( '--no-ansi' ))) {
$output -> setDecorated ( false );
}
if ( true === $input -> hasParameterOption ( array ( '--no-interaction' , '-n' ))) {
$input -> setInteractive ( false );
2013-06-30 19:29:16 +01:00
} elseif ( function_exists ( 'posix_isatty' ) && $this -> getHelperSet () -> has ( 'dialog' )) {
2013-05-09 09:57:19 +01:00
$inputStream = $this -> getHelperSet () -> get ( 'dialog' ) -> getInputStream ();
2013-09-06 19:20:34 +01:00
if ( !@ posix_isatty ( $inputStream )) {
2013-05-09 09:57:19 +01:00
$input -> setInteractive ( false );
}
}
if ( true === $input -> hasParameterOption ( array ( '--quiet' , '-q' ))) {
$output -> setVerbosity ( OutputInterface :: VERBOSITY_QUIET );
} else {
if ( $input -> hasParameterOption ( '-vvv' ) || $input -> hasParameterOption ( '--verbose=3' ) || $input -> getParameterOption ( '--verbose' ) === 3 ) {
$output -> setVerbosity ( OutputInterface :: VERBOSITY_DEBUG );
} elseif ( $input -> hasParameterOption ( '-vv' ) || $input -> hasParameterOption ( '--verbose=2' ) || $input -> getParameterOption ( '--verbose' ) === 2 ) {
$output -> setVerbosity ( OutputInterface :: VERBOSITY_VERY_VERBOSE );
} elseif ( $input -> hasParameterOption ( '-v' ) || $input -> hasParameterOption ( '--verbose=1' ) || $input -> hasParameterOption ( '--verbose' ) || $input -> getParameterOption ( '--verbose' )) {
$output -> setVerbosity ( OutputInterface :: VERBOSITY_VERBOSE );
}
}
}
2013-03-24 09:08:12 +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 .
*
* @ param Command $command A Command instance
* @ param InputInterface $input An Input instance
* @ param OutputInterface $output An Output instance
*
* @ return integer 0 if everything went fine , or an error code
*/
protected function doRunCommand ( Command $command , InputInterface $input , OutputInterface $output )
{
if ( null === $this -> dispatcher ) {
return $command -> run ( $input , $output );
}
$event = new ConsoleCommandEvent ( $command , $input , $output );
$this -> dispatcher -> dispatch ( ConsoleEvents :: COMMAND , $event );
try {
$exitCode = $command -> run ( $input , $output );
} catch ( \Exception $e ) {
$event = new ConsoleTerminateEvent ( $command , $input , $output , $e -> getCode ());
$this -> dispatcher -> dispatch ( ConsoleEvents :: TERMINATE , $event );
2013-05-27 11:36:30 +01:00
$event = new ConsoleExceptionEvent ( $command , $input , $output , $e , $event -> getExitCode ());
2013-03-24 09:08:12 +00:00
$this -> dispatcher -> dispatch ( ConsoleEvents :: EXCEPTION , $event );
throw $event -> getException ();
}
$event = new ConsoleTerminateEvent ( $command , $input , $output , $exitCode );
$this -> dispatcher -> dispatch ( ConsoleEvents :: TERMINATE , $event );
return $event -> getExitCode ();
}
2011-02-07 00:34:24 +00:00
/**
* Gets the name of the command based on input .
*
* @ param InputInterface $input The input interface
2011-04-15 20:12:02 +01:00
*
2011-02-07 00:34:24 +00:00
* @ return string The command name
*/
2010-07-01 13:31:45 +01:00
protected function getCommandName ( InputInterface $input )
{
2012-06-24 14:06:01 +01:00
return $input -> getFirstArgument ();
2010-07-01 13:31:45 +01:00
}
2011-10-25 16:11:49 +01: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.' ),
2013-04-25 11:15:38 +01:00
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' ),
2011-12-28 19:44:29 +00:00
new InputOption ( '--version' , '-V' , InputOption :: VALUE_NONE , 'Display this application version.' ),
2011-10-25 16:11:49 +01:00
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 .
*
2012-11-01 15:08:59 +00:00
* @ return Command [] An array of default Command instances
2011-10-25 16:11:49 +01:00
*/
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 DialogHelper (),
2012-09-29 21:11:59 +01:00
new ProgressHelper (),
2012-12-15 15:08:23 +00:00
new TableHelper (),
2011-10-25 16:11:49 +01:00
));
}
2012-04-24 17:59:33 +01:00
/**
* Runs and parses stty - a if it ' s available , suppressing any error output
*
* @ return string
*/
private function getSttyColumns ()
{
2012-05-21 11:40:20 +01:00
if ( ! function_exists ( 'proc_open' )) {
return ;
}
2012-04-24 17:59:33 +01:00
$descriptorspec = array ( 1 => array ( 'pipe' , 'w' ), 2 => array ( 'pipe' , 'w' ));
$process = proc_open ( 'stty -a | grep columns' , $descriptorspec , $pipes , null , null , array ( 'suppress_errors' => true ));
if ( is_resource ( $process )) {
$info = stream_get_contents ( $pipes [ 1 ]);
2012-10-15 16:06:38 +01:00
fclose ( $pipes [ 1 ]);
fclose ( $pipes [ 2 ]);
proc_close ( $process );
return $info ;
}
}
/**
* Runs and parses mode CON if it ' s available , suppressing any error output
*
2012-12-13 17:39:04 +00:00
* @ return string < width > x < height > or null if it could not be parsed
2012-10-15 16:06:38 +01:00
*/
private function getConsoleMode ()
{
if ( ! function_exists ( 'proc_open' )) {
return ;
}
$descriptorspec = array ( 1 => array ( 'pipe' , 'w' ), 2 => array ( 'pipe' , 'w' ));
$process = proc_open ( 'mode CON' , $descriptorspec , $pipes , null , null , array ( 'suppress_errors' => true ));
if ( is_resource ( $process )) {
$info = stream_get_contents ( $pipes [ 1 ]);
2012-04-24 17:59:33 +01:00
fclose ( $pipes [ 1 ]);
fclose ( $pipes [ 2 ]);
proc_close ( $process );
2013-01-05 17:54:53 +00:00
if ( preg_match ( '/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/' , $info , $matches )) {
2012-12-13 17:39:04 +00:00
return $matches [ 2 ] . 'x' . $matches [ 1 ];
}
2012-04-24 17:59:33 +01:00
}
}
2011-02-07 00:34:24 +00:00
/**
* Returns abbreviated suggestions in string format .
*
* @ param array $abbrevs Abbreviated suggestions to convert
*
* @ return string A formatted string of abbreviated suggestions
*/
2011-03-11 11:53:42 +00:00
private function getAbbreviationSuggestions ( $abbrevs )
2010-01-04 14:42:28 +00:00
{
2010-05-06 12:25:53 +01:00
return sprintf ( '%s, %s%s' , $abbrevs [ 0 ], $abbrevs [ 1 ], count ( $abbrevs ) > 2 ? sprintf ( ' and %d more' , count ( $abbrevs ) - 2 ) : '' );
2010-01-04 14:42:28 +00:00
}
2011-06-07 16:51:43 +01:00
2011-12-28 09:22:28 +00:00
/**
* Returns the namespace part of the command name .
*
2013-03-22 13:40:47 +00:00
* This method is not part of public API and should not be used directly .
*
2011-12-28 09:22:28 +00:00
* @ 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
*/
2013-03-22 13:40:47 +00:00
public function extractNamespace ( $name , $limit = null )
2011-06-07 16:51:43 +01:00
{
2011-06-07 17:14:15 +01:00
$parts = explode ( ':' , $name );
array_pop ( $parts );
2011-06-07 16:51:43 +01:00
2011-06-07 17:14:15 +01:00
return implode ( ':' , null === $limit ? $parts : array_slice ( $parts , 0 , $limit ));
2011-06-07 16:51:43 +01:00
}
2012-02-11 01:58:39 +00:00
/**
* Finds alternative commands of $name
*
2012-05-15 21:19:31 +01:00
* @ param string $name The full name of the command
* @ param array $abbrevs The abbreviations
2012-02-11 19:38:08 +00:00
*
2012-02-11 01:58:39 +00:00
* @ return array A sorted array of similar commands
*/
2012-02-12 16:53:56 +00:00
private function findAlternativeCommands ( $name , $abbrevs )
2012-02-11 01:58:39 +00:00
{
2012-02-12 16:53:56 +00:00
$callback = function ( $item ) {
return $item -> getName ();
2012-02-11 19:38:08 +00:00
};
2012-02-12 16:53:56 +00:00
return $this -> findAlternatives ( $name , $this -> commands , $abbrevs , $callback );
2012-02-11 19:38:08 +00:00
}
/**
* Finds alternative namespace of $name
*
2012-05-15 21:19:31 +01:00
* @ param string $name The full name of the namespace
* @ param array $abbrevs The abbreviations
2012-02-11 19:38:08 +00:00
*
* @ return array A sorted array of similar namespace
*/
2012-02-12 16:53:56 +00:00
private function findAlternativeNamespace ( $name , $abbrevs )
2012-02-11 19:38:08 +00:00
{
2012-02-12 16:53:56 +00:00
return $this -> findAlternatives ( $name , $this -> getNamespaces (), $abbrevs );
2012-02-11 19:38:08 +00:00
}
/**
2012-02-12 16:53:56 +00:00
* Finds alternative of $name among $collection ,
* if nothing is found in $collection , try in $abbrevs
2012-02-11 19:38:08 +00:00
*
2012-05-15 21:19:31 +01:00
* @ param string $name The string
2012-07-28 23:02:29 +01:00
* @ param array | Traversable $collection The collection
2012-05-15 21:19:31 +01:00
* @ param array $abbrevs The abbreviations
* @ param Closure | string | array $callback The callable to transform collection item before comparison
2012-02-11 19:38:08 +00:00
*
* @ return array A sorted array of similar string
*/
2012-05-21 15:06:09 +01:00
private function findAlternatives ( $name , $collection , $abbrevs , $callback = null )
{
2012-02-11 01:58:39 +00:00
$alternatives = array ();
2012-02-11 19:38:08 +00:00
foreach ( $collection as $item ) {
2012-02-12 23:29:28 +00:00
if ( null !== $callback ) {
2012-02-11 19:38:08 +00:00
$item = call_user_func ( $callback , $item );
}
$lev = levenshtein ( $name , $item );
if ( $lev <= strlen ( $name ) / 3 || false !== strpos ( $item , $name )) {
$alternatives [ $item ] = $lev ;
2012-02-11 01:58:39 +00:00
}
}
2012-02-12 16:53:56 +00:00
if ( ! $alternatives ) {
foreach ( $abbrevs as $key => $values ) {
$lev = levenshtein ( $name , $key );
if ( $lev <= strlen ( $name ) / 3 || false !== strpos ( $key , $name )) {
foreach ( $values as $value ) {
$alternatives [ $value ] = $lev ;
}
}
}
}
2012-02-11 01:58:39 +00:00
asort ( $alternatives );
return array_keys ( $alternatives );
}
2010-01-04 14:42:28 +00:00
}