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\Descriptor ;
use Symfony\Component\Console\Application ;
use Symfony\Component\Console\Command\Command ;
2017-02-02 16:28:38 -08:00
use Symfony\Component\Console\Formatter\OutputFormatter ;
use Symfony\Component\Console\Helper\Helper ;
2015-08-17 17:00:26 -07:00
use Symfony\Component\Console\Input\InputArgument ;
use Symfony\Component\Console\Input\InputDefinition ;
use Symfony\Component\Console\Input\InputOption ;
/**
* Text descriptor .
*
* @ author Jean - François Simon < contact @ jfsimon . fr >
*
* @ internal
*/
class TextDescriptor extends Descriptor
{
/**
* { @ inheritdoc }
*/
protected function describeInputArgument ( InputArgument $argument , array $options = array ())
{
2018-11-23 12:29:20 +00:00
if ( null !== $argument -> getDefault () && ( ! \is_array ( $argument -> getDefault ()) || \count ( $argument -> getDefault ()))) {
2015-08-17 17:00:26 -07:00
$default = sprintf ( '<comment> [default: %s]</comment>' , $this -> formatDefaultValue ( $argument -> getDefault ()));
} else {
$default = '' ;
}
2017-02-02 16:28:38 -08:00
$totalWidth = isset ( $options [ 'total_width' ]) ? $options [ 'total_width' ] : Helper :: strlen ( $argument -> getName ());
2018-11-23 12:29:20 +00:00
$spacingWidth = $totalWidth - \strlen ( $argument -> getName ());
2015-08-17 17:00:26 -07:00
2017-02-02 16:28:38 -08:00
$this -> writeText ( sprintf ( ' <info>%s</info> %s%s%s' ,
2015-08-17 17:00:26 -07:00
$argument -> getName (),
str_repeat ( ' ' , $spacingWidth ),
2017-02-02 16:28:38 -08:00
// + 4 = 2 spaces before <info>, 2 spaces after </info>
preg_replace ( '/\s*[\r\n]\s*/' , " \n " . str_repeat ( ' ' , $totalWidth + 4 ), $argument -> getDescription ()),
2015-08-17 17:00:26 -07:00
$default
), $options );
}
/**
* { @ inheritdoc }
*/
protected function describeInputOption ( InputOption $option , array $options = array ())
{
2018-11-23 12:29:20 +00:00
if ( $option -> acceptValue () && null !== $option -> getDefault () && ( ! \is_array ( $option -> getDefault ()) || \count ( $option -> getDefault ()))) {
2015-08-17 17:00:26 -07:00
$default = sprintf ( '<comment> [default: %s]</comment>' , $this -> formatDefaultValue ( $option -> getDefault ()));
} else {
$default = '' ;
}
$value = '' ;
if ( $option -> acceptValue ()) {
$value = '=' . strtoupper ( $option -> getName ());
if ( $option -> isValueOptional ()) {
$value = '[' . $value . ']' ;
}
}
$totalWidth = isset ( $options [ 'total_width' ]) ? $options [ 'total_width' ] : $this -> calculateTotalWidthForOptions ( array ( $option ));
$synopsis = sprintf ( '%s%s' ,
$option -> getShortcut () ? sprintf ( '-%s, ' , $option -> getShortcut ()) : ' ' ,
sprintf ( '--%s%s' , $option -> getName (), $value )
);
2017-02-02 16:28:38 -08:00
$spacingWidth = $totalWidth - Helper :: strlen ( $synopsis );
2015-08-17 17:00:26 -07:00
2017-02-02 16:28:38 -08:00
$this -> writeText ( sprintf ( ' <info>%s</info> %s%s%s%s' ,
2015-08-17 17:00:26 -07:00
$synopsis ,
str_repeat ( ' ' , $spacingWidth ),
2017-02-02 16:28:38 -08:00
// + 4 = 2 spaces before <info>, 2 spaces after </info>
preg_replace ( '/\s*[\r\n]\s*/' , " \n " . str_repeat ( ' ' , $totalWidth + 4 ), $option -> getDescription ()),
2015-08-17 17:00:26 -07:00
$default ,
$option -> isArray () ? '<comment> (multiple values allowed)</comment>' : ''
), $options );
}
/**
* { @ inheritdoc }
*/
protected function describeInputDefinition ( InputDefinition $definition , array $options = array ())
{
$totalWidth = $this -> calculateTotalWidthForOptions ( $definition -> getOptions ());
foreach ( $definition -> getArguments () as $argument ) {
2017-02-02 16:28:38 -08:00
$totalWidth = max ( $totalWidth , Helper :: strlen ( $argument -> getName ()));
2015-08-17 17:00:26 -07:00
}
if ( $definition -> getArguments ()) {
$this -> writeText ( '<comment>Arguments:</comment>' , $options );
$this -> writeText ( " \n " );
foreach ( $definition -> getArguments () as $argument ) {
$this -> describeInputArgument ( $argument , array_merge ( $options , array ( 'total_width' => $totalWidth )));
$this -> writeText ( " \n " );
}
}
if ( $definition -> getArguments () && $definition -> getOptions ()) {
$this -> writeText ( " \n " );
}
if ( $definition -> getOptions ()) {
$laterOptions = array ();
$this -> writeText ( '<comment>Options:</comment>' , $options );
foreach ( $definition -> getOptions () as $option ) {
2018-11-23 12:29:20 +00:00
if ( \strlen ( $option -> getShortcut ()) > 1 ) {
2015-08-17 17:00:26 -07:00
$laterOptions [] = $option ;
continue ;
}
$this -> writeText ( " \n " );
$this -> describeInputOption ( $option , array_merge ( $options , array ( 'total_width' => $totalWidth )));
}
foreach ( $laterOptions as $option ) {
$this -> writeText ( " \n " );
$this -> describeInputOption ( $option , array_merge ( $options , array ( 'total_width' => $totalWidth )));
}
}
}
/**
* { @ inheritdoc }
*/
protected function describeCommand ( Command $command , array $options = array ())
{
$command -> getSynopsis ( true );
$command -> getSynopsis ( false );
$command -> mergeApplicationDefinition ( false );
$this -> writeText ( '<comment>Usage:</comment>' , $options );
foreach ( array_merge ( array ( $command -> getSynopsis ( true )), $command -> getAliases (), $command -> getUsages ()) as $usage ) {
$this -> writeText ( " \n " );
2018-11-23 12:29:20 +00:00
$this -> writeText ( ' ' . OutputFormatter :: escape ( $usage ), $options );
2015-08-17 17:00:26 -07:00
}
$this -> writeText ( " \n " );
$definition = $command -> getNativeDefinition ();
if ( $definition -> getOptions () || $definition -> getArguments ()) {
$this -> writeText ( " \n " );
$this -> describeInputDefinition ( $definition , $options );
$this -> writeText ( " \n " );
}
if ( $help = $command -> getProcessedHelp ()) {
$this -> writeText ( " \n " );
$this -> writeText ( '<comment>Help:</comment>' , $options );
$this -> writeText ( " \n " );
2017-02-02 16:28:38 -08:00
$this -> writeText ( ' ' . str_replace ( " \n " , " \n " , $help ), $options );
2015-08-17 17:00:26 -07:00
$this -> writeText ( " \n " );
}
}
/**
* { @ inheritdoc }
*/
protected function describeApplication ( Application $application , array $options = array ())
{
$describedNamespace = isset ( $options [ 'namespace' ]) ? $options [ 'namespace' ] : null ;
$description = new ApplicationDescription ( $application , $describedNamespace );
if ( isset ( $options [ 'raw_text' ]) && $options [ 'raw_text' ]) {
$width = $this -> getColumnWidth ( $description -> getCommands ());
foreach ( $description -> getCommands () as $command ) {
2016-04-20 09:56:34 -07:00
$this -> writeText ( sprintf ( " %- { $width } s %s " , $command -> getName (), $command -> getDescription ()), $options );
2015-08-17 17:00:26 -07:00
$this -> writeText ( " \n " );
}
} else {
if ( '' != $help = $application -> getHelp ()) {
$this -> writeText ( " $help\n\n " , $options );
}
$this -> writeText ( " <comment>Usage:</comment> \n " , $options );
$this -> writeText ( " command [options] [arguments] \n \n " , $options );
$this -> describeInputDefinition ( new InputDefinition ( $application -> getDefinition () -> getOptions ()), $options );
$this -> writeText ( " \n " );
$this -> writeText ( " \n " );
2018-11-23 12:29:20 +00:00
$commands = $description -> getCommands ();
$namespaces = $description -> getNamespaces ();
if ( $describedNamespace && $namespaces ) {
// make sure all alias commands are included when describing a specific namespace
$describedNamespaceInfo = reset ( $namespaces );
foreach ( $describedNamespaceInfo [ 'commands' ] as $name ) {
$commands [ $name ] = $description -> getCommand ( $name );
}
}
// calculate max. width based on available commands per namespace
$width = $this -> getColumnWidth ( \call_user_func_array ( 'array_merge' , array_map ( function ( $namespace ) use ( $commands ) {
return array_intersect ( $namespace [ 'commands' ], array_keys ( $commands ));
}, $namespaces )));
2015-08-17 17:00:26 -07:00
if ( $describedNamespace ) {
$this -> writeText ( sprintf ( '<comment>Available commands for the "%s" namespace:</comment>' , $describedNamespace ), $options );
} else {
$this -> writeText ( '<comment>Available commands:</comment>' , $options );
}
2018-11-23 12:29:20 +00:00
foreach ( $namespaces as $namespace ) {
$namespace [ 'commands' ] = array_filter ( $namespace [ 'commands' ], function ( $name ) use ( $commands ) {
return isset ( $commands [ $name ]);
});
if ( ! $namespace [ 'commands' ]) {
continue ;
}
2015-08-17 17:00:26 -07:00
if ( ! $describedNamespace && ApplicationDescription :: GLOBAL_NAMESPACE !== $namespace [ 'id' ]) {
$this -> writeText ( " \n " );
$this -> writeText ( ' <comment>' . $namespace [ 'id' ] . '</comment>' , $options );
}
foreach ( $namespace [ 'commands' ] as $name ) {
$this -> writeText ( " \n " );
2017-02-02 16:28:38 -08:00
$spacingWidth = $width - Helper :: strlen ( $name );
2018-11-23 12:29:20 +00:00
$command = $commands [ $name ];
$commandAliases = $name === $command -> getName () ? $this -> getCommandAliasesText ( $command ) : '' ;
$this -> writeText ( sprintf ( ' <info>%s</info>%s%s' , $name , str_repeat ( ' ' , $spacingWidth ), $commandAliases . $command -> getDescription ()), $options );
2015-08-17 17:00:26 -07:00
}
}
$this -> writeText ( " \n " );
}
}
/**
* { @ inheritdoc }
*/
private function writeText ( $content , array $options = array ())
{
$this -> write (
isset ( $options [ 'raw_text' ]) && $options [ 'raw_text' ] ? strip_tags ( $content ) : $content ,
isset ( $options [ 'raw_output' ]) ? ! $options [ 'raw_output' ] : true
);
}
2018-11-23 12:29:20 +00:00
/**
* Formats command aliases to show them in the command description .
*
* @ return string
*/
private function getCommandAliasesText ( Command $command )
{
$text = '' ;
$aliases = $command -> getAliases ();
if ( $aliases ) {
$text = '[' . implode ( '|' , $aliases ) . '] ' ;
}
return $text ;
}
2015-08-17 17:00:26 -07:00
/**
* Formats input option / argument default value .
*
* @ param mixed $default
*
* @ return string
*/
private function formatDefaultValue ( $default )
{
2018-11-23 12:29:20 +00:00
if ( INF === $default ) {
return 'INF' ;
}
if ( \is_string ( $default )) {
2017-02-02 16:28:38 -08:00
$default = OutputFormatter :: escape ( $default );
2018-11-23 12:29:20 +00:00
} elseif ( \is_array ( $default )) {
2017-02-02 16:28:38 -08:00
foreach ( $default as $key => $value ) {
2018-11-23 12:29:20 +00:00
if ( \is_string ( $value )) {
2017-02-02 16:28:38 -08:00
$default [ $key ] = OutputFormatter :: escape ( $value );
}
}
}
2016-04-20 09:56:34 -07:00
return str_replace ( '\\\\' , '\\' , json_encode ( $default , JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ));
2015-08-17 17:00:26 -07:00
}
/**
2018-11-23 12:29:20 +00:00
* @ param ( Command | string )[] $commands
2015-08-17 17:00:26 -07:00
*
* @ return int
*/
private function getColumnWidth ( array $commands )
{
2015-10-08 11:40:12 -07:00
$widths = array ();
2015-08-17 17:00:26 -07:00
foreach ( $commands as $command ) {
2018-11-23 12:29:20 +00:00
if ( $command instanceof Command ) {
$widths [] = Helper :: strlen ( $command -> getName ());
foreach ( $command -> getAliases () as $alias ) {
$widths [] = Helper :: strlen ( $alias );
}
} else {
$widths [] = Helper :: strlen ( $command );
2015-10-08 11:40:12 -07:00
}
2015-08-17 17:00:26 -07:00
}
2018-11-23 12:29:20 +00:00
return $widths ? max ( $widths ) + 2 : 0 ;
2015-08-17 17:00:26 -07:00
}
/**
* @ param InputOption [] $options
*
* @ return int
*/
2018-11-23 12:29:20 +00:00
private function calculateTotalWidthForOptions ( array $options )
2015-08-17 17:00:26 -07:00
{
$totalWidth = 0 ;
foreach ( $options as $option ) {
2015-08-27 12:03:05 -07:00
// "-" + shortcut + ", --" + name
2018-11-23 12:29:20 +00:00
$nameLength = 1 + max ( Helper :: strlen ( $option -> getShortcut ()), 1 ) + 4 + Helper :: strlen ( $option -> getName ());
2015-08-17 17:00:26 -07:00
if ( $option -> acceptValue ()) {
2017-02-02 16:28:38 -08:00
$valueLength = 1 + Helper :: strlen ( $option -> getName ()); // = + value
2015-08-17 17:00:26 -07:00
$valueLength += $option -> isValueOptional () ? 2 : 0 ; // [ + ]
$nameLength += $valueLength ;
}
$totalWidth = max ( $totalWidth , $nameLength );
}
return $totalWidth ;
}
}