update v 1.0.7.5

This commit is contained in:
Sujit Prasad
2016-06-13 20:41:55 +05:30
parent aa9786d829
commit 283d97e3ea
5078 changed files with 339851 additions and 175995 deletions

View File

@@ -11,8 +11,7 @@
namespace Symfony\Component\Console;
use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Helper\DebugFormatterHelper;
use Symfony\Component\Console\Helper\ProcessHelper;
use Symfony\Component\Console\Helper\QuestionHelper;
@@ -23,7 +22,6 @@ use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputAwareInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
@@ -32,12 +30,11 @@ 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;
use Symfony\Component\Console\Helper\ProgressHelper;
use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
@@ -54,8 +51,6 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
* $app->run();
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class Application
{
@@ -77,8 +72,6 @@ class Application
*
* @param string $name The name of the application
* @param string $version The version of the application
*
* @api
*/
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
{
@@ -107,8 +100,6 @@ class Application
* @return int 0 if everything went fine, or an error code
*
* @throws \Exception When doRun returns Exception
*
* @api
*/
public function run(InputInterface $input = null, OutputInterface $output = null)
{
@@ -167,14 +158,14 @@ class Application
*/
public function doRun(InputInterface $input, OutputInterface $output)
{
if (true === $input->hasParameterOption(array('--version', '-V'))) {
if (true === $input->hasParameterOption(array('--version', '-V'), true)) {
$output->writeln($this->getLongVersion());
return 0;
}
$name = $this->getCommandName($input);
if (true === $input->hasParameterOption(array('--help', '-h'))) {
if (true === $input->hasParameterOption(array('--help', '-h'), true)) {
if (!$name) {
$name = 'help';
$input = new ArrayInput(array('command' => 'help'));
@@ -202,8 +193,6 @@ class Application
* Set a helper set to be used with the command.
*
* @param HelperSet $helperSet The helper set
*
* @api
*/
public function setHelperSet(HelperSet $helperSet)
{
@@ -214,8 +203,6 @@ class Application
* Get the helper set associated with the command.
*
* @return HelperSet The HelperSet instance associated with this command
*
* @api
*/
public function getHelperSet()
{
@@ -226,8 +213,6 @@ class Application
* Set an input definition set to be used with this application.
*
* @param InputDefinition $definition The input definition
*
* @api
*/
public function setDefinition(InputDefinition $definition)
{
@@ -258,8 +243,6 @@ class Application
* Sets whether to catch exceptions or not during commands execution.
*
* @param bool $boolean Whether to catch exceptions or not during commands execution
*
* @api
*/
public function setCatchExceptions($boolean)
{
@@ -270,8 +253,6 @@ class Application
* Sets whether to automatically exit after a command execution or not.
*
* @param bool $boolean Whether to automatically exit after a command execution or not
*
* @api
*/
public function setAutoExit($boolean)
{
@@ -282,8 +263,6 @@ class Application
* Gets the name of the application.
*
* @return string The application name
*
* @api
*/
public function getName()
{
@@ -294,8 +273,6 @@ class Application
* Sets the application name.
*
* @param string $name The application name
*
* @api
*/
public function setName($name)
{
@@ -306,8 +283,6 @@ class Application
* Gets the application version.
*
* @return string The application version
*
* @api
*/
public function getVersion()
{
@@ -318,8 +293,6 @@ class Application
* Sets the application version.
*
* @param string $version The application version
*
* @api
*/
public function setVersion($version)
{
@@ -330,13 +303,15 @@ class Application
* Returns the long version of the application.
*
* @return string The long application version
*
* @api
*/
public function getLongVersion()
{
if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
if ('UNKNOWN' !== $this->getName()) {
if ('UNKNOWN' !== $this->getVersion()) {
return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
}
return sprintf('<info>%s</info>', $this->getName());
}
return '<info>Console Tool</info>';
@@ -348,8 +323,6 @@ class Application
* @param string $name The command name
*
* @return Command The newly created command
*
* @api
*/
public function register($name)
{
@@ -360,8 +333,6 @@ class Application
* Adds an array of command objects.
*
* @param Command[] $commands An array of commands
*
* @api
*/
public function addCommands(array $commands)
{
@@ -378,8 +349,6 @@ class Application
* @param Command $command A Command object
*
* @return Command The registered command
*
* @api
*/
public function add(Command $command)
{
@@ -392,7 +361,7 @@ class Application
}
if (null === $command->getDefinition()) {
throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
}
$this->commands[$command->getName()] = $command;
@@ -411,14 +380,12 @@ class Application
*
* @return Command A Command object
*
* @throws \InvalidArgumentException When command name given does not exist
*
* @api
* @throws CommandNotFoundException When command name given does not exist
*/
public function get($name)
{
if (!isset($this->commands[$name])) {
throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
}
$command = $this->commands[$name];
@@ -441,8 +408,6 @@ class Application
* @param string $name The command name or alias
*
* @return bool true if the command exists, false otherwise
*
* @api
*/
public function has($name)
{
@@ -459,7 +424,7 @@ class Application
public function getNamespaces()
{
$namespaces = array();
foreach ($this->commands as $command) {
foreach ($this->all() as $command) {
$namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
foreach ($command->getAliases() as $alias) {
@@ -477,7 +442,7 @@ class Application
*
* @return string A registered namespace
*
* @throws \InvalidArgumentException When namespace is incorrect or ambiguous
* @throws CommandNotFoundException When namespace is incorrect or ambiguous
*/
public function findNamespace($namespace)
{
@@ -498,12 +463,12 @@ class Application
$message .= implode("\n ", $alternatives);
}
throw new \InvalidArgumentException($message);
throw new CommandNotFoundException($message, $alternatives);
}
$exact = in_array($namespace, $namespaces, true);
if (count($namespaces) > 1 && !$exact) {
throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))));
throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
}
return $exact ? $namespace : reset($namespaces);
@@ -519,9 +484,7 @@ class Application
*
* @return Command A Command instance
*
* @throws \InvalidArgumentException When command name is incorrect or ambiguous
*
* @api
* @throws CommandNotFoundException When command name is incorrect or ambiguous
*/
public function find($name)
{
@@ -546,7 +509,7 @@ class Application
$message .= implode("\n ", $alternatives);
}
throw new \InvalidArgumentException($message);
throw new CommandNotFoundException($message, $alternatives);
}
// filter out aliases for commands which are already on the list
@@ -563,7 +526,7 @@ class Application
if (count($commands) > 1 && !$exact) {
$suggestions = $this->getAbbreviationSuggestions(array_values($commands));
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
}
return $this->get($exact ? $name : reset($commands));
@@ -577,8 +540,6 @@ class Application
* @param string $namespace A namespace name
*
* @return Command[] An array of Command instances
*
* @api
*/
public function all($namespace = null)
{
@@ -616,57 +577,16 @@ class Application
return $abbrevs;
}
/**
* Returns a text representation of the Application.
*
* @param string $namespace An optional namespace name
* @param bool $raw Whether to return raw command list
*
* @return string A string representing the Application
*
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asText($namespace = null, $raw = false)
{
$descriptor = new TextDescriptor();
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
$descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
return $output->fetch();
}
/**
* Returns an XML representation of the Application.
*
* @param string $namespace An optional namespace name
* @param bool $asDom Whether to return a DOM or an XML string
*
* @return string|\DOMDocument An XML string representing the Application
*
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asXml($namespace = null, $asDom = false)
{
$descriptor = new XmlDescriptor();
if ($asDom) {
return $descriptor->getApplicationDocument($this, $namespace);
}
$output = new BufferedOutput();
$descriptor->describe($output, $this, array('namespace' => $namespace));
return $output->fetch();
}
/**
* Renders a caught exception.
*
* @param \Exception $e An exception instance
* @param OutputInterface $output An OutputInterface instance
*/
public function renderException($e, $output)
public function renderException(\Exception $e, OutputInterface $output)
{
$output->writeln('', OutputInterface::VERBOSITY_QUIET);
do {
$title = sprintf(' [%s] ', get_class($e));
@@ -689,7 +609,7 @@ class Application
}
}
$messages = array('', '');
$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 - $this->stringWidth($title)))));
foreach ($lines as $line) {
@@ -697,12 +617,11 @@ class Application
}
$messages[] = $emptyLine;
$messages[] = '';
$messages[] = '';
$output->writeln($messages, OutputInterface::OUTPUT_RAW);
$output->writeln($messages, OutputInterface::OUTPUT_RAW | OutputInterface::VERBOSITY_QUIET);
if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
$output->writeln('<comment>Exception trace:</comment>');
$output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
// exception related properties
$trace = $e->getTrace();
@@ -720,18 +639,16 @@ class Application
$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));
$output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
}
$output->writeln('');
$output->writeln('');
$output->writeln('', OutputInterface::VERBOSITY_QUIET);
}
} while ($e = $e->getPrevious());
if (null !== $this->runningCommand) {
$output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
$output->writeln('');
$output->writeln('');
$output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
$output->writeln('', OutputInterface::VERBOSITY_QUIET);
}
}
@@ -820,13 +737,13 @@ class Application
*/
protected function configureIO(InputInterface $input, OutputInterface $output)
{
if (true === $input->hasParameterOption(array('--ansi'))) {
if (true === $input->hasParameterOption(array('--ansi'), true)) {
$output->setDecorated(true);
} elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
} elseif (true === $input->hasParameterOption(array('--no-ansi'), true)) {
$output->setDecorated(false);
}
if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
if (true === $input->hasParameterOption(array('--no-interaction', '-n'), true)) {
$input->setInteractive(false);
} elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
$inputStream = $this->getHelperSet()->get('question')->getInputStream();
@@ -835,14 +752,14 @@ class Application
}
}
if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
if (true === $input->hasParameterOption(array('--quiet', '-q'), true)) {
$output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
} else {
if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || $input->getParameterOption('--verbose', false, true) === 3) {
$output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
} elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
} elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || $input->getParameterOption('--verbose', false, true) === 2) {
$output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
} elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
} elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) {
$output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
}
}
@@ -874,6 +791,14 @@ class Application
return $command->run($input, $output);
}
// 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
}
$event = new ConsoleCommandEvent($command, $input, $output);
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
@@ -881,13 +806,15 @@ class Application
try {
$exitCode = $command->run($input, $output);
} catch (\Exception $e) {
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode());
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
$e = $event->getException();
$event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
throw $event->getException();
throw $e;
}
} else {
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
@@ -950,9 +877,6 @@ class Application
{
return new HelperSet(array(
new FormatterHelper(),
new DialogHelper(),
new ProgressHelper(),
new TableHelper(),
new DebugFormatterHelper(),
new ProcessHelper(),
new QuestionHelper(),
@@ -1100,11 +1024,7 @@ class Application
private function stringWidth($string)
{
if (!function_exists('mb_strwidth')) {
return strlen($string);
}
if (false === $encoding = mb_detect_encoding($string)) {
if (false === $encoding = mb_detect_encoding($string, null, true)) {
return strlen($string);
}
@@ -1116,12 +1036,7 @@ class Application
// 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
if (!function_exists('mb_strwidth')) {
return str_split($string, $width);
}
if (false === $encoding = mb_detect_encoding($string)) {
if (false === $encoding = mb_detect_encoding($string, null, true)) {
return str_split($string, $width);
}

View File

@@ -1,6 +1,17 @@
CHANGELOG
=========
2.8.3
-----
* remove readline support from the question helper as it caused issues
2.8.0
-----
* use readline for user input in the question helper when available to allow
the use of arrow keys
2.6.0
-----

View File

@@ -11,23 +11,21 @@
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
/**
* Base class for all commands.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class Command
{
@@ -42,7 +40,8 @@ class Command
private $applicationDefinitionMerged = false;
private $applicationDefinitionMergedWithArgs = false;
private $code;
private $synopsis;
private $synopsis = array();
private $usages = array();
private $helperSet;
/**
@@ -50,9 +49,7 @@ class Command
*
* @param string|null $name The name of the command; passing null means it must be set in configure()
*
* @throws \LogicException When the command name is empty
*
* @api
* @throws LogicException When the command name is empty
*/
public function __construct($name = null)
{
@@ -65,7 +62,7 @@ class Command
$this->configure();
if (!$this->name) {
throw new \LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
}
}
@@ -83,8 +80,6 @@ class Command
* Sets the application instance for this command.
*
* @param Application $application An Application instance
*
* @api
*/
public function setApplication(Application $application = null)
{
@@ -120,8 +115,6 @@ class Command
* Gets the application instance for this command.
*
* @return Application An Application instance
*
* @api
*/
public function getApplication()
{
@@ -161,13 +154,13 @@ class Command
*
* @return null|int null or 0 if everything went fine, or an error code
*
* @throws \LogicException When this abstract method is not implemented
* @throws LogicException When this abstract method is not implemented
*
* @see setCode()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
throw new \LogicException('You must override the execute() method in the concrete command class.');
throw new LogicException('You must override the execute() method in the concrete command class.');
}
/**
@@ -213,13 +206,12 @@ class Command
*
* @see setCode()
* @see execute()
*
* @api
*/
public function run(InputInterface $input, OutputInterface $output)
{
// force the creation of the synopsis before the merge with the app definition
$this->getSynopsis();
$this->getSynopsis(true);
$this->getSynopsis(false);
// add the application arguments and options
$this->mergeApplicationDefinition();
@@ -227,7 +219,7 @@ class Command
// bind the input against the command specific arguments/options
try {
$input->bind($this->definition);
} catch (\Exception $e) {
} catch (ExceptionInterface $e) {
if (!$this->ignoreValidationErrors) {
throw $e;
}
@@ -249,6 +241,13 @@ class Command
$this->interact($input, $output);
}
// The command name argument is often omitted when a command is executed directly with its run() method.
// It would fail the validation if we didn't make sure the command argument is present,
// since it's required by the application.
if ($input->hasArgument('command') && null === $input->getArgument('command')) {
$input->setArgument('command', $this->getName());
}
$input->validate();
if ($this->code) {
@@ -270,16 +269,17 @@ class Command
*
* @return Command The current instance
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*
* @see execute()
*
* @api
*/
public function setCode($code)
public function setCode(callable $code)
{
if (!is_callable($code)) {
throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.');
if ($code instanceof \Closure) {
$r = new \ReflectionFunction($code);
if (null === $r->getClosureThis()) {
$code = \Closure::bind($code, $this);
}
}
$this->code = $code;
@@ -300,14 +300,14 @@ class Command
return;
}
$this->definition->addOptions($this->application->getDefinition()->getOptions());
if ($mergeArgs) {
$currentArguments = $this->definition->getArguments();
$this->definition->setArguments($this->application->getDefinition()->getArguments());
$this->definition->addArguments($currentArguments);
}
$this->definition->addOptions($this->application->getDefinition()->getOptions());
$this->applicationDefinitionMerged = true;
if ($mergeArgs) {
$this->applicationDefinitionMergedWithArgs = true;
@@ -320,8 +320,6 @@ class Command
* @param array|InputDefinition $definition An array of argument and option instances or a definition instance
*
* @return Command The current instance
*
* @api
*/
public function setDefinition($definition)
{
@@ -340,8 +338,6 @@ class Command
* Gets the InputDefinition attached to this Command.
*
* @return InputDefinition An InputDefinition instance
*
* @api
*/
public function getDefinition()
{
@@ -349,7 +345,7 @@ class Command
}
/**
* Gets the InputDefinition to be used to create XML and Text representations of this Command.
* Gets the InputDefinition to be used to create representations of this Command.
*
* Can be overridden to provide the original command representation when it would otherwise
* be changed by merging with the application InputDefinition.
@@ -372,8 +368,6 @@ class Command
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
*
* @return Command The current instance
*
* @api
*/
public function addArgument($name, $mode = null, $description = '', $default = null)
{
@@ -389,11 +383,9 @@ class Command
* @param string $shortcut The shortcut (can be null)
* @param int $mode The option mode: One of the InputOption::VALUE_* constants
* @param string $description A description text
* @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE)
* @param mixed $default The default value (must be null for InputOption::VALUE_NONE)
*
* @return Command The current instance
*
* @api
*/
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
{
@@ -414,9 +406,7 @@ class Command
*
* @return Command The current instance
*
* @throws \InvalidArgumentException When the name is invalid
*
* @api
* @throws InvalidArgumentException When the name is invalid
*/
public function setName($name)
{
@@ -450,8 +440,6 @@ class Command
* Returns the command name.
*
* @return string The command name
*
* @api
*/
public function getName()
{
@@ -464,8 +452,6 @@ class Command
* @param string $description The description for the command
*
* @return Command The current instance
*
* @api
*/
public function setDescription($description)
{
@@ -478,8 +464,6 @@ class Command
* Returns the description for the command.
*
* @return string The description for the command
*
* @api
*/
public function getDescription()
{
@@ -492,8 +476,6 @@ class Command
* @param string $help The help for the command
*
* @return Command The current instance
*
* @api
*/
public function setHelp($help)
{
@@ -506,8 +488,6 @@ class Command
* Returns the help for the command.
*
* @return string The help for the command
*
* @api
*/
public function getHelp()
{
@@ -533,7 +513,7 @@ class Command
$_SERVER['PHP_SELF'].' '.$name,
);
return str_replace($placeholders, $replacements, $this->getHelp());
return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
}
/**
@@ -543,14 +523,12 @@ class Command
*
* @return Command The current instance
*
* @throws \InvalidArgumentException When an alias is invalid
*
* @api
* @throws InvalidArgumentException When an alias is invalid
*/
public function setAliases($aliases)
{
if (!is_array($aliases) && !$aliases instanceof \Traversable) {
throw new \InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
}
foreach ($aliases as $alias) {
@@ -566,8 +544,6 @@ class Command
* Returns the aliases for the command.
*
* @return array An array of aliases for the command
*
* @api
*/
public function getAliases()
{
@@ -577,15 +553,45 @@ class Command
/**
* Returns the synopsis for the command.
*
* @param bool $short Whether to show the short version of the synopsis (with options folded) or not
*
* @return string The synopsis
*/
public function getSynopsis()
public function getSynopsis($short = false)
{
if (null === $this->synopsis) {
$this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis()));
$key = $short ? 'short' : 'long';
if (!isset($this->synopsis[$key])) {
$this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
}
return $this->synopsis;
return $this->synopsis[$key];
}
/**
* Add a command usage example.
*
* @param string $usage The usage, it'll be prefixed with the command name
*/
public function addUsage($usage)
{
if (0 !== strpos($usage, $this->name)) {
$usage = sprintf('%s %s', $this->name, $usage);
}
$this->usages[] = $usage;
return $this;
}
/**
* Returns alternative usages of the command.
*
* @return array
*/
public function getUsages()
{
return $this->usages;
}
/**
@@ -595,52 +601,16 @@ class Command
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
*
* @api
* @throws LogicException if no HelperSet is defined
* @throws InvalidArgumentException if the helper is not defined
*/
public function getHelper($name)
{
return $this->helperSet->get($name);
}
/**
* Returns a text representation of the command.
*
* @return string A string representing the command
*
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asText()
{
$descriptor = new TextDescriptor();
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
$descriptor->describe($output, $this, array('raw_output' => true));
return $output->fetch();
}
/**
* Returns an XML representation of the command.
*
* @param bool $asDom Whether to return a DOM or an XML string
*
* @return string|\DOMDocument An XML string representing the command
*
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asXml($asDom = false)
{
$descriptor = new XmlDescriptor();
if ($asDom) {
return $descriptor->getCommandDocument($this);
if (null === $this->helperSet) {
throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
}
$output = new BufferedOutput();
$descriptor->describe($output, $this);
return $output->fetch();
return $this->helperSet->get($name);
}
/**
@@ -650,12 +620,12 @@ class Command
*
* @param string $name
*
* @throws \InvalidArgumentException When the name is invalid
* @throws InvalidArgumentException When the name is invalid
*/
private function validateName($name)
{
if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
}
}
}

View File

@@ -37,12 +37,11 @@ class HelpCommand extends Command
->setName('help')
->setDefinition(array(
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
))
->setDescription('Displays help for a command')
->setHelp(<<<EOF
->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays help for a given command:
<info>php %command.full_name% list</info>
@@ -76,10 +75,6 @@ EOF
$this->command = $this->getApplication()->find($input->getArgument('command_name'));
}
if ($input->getOption('xml')) {
$input->setOption('format', 'xml');
}
$helper = new DescriptorHelper();
$helper->describe($output, $this->command, array(
'format' => $input->getOption('format'),

View File

@@ -34,7 +34,7 @@ class ListCommand extends Command
->setName('list')
->setDefinition($this->createDefinition())
->setDescription('Lists commands')
->setHelp(<<<EOF
->setHelp(<<<'EOF'
The <info>%command.name%</info> command lists all commands:
<info>php %command.full_name%</info>
@@ -68,10 +68,6 @@ EOF
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('xml')) {
$input->setOption('format', 'xml');
}
$helper = new DescriptorHelper();
$helper->describe($output, $this->getApplication(), array(
'format' => $input->getOption('format'),
@@ -87,9 +83,8 @@ EOF
{
return new InputDefinition(array(
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
));
}
}

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\CommandNotFoundException;
/**
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
@@ -89,12 +90,12 @@ class ApplicationDescription
*
* @return Command
*
* @throws \InvalidArgumentException
* @throws CommandNotFoundException
*/
public function getCommand($name)
{
if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name));
throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
}
return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
@@ -136,15 +137,17 @@ class ApplicationDescription
private function sortCommands(array $commands)
{
$namespacedCommands = array();
$globalCommands = array();
foreach ($commands as $name => $command) {
$key = $this->application->extractNamespace($name, 1);
if (!$key) {
$key = '_global';
$globalCommands['_global'][$name] = $command;
} else {
$namespacedCommands[$key][$name] = $command;
}
$namespacedCommands[$key][$name] = $command;
}
ksort($namespacedCommands);
$namespacedCommands = array_merge($globalCommands, $namespacedCommands);
foreach ($namespacedCommands as &$commandsSet) {
ksort($commandsSet);

View File

@@ -17,6 +17,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
@@ -28,7 +29,7 @@ abstract class Descriptor implements DescriptorInterface
/**
* @var OutputInterface
*/
private $output;
protected $output;
/**
* {@inheritdoc}
@@ -54,7 +55,7 @@ abstract class Descriptor implements DescriptorInterface
$this->describeApplication($object, $options);
break;
default:
throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
}
}

View File

@@ -102,7 +102,7 @@ class JsonDescriptor extends Descriptor
'name' => $argument->getName(),
'is_required' => $argument->isRequired(),
'is_array' => $argument->isArray(),
'description' => $argument->getDescription(),
'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
'default' => $argument->getDefault(),
);
}
@@ -120,7 +120,7 @@ class JsonDescriptor extends Descriptor
'accept_value' => $option->acceptValue(),
'is_value_required' => $option->isValueRequired(),
'is_multiple' => $option->isArray(),
'description' => $option->getDescription(),
'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
'default' => $option->getDefault(),
);
}
@@ -157,10 +157,9 @@ class JsonDescriptor extends Descriptor
return array(
'name' => $command->getName(),
'usage' => $command->getSynopsis(),
'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
'description' => $command->getDescription(),
'help' => $command->getProcessedHelp(),
'aliases' => $command->getAliases(),
'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
);
}

View File

@@ -36,7 +36,7 @@ class MarkdownDescriptor extends Descriptor
.'* Name: '.($argument->getName() ?: '<none>')."\n"
.'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
.'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
.'* Description: '.($argument->getDescription() ?: '<none>')."\n"
.'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n ", $argument->getDescription() ?: '<none>')."\n"
.'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
);
}
@@ -53,7 +53,7 @@ class MarkdownDescriptor extends Descriptor
.'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
.'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
.'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
.'* Description: '.($option->getDescription() ?: '<none>')."\n"
.'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n ", $option->getDescription() ?: '<none>')."\n"
.'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
);
}
@@ -96,12 +96,14 @@ class MarkdownDescriptor extends Descriptor
$command->getName()."\n"
.str_repeat('-', strlen($command->getName()))."\n\n"
.'* Description: '.($command->getDescription() ?: '<none>')."\n"
.'* Usage: `'.$command->getSynopsis().'`'."\n"
.'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '<none>')
.'* Usage:'."\n\n"
.array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
return $carry .= ' * `'.$usage.'`'."\n";
})
);
if ($help = $command->getProcessedHelp()) {
$this->write("\n\n");
$this->write("\n");
$this->write($help);
}

View File

@@ -32,16 +32,19 @@ class TextDescriptor extends Descriptor
protected function describeInputArgument(InputArgument $argument, array $options = array())
{
if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
$default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault()));
$default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
} else {
$default = '';
}
$nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName());
$totalWidth = isset($options['total_width']) ? $options['total_width'] : strlen($argument->getName());
$spacingWidth = $totalWidth - strlen($argument->getName()) + 2;
$this->writeText(sprintf(" <info>%-${nameWidth}s</info> %s%s",
$this->writeText(sprintf(' <info>%s</info>%s%s%s',
$argument->getName(),
str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()),
str_repeat(' ', $spacingWidth),
// + 17 = 2 spaces + <info> + </info> + 2 spaces
preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $argument->getDescription()),
$default
), $options);
}
@@ -52,18 +55,33 @@ class TextDescriptor extends Descriptor
protected function describeInputOption(InputOption $option, array $options = array())
{
if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
$default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($option->getDefault()));
$default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
} else {
$default = '';
}
$nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName());
$nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2;
$value = '';
if ($option->acceptValue()) {
$value = '='.strtoupper($option->getName());
$this->writeText(sprintf(" <info>%s</info> %-${nameWithShortcutWidth}s%s%s%s",
'--'.$option->getName(),
$option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()),
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)
);
$spacingWidth = $totalWidth - strlen($synopsis) + 2;
$this->writeText(sprintf(' <info>%s</info>%s%s%s%s',
$synopsis,
str_repeat(' ', $spacingWidth),
// + 17 = 2 spaces + <info> + </info> + 2 spaces
preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $option->getDescription()),
$default,
$option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
), $options);
@@ -74,24 +92,16 @@ class TextDescriptor extends Descriptor
*/
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
{
$nameWidth = 0;
foreach ($definition->getOptions() as $option) {
$nameLength = strlen($option->getName()) + 2;
if ($option->getShortcut()) {
$nameLength += strlen($option->getShortcut()) + 3;
}
$nameWidth = max($nameWidth, $nameLength);
}
$totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
foreach ($definition->getArguments() as $argument) {
$nameWidth = max($nameWidth, strlen($argument->getName()));
$totalWidth = max($totalWidth, strlen($argument->getName()));
}
++$nameWidth;
if ($definition->getArguments()) {
$this->writeText('<comment>Arguments:</comment>', $options);
$this->writeText("\n");
foreach ($definition->getArguments() as $argument) {
$this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth)));
$this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
$this->writeText("\n");
}
}
@@ -101,11 +111,20 @@ class TextDescriptor extends Descriptor
}
if ($definition->getOptions()) {
$laterOptions = array();
$this->writeText('<comment>Options:</comment>', $options);
$this->writeText("\n");
foreach ($definition->getOptions() as $option) {
$this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth)));
if (strlen($option->getShortcut()) > 1) {
$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)));
}
}
}
@@ -115,27 +134,26 @@ class TextDescriptor extends Descriptor
*/
protected function describeCommand(Command $command, array $options = array())
{
$command->getSynopsis();
$command->getSynopsis(true);
$command->getSynopsis(false);
$command->mergeApplicationDefinition(false);
$this->writeText('<comment>Usage:</comment>', $options);
$this->writeText("\n");
$this->writeText(' '.$command->getSynopsis(), $options);
$this->writeText("\n");
if (count($command->getAliases()) > 0) {
foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
$this->writeText("\n");
$this->writeText('<comment>Aliases:</comment> <info>'.implode(', ', $command->getAliases()).'</info>', $options);
$this->writeText(' '.$usage, $options);
}
$this->writeText("\n");
if ($definition = $command->getNativeDefinition()) {
$definition = $command->getNativeDefinition();
if ($definition->getOptions() || $definition->getArguments()) {
$this->writeText("\n");
$this->describeInputDefinition($definition, $options);
$this->writeText("\n");
}
$this->writeText("\n");
if ($help = $command->getProcessedHelp()) {
$this->writeText("\n");
$this->writeText('<comment>Help:</comment>', $options);
$this->writeText("\n");
$this->writeText(' '.str_replace("\n", "\n ", $help), $options);
@@ -155,7 +173,7 @@ class TextDescriptor extends Descriptor
$width = $this->getColumnWidth($description->getCommands());
foreach ($description->getCommands() as $command) {
$this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options);
$this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
$this->writeText("\n");
}
} else {
@@ -164,27 +182,12 @@ class TextDescriptor extends Descriptor
}
$this->writeText("<comment>Usage:</comment>\n", $options);
$this->writeText(" command [options] [arguments]\n\n", $options);
$this->writeText('<comment>Options:</comment>', $options);
$this->writeText(" command [options] [arguments]\n\n", $options);
$inputOptions = $application->getDefinition()->getOptions();
$this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
$width = 0;
foreach ($inputOptions as $option) {
$nameLength = strlen($option->getName()) + 2;
if ($option->getShortcut()) {
$nameLength += strlen($option->getShortcut()) + 3;
}
$width = max($width, $nameLength);
}
++$width;
foreach ($inputOptions as $option) {
$this->writeText("\n", $options);
$this->describeInputOption($option, array_merge($options, array('name_width' => $width)));
}
$this->writeText("\n\n", $options);
$this->writeText("\n");
$this->writeText("\n");
$width = $this->getColumnWidth($description->getCommands());
@@ -198,12 +201,13 @@ class TextDescriptor extends Descriptor
foreach ($description->getNamespaces() as $namespace) {
if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
$this->writeText("\n");
$this->writeText('<comment>'.$namespace['id'].'</comment>', $options);
$this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
}
foreach ($namespace['commands'] as $name) {
$this->writeText("\n");
$this->writeText(sprintf(" <info>%-${width}s</info> %s", $name, $description->getCommand($name)->getDescription()), $options);
$spacingWidth = $width - strlen($name);
$this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
}
}
@@ -231,11 +235,7 @@ class TextDescriptor extends Descriptor
*/
private function formatDefaultValue($default)
{
if (PHP_VERSION_ID < 50400) {
return str_replace('\/', '/', json_encode($default));
}
return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
}
/**
@@ -245,11 +245,39 @@ class TextDescriptor extends Descriptor
*/
private function getColumnWidth(array $commands)
{
$width = 0;
$widths = array();
foreach ($commands as $command) {
$width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
$widths[] = strlen($command->getName());
foreach ($command->getAliases() as $alias) {
$widths[] = strlen($alias);
}
}
return $width + 2;
return max($widths) + 2;
}
/**
* @param InputOption[] $options
*
* @return int
*/
private function calculateTotalWidthForOptions($options)
{
$totalWidth = 0;
foreach ($options as $option) {
// "-" + shortcut + ", --" + name
$nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + strlen($option->getName());
if ($option->acceptValue()) {
$valueLength = 1 + strlen($option->getName()); // = + value
$valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]
$nameLength += $valueLength;
}
$totalWidth = max($totalWidth, $nameLength);
}
return $totalWidth;
}
}

View File

@@ -65,8 +65,11 @@ class XmlDescriptor extends Descriptor
$commandXML->setAttribute('id', $command->getName());
$commandXML->setAttribute('name', $command->getName());
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
$usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), '')));
$commandXML->appendChild($usagesXML = $dom->createElement('usages'));
foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
$usagesXML->appendChild($dom->createElement('usage', $usage));
}
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
@@ -74,12 +77,6 @@ class XmlDescriptor extends Descriptor
$commandXML->appendChild($helpXML = $dom->createElement('help'));
$helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
foreach ($command->getAliases() as $alias) {
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
$aliasXML->appendChild($dom->createTextNode($alias));
}
$definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
$this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));

View File

@@ -19,19 +19,19 @@ namespace Symfony\Component\Console\Event;
class ConsoleCommandEvent extends ConsoleEvent
{
/**
* The return code for skipped commands, this will also be passed into the terminate event
* The return code for skipped commands, this will also be passed into the terminate event.
*/
const RETURN_CODE_DISABLED = 113;
/**
* Indicates if the command should be run or skipped
* Indicates if the command should be run or skipped.
*
* @var bool
*/
private $commandShouldRun = true;
/**
* Disables the command, so it won't be run
* Disables the command, so it won't be run.
*
* @return bool
*/
@@ -41,7 +41,7 @@ class ConsoleCommandEvent extends ConsoleEvent
}
/**
* Enables the command
* Enables the command.
*
* @return bool
*/
@@ -51,7 +51,7 @@ class ConsoleCommandEvent extends ConsoleEvent
}
/**
* Returns true if the command is runnable, false otherwise
* Returns true if the command is runnable, false otherwise.
*
* @return bool
*/

View File

@@ -0,0 +1,43 @@
<?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\Exception;
/**
* Represents an incorrect command name typed in the console.
*
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
{
private $alternatives;
/**
* @param string $message Exception message to throw.
* @param array $alternatives List of similar defined names.
* @param int $code Exception code.
* @param Exception $previous previous exception used for the exception chaining.
*/
public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
$this->alternatives = $alternatives;
}
/**
* @return array A list of similar defined names.
*/
public function getAlternatives()
{
return $this->alternatives;
}
}

View File

@@ -9,12 +9,12 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Exception;
namespace Symfony\Component\Console\Exception;
/**
* Base ExceptionInterface for the Security component.
* ExceptionInterface.
*
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
interface ExceptionInterface
{

View File

@@ -9,12 +9,10 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Exception;
namespace Symfony\Component\Console\Exception;
/**
* Base InvalidArgumentException for the Security component.
*
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Debug\Exception;
namespace Symfony\Component\Console\Exception;
/**
* @author Fabien Potencier <fabien@symfony.com>
* Represents an incorrect option name typed in the console.
*
* @deprecated since version 2.5, to be removed in 3.0.
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
class DummyException extends \ErrorException
class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -9,11 +9,11 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Finder\Exception;
namespace Symfony\Component\Console\Exception;
/**
* @author Jean-François Simon <contact@jfsimon.fr>
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
class OperationNotPermitedException extends AdapterFailureException
class LogicException extends \LogicException implements ExceptionInterface
{
}

View File

@@ -9,12 +9,10 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Exception;
namespace Symfony\Component\Console\Exception;
/**
* Base RuntimeException for the Security component.
*
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{

View File

@@ -11,12 +11,12 @@
namespace Symfony\Component\Console\Formatter;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* Formatter class for console output.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*
* @api
*/
class OutputFormatter implements OutputFormatterInterface
{
@@ -33,7 +33,15 @@ class OutputFormatter implements OutputFormatterInterface
*/
public static function escape($text)
{
return preg_replace('/([^\\\\]?)</', '$1\\<', $text);
$text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
if ('\\' === substr($text, -1)) {
$len = strlen($text);
$text = rtrim($text, '\\');
$text .= str_repeat('<<', $len - strlen($text));
}
return $text;
}
/**
@@ -41,8 +49,6 @@ class OutputFormatter implements OutputFormatterInterface
*
* @param bool $decorated Whether this formatter should actually decorate strings
* @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
*
* @api
*/
public function __construct($decorated = false, array $styles = array())
{
@@ -64,8 +70,6 @@ class OutputFormatter implements OutputFormatterInterface
* Sets the decorated flag.
*
* @param bool $decorated Whether to decorate the messages or not
*
* @api
*/
public function setDecorated($decorated)
{
@@ -76,8 +80,6 @@ class OutputFormatter implements OutputFormatterInterface
* Gets the decorated flag.
*
* @return bool true if the output will decorate messages, false otherwise
*
* @api
*/
public function isDecorated()
{
@@ -89,8 +91,6 @@ class OutputFormatter implements OutputFormatterInterface
*
* @param string $name The style name
* @param OutputFormatterStyleInterface $style The style instance
*
* @api
*/
public function setStyle($name, OutputFormatterStyleInterface $style)
{
@@ -103,8 +103,6 @@ class OutputFormatter implements OutputFormatterInterface
* @param string $name
*
* @return bool
*
* @api
*/
public function hasStyle($name)
{
@@ -118,14 +116,12 @@ class OutputFormatter implements OutputFormatterInterface
*
* @return OutputFormatterStyleInterface
*
* @throws \InvalidArgumentException When style isn't defined
*
* @api
* @throws InvalidArgumentException When style isn't defined
*/
public function getStyle($name)
{
if (!$this->hasStyle($name)) {
throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name));
throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
}
return $this->styles[strtolower($name)];
@@ -137,15 +133,13 @@ class OutputFormatter implements OutputFormatterInterface
* @param string $message The message to style
*
* @return string The styled message
*
* @api
*/
public function format($message)
{
$message = (string) $message;
$offset = 0;
$output = '';
$tagRegex = '[a-z][a-z0-9_=;-]*';
$tagRegex = '[a-z][a-z0-9_=;-]*+';
preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[0] as $i => $match) {
$pos = $match[1];
@@ -180,6 +174,10 @@ class OutputFormatter implements OutputFormatterInterface
$output .= $this->applyCurrentStyle(substr($message, $offset));
if (false !== strpos($output, '<<')) {
return strtr($output, array('\\<' => '<', '<<' => '\\'));
}
return str_replace('\\<', '<', $output);
}

View File

@@ -15,8 +15,6 @@ namespace Symfony\Component\Console\Formatter;
* Formatter interface for console output.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*
* @api
*/
interface OutputFormatterInterface
{
@@ -24,8 +22,6 @@ interface OutputFormatterInterface
* Sets the decorated flag.
*
* @param bool $decorated Whether to decorate the messages or not
*
* @api
*/
public function setDecorated($decorated);
@@ -33,8 +29,6 @@ interface OutputFormatterInterface
* Gets the decorated flag.
*
* @return bool true if the output will decorate messages, false otherwise
*
* @api
*/
public function isDecorated();
@@ -43,8 +37,6 @@ interface OutputFormatterInterface
*
* @param string $name The style name
* @param OutputFormatterStyleInterface $style The style instance
*
* @api
*/
public function setStyle($name, OutputFormatterStyleInterface $style);
@@ -54,8 +46,6 @@ interface OutputFormatterInterface
* @param string $name
*
* @return bool
*
* @api
*/
public function hasStyle($name);
@@ -65,8 +55,6 @@ interface OutputFormatterInterface
* @param string $name
*
* @return OutputFormatterStyleInterface
*
* @api
*/
public function getStyle($name);
@@ -76,8 +64,6 @@ interface OutputFormatterInterface
* @param string $message The message to style
*
* @return string The styled message
*
* @api
*/
public function format($message);
}

View File

@@ -11,12 +11,12 @@
namespace Symfony\Component\Console\Formatter;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* Formatter style class for defining styles.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*
* @api
*/
class OutputFormatterStyle implements OutputFormatterStyleInterface
{
@@ -60,8 +60,6 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
* @param string|null $foreground The style foreground color name
* @param string|null $background The style background color name
* @param array $options The style options
*
* @api
*/
public function __construct($foreground = null, $background = null, array $options = array())
{
@@ -81,9 +79,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
*
* @param string|null $color The color name
*
* @throws \InvalidArgumentException When the color name isn't defined
*
* @api
* @throws InvalidArgumentException When the color name isn't defined
*/
public function setForeground($color = null)
{
@@ -94,7 +90,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
}
if (!isset(static::$availableForegroundColors[$color])) {
throw new \InvalidArgumentException(sprintf(
throw new InvalidArgumentException(sprintf(
'Invalid foreground color specified: "%s". Expected one of (%s)',
$color,
implode(', ', array_keys(static::$availableForegroundColors))
@@ -109,9 +105,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
*
* @param string|null $color The color name
*
* @throws \InvalidArgumentException When the color name isn't defined
*
* @api
* @throws InvalidArgumentException When the color name isn't defined
*/
public function setBackground($color = null)
{
@@ -122,7 +116,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
}
if (!isset(static::$availableBackgroundColors[$color])) {
throw new \InvalidArgumentException(sprintf(
throw new InvalidArgumentException(sprintf(
'Invalid background color specified: "%s". Expected one of (%s)',
$color,
implode(', ', array_keys(static::$availableBackgroundColors))
@@ -137,14 +131,12 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
*
* @param string $option The option name
*
* @throws \InvalidArgumentException When the option name isn't defined
*
* @api
* @throws InvalidArgumentException When the option name isn't defined
*/
public function setOption($option)
{
if (!isset(static::$availableOptions[$option])) {
throw new \InvalidArgumentException(sprintf(
throw new InvalidArgumentException(sprintf(
'Invalid option specified: "%s". Expected one of (%s)',
$option,
implode(', ', array_keys(static::$availableOptions))
@@ -161,12 +153,12 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
*
* @param string $option The option name
*
* @throws \InvalidArgumentException When the option name isn't defined
* @throws InvalidArgumentException When the option name isn't defined
*/
public function unsetOption($option)
{
if (!isset(static::$availableOptions[$option])) {
throw new \InvalidArgumentException(sprintf(
throw new InvalidArgumentException(sprintf(
'Invalid option specified: "%s". Expected one of (%s)',
$option,
implode(', ', array_keys(static::$availableOptions))

View File

@@ -15,8 +15,6 @@ namespace Symfony\Component\Console\Formatter;
* Formatter style interface for defining styles.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*
* @api
*/
interface OutputFormatterStyleInterface
{
@@ -24,8 +22,6 @@ interface OutputFormatterStyleInterface
* Sets style foreground color.
*
* @param string $color The color name
*
* @api
*/
public function setForeground($color = null);
@@ -33,8 +29,6 @@ interface OutputFormatterStyleInterface
* Sets style background color.
*
* @param string $color The color name
*
* @api
*/
public function setBackground($color = null);
@@ -42,8 +36,6 @@ interface OutputFormatterStyleInterface
* Sets some specific style option.
*
* @param string $option The option name
*
* @api
*/
public function setOption($option);

View File

@@ -11,6 +11,8 @@
namespace Symfony\Component\Console\Formatter;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* @author Jean-François Simon <contact@jfsimon.fr>
*/
@@ -62,7 +64,7 @@ class OutputFormatterStyleStack
*
* @return OutputFormatterStyleInterface
*
* @throws \InvalidArgumentException When style tags incorrectly nested
* @throws InvalidArgumentException When style tags incorrectly nested
*/
public function pop(OutputFormatterStyleInterface $style = null)
{
@@ -82,7 +84,7 @@ class OutputFormatterStyleStack
}
}
throw new \InvalidArgumentException('Incorrectly nested style tag found.');
throw new InvalidArgumentException('Incorrectly nested style tag found.');
}
/**

View File

@@ -25,7 +25,7 @@ class DebugFormatterHelper extends Helper
private $count = -1;
/**
* Starts a debug formatting session
* Starts a debug formatting session.
*
* @param string $id The id of the formatting session
* @param string $message The message to display
@@ -41,7 +41,7 @@ class DebugFormatterHelper extends Helper
}
/**
* Adds progress to a formatting session
* Adds progress to a formatting session.
*
* @param string $id The id of the formatting session
* @param string $buffer The message to display
@@ -61,7 +61,7 @@ class DebugFormatterHelper extends Helper
unset($this->started[$id]['out']);
}
if (!isset($this->started[$id]['err'])) {
$message .= sprintf("%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix);
$message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
$this->started[$id]['err'] = true;
}
@@ -72,7 +72,7 @@ class DebugFormatterHelper extends Helper
unset($this->started[$id]['err']);
}
if (!isset($this->started[$id]['out'])) {
$message .= sprintf("%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix);
$message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
$this->started[$id]['out'] = true;
}
@@ -83,7 +83,7 @@ class DebugFormatterHelper extends Helper
}
/**
* Stops a formatting session
* Stops a formatting session.
*
* @param string $id The id of the formatting session
* @param string $message The message to display

View File

@@ -17,6 +17,7 @@ use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* This class adds helper method to describe objects in various formats.
@@ -54,7 +55,7 @@ class DescriptorHelper extends Helper
* @param object $object
* @param array $options
*
* @throws \InvalidArgumentException when the given format is not supported
* @throws InvalidArgumentException when the given format is not supported
*/
public function describe(OutputInterface $output, $object, array $options = array())
{
@@ -64,7 +65,7 @@ class DescriptorHelper extends Helper
), $options);
if (!isset($this->descriptors[$options['format']])) {
throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
}
$descriptor = $this->descriptors[$options['format']];

View File

@@ -51,11 +51,7 @@ abstract class Helper implements HelperInterface
*/
public static function strlen($string)
{
if (!function_exists('mb_strwidth')) {
return strlen($string);
}
if (false === $encoding = mb_detect_encoding($string)) {
if (false === $encoding = mb_detect_encoding($string, null, true)) {
return strlen($string);
}
@@ -66,26 +62,28 @@ abstract class Helper implements HelperInterface
{
static $timeFormats = array(
array(0, '< 1 sec'),
array(2, '1 sec'),
array(59, 'secs', 1),
array(1, '1 sec'),
array(2, 'secs', 1),
array(60, '1 min'),
array(3600, 'mins', 60),
array(5400, '1 hr'),
array(86400, 'hrs', 3600),
array(129600, '1 day'),
array(604800, 'days', 86400),
array(120, 'mins', 60),
array(3600, '1 hr'),
array(7200, 'hrs', 3600),
array(86400, '1 day'),
array(172800, 'days', 86400),
);
foreach ($timeFormats as $format) {
foreach ($timeFormats as $index => $format) {
if ($secs >= $format[0]) {
continue;
}
if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
|| $index == count($timeFormats) - 1
) {
if (2 == count($format)) {
return $format[1];
}
if (2 == count($format)) {
return $format[1];
return floor($secs / $format[2]).' '.$format[1];
}
}
return ceil($secs / $format[2]).' '.$format[1];
}
}

View File

@@ -15,8 +15,6 @@ namespace Symfony\Component\Console\Helper;
* HelperInterface is the interface all helpers must implement.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
interface HelperInterface
{
@@ -24,8 +22,6 @@ interface HelperInterface
* Sets the helper set associated with this helper.
*
* @param HelperSet $helperSet A HelperSet instance
*
* @api
*/
public function setHelperSet(HelperSet $helperSet = null);
@@ -33,8 +29,6 @@ interface HelperInterface
* Gets the helper set associated with this helper.
*
* @return HelperSet A HelperSet instance
*
* @api
*/
public function getHelperSet();
@@ -42,8 +36,6 @@ interface HelperInterface
* Returns the canonical name of this helper.
*
* @return string The canonical name
*
* @api
*/
public function getName();
}

View File

@@ -12,6 +12,7 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* HelperSet represents a set of helpers to be used with a command.
@@ -70,12 +71,12 @@ class HelperSet implements \IteratorAggregate
*
* @return HelperInterface The helper instance
*
* @throws \InvalidArgumentException if the helper is not defined
* @throws InvalidArgumentException if the helper is not defined
*/
public function get($name)
{
if (!$this->has($name)) {
throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
}
return $this->helpers[$name];

View File

@@ -11,6 +11,7 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
@@ -35,8 +36,12 @@ class ProcessHelper extends Helper
*
* @return Process The process that ran
*/
public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
public function run(OutputInterface $output, $cmd, $error = null, callable $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
{
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
$formatter = $this->getHelperSet()->get('debug_formatter');
if (is_array($cmd)) {
@@ -87,7 +92,7 @@ class ProcessHelper extends Helper
*
* @see run()
*/
public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
public function mustRun(OutputInterface $output, $cmd, $error = null, callable $callback = null)
{
$process = $this->run($output, $cmd, $error, $callback);
@@ -107,14 +112,16 @@ class ProcessHelper extends Helper
*
* @return callable
*/
public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null)
{
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
$formatter = $this->getHelperSet()->get('debug_formatter');
$that = $this;
return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
$output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
return function ($type, $buffer) use ($output, $process, $callback, $formatter) {
$output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type));
if (null !== $callback) {
call_user_func($callback, $type, $buffer);
@@ -122,12 +129,7 @@ class ProcessHelper extends Helper
};
}
/**
* This method is public for PHP 5.3 compatibility, it should be private.
*
* @internal
*/
public function escapeString($str)
private function escapeString($str)
{
return str_replace('<', '\\<', $str);
}

View File

@@ -11,7 +11,9 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Exception\LogicException;
/**
* The ProgressBar provides helpers to display progress output.
@@ -26,7 +28,8 @@ class ProgressBar
private $barChar;
private $emptyBarChar = '-';
private $progressChar = '>';
private $format = null;
private $format;
private $internalFormat;
private $redrawFreq = 1;
/**
@@ -38,7 +41,6 @@ class ProgressBar
private $startTime;
private $stepWidth;
private $percent = 0.0;
private $lastMessagesLength = 0;
private $formatLineCount;
private $messages;
private $overwrite = true;
@@ -54,6 +56,10 @@ class ProgressBar
*/
public function __construct(OutputInterface $output, $max = 0)
{
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
$this->output = $output;
$this->setMaxSteps($max);
@@ -61,14 +67,10 @@ class ProgressBar
// disable overwrite when output does not support ANSI codes.
$this->overwrite = false;
if ($this->max > 10) {
// set a reasonable redraw frequency so output isn't flooded
$this->setRedrawFrequency($max / 10);
}
// set a reasonable redraw frequency so output isn't flooded
$this->setRedrawFrequency($max / 10);
}
$this->setFormat($this->determineBestFormat());
$this->startTime = time();
}
@@ -80,7 +82,7 @@ class ProgressBar
* @param string $name The placeholder name (including the delimiter char like %)
* @param callable $callable A PHP callable
*/
public static function setPlaceholderFormatterDefinition($name, $callable)
public static function setPlaceholderFormatterDefinition($name, callable $callable)
{
if (!self::$formatters) {
self::$formatters = self::initPlaceholderFormatters();
@@ -168,18 +170,6 @@ class ProgressBar
return $this->max;
}
/**
* Gets the progress bar step.
*
* @deprecated since 2.6, to be removed in 3.0. Use {@link getProgress()} instead.
*
* @return int The progress bar step
*/
public function getStep()
{
return $this->getProgress();
}
/**
* Gets the current step position.
*
@@ -193,11 +183,9 @@ class ProgressBar
/**
* Gets the progress bar step width.
*
* @internal This method is public for PHP 5.3 compatibility, it should not be used.
*
* @return int The progress bar step width
*/
public function getStepWidth()
private function getStepWidth()
{
return $this->stepWidth;
}
@@ -303,26 +291,18 @@ class ProgressBar
*/
public function setFormat($format)
{
// try to use the _nomax variant if available
if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
$this->format = self::getFormatDefinition($format.'_nomax');
} elseif (null !== self::getFormatDefinition($format)) {
$this->format = self::getFormatDefinition($format);
} else {
$this->format = $format;
}
$this->formatLineCount = substr_count($this->format, "\n");
$this->format = null;
$this->internalFormat = $format;
}
/**
* Sets the redraw frequency.
*
* @param int $freq The frequency in steps
* @param int|float $freq The frequency in steps
*/
public function setRedrawFrequency($freq)
{
$this->redrawFreq = (int) $freq;
$this->redrawFreq = max((int) $freq, 1);
}
/**
@@ -348,27 +328,13 @@ class ProgressBar
*
* @param int $step Number of steps to advance
*
* @throws \LogicException
* @throws LogicException
*/
public function advance($step = 1)
{
$this->setProgress($this->step + $step);
}
/**
* Sets the current progress.
*
* @deprecated since 2.6, to be removed in 3.0. Use {@link setProgress()} instead.
*
* @param int $step The current progress
*
* @throws \LogicException
*/
public function setCurrent($step)
{
$this->setProgress($step);
}
/**
* Sets whether to overwrite the progressbar, false for new line.
*
@@ -384,13 +350,13 @@ class ProgressBar
*
* @param int $step The current progress
*
* @throws \LogicException
* @throws LogicException
*/
public function setProgress($step)
{
$step = (int) $step;
if ($step < $this->step) {
throw new \LogicException('You can\'t regress the progress bar.');
throw new LogicException('You can\'t regress the progress bar.');
}
if ($this->max && $step > $this->max) {
@@ -432,15 +398,15 @@ class ProgressBar
return;
}
// these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped.
$self = $this;
$output = $this->output;
$messages = $this->messages;
$this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
$text = call_user_func($formatter, $self, $output);
} elseif (isset($messages[$matches[1]])) {
$text = $messages[$matches[1]];
if (null === $this->format) {
$this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
}
$this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) {
if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) {
$text = call_user_func($formatter, $this, $this->output);
} elseif (isset($this->messages[$matches[1]])) {
$text = $this->messages[$matches[1]];
} else {
return $matches[0];
}
@@ -466,13 +432,36 @@ class ProgressBar
return;
}
$this->overwrite(str_repeat("\n", $this->formatLineCount));
if (null === $this->format) {
$this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
}
$this->overwrite('');
}
/**
* Sets the progress bar format.
*
* @param string $format The format
*/
private function setRealFormat($format)
{
// try to use the _nomax variant if available
if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
$this->format = self::getFormatDefinition($format.'_nomax');
} elseif (null !== self::getFormatDefinition($format)) {
$this->format = self::getFormatDefinition($format);
} else {
$this->format = $format;
}
$this->formatLineCount = substr_count($this->format, "\n");
}
/**
* Sets the progress bar maximal steps.
*
* @param int The progress bar max steps
* @param int $max The progress bar max steps
*/
private function setMaxSteps($max)
{
@@ -487,37 +476,22 @@ class ProgressBar
*/
private function overwrite($message)
{
$lines = explode("\n", $message);
// append whitespace to match the line's length
if (null !== $this->lastMessagesLength) {
foreach ($lines as $i => $line) {
if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $line)) {
$lines[$i] = str_pad($line, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
}
}
}
if ($this->overwrite) {
// move back to the beginning of the progress bar before redrawing it
// Move the cursor to the beginning of the line
$this->output->write("\x0D");
// Erase the line
$this->output->write("\x1B[2K");
// Erase previous lines
if ($this->formatLineCount > 0) {
$this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
}
} elseif ($this->step > 0) {
// move to new line
$this->output->writeln('');
}
if ($this->formatLineCount) {
$this->output->write(sprintf("\033[%dA", $this->formatLineCount));
}
$this->output->write(implode("\n", $lines));
$this->lastMessagesLength = 0;
foreach ($lines as $line) {
$len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $line);
if ($len > $this->lastMessagesLength) {
$this->lastMessagesLength = $len;
}
}
$this->output->write($message);
}
private function determineBestFormat()
@@ -553,7 +527,7 @@ class ProgressBar
},
'remaining' => function (ProgressBar $bar) {
if (!$bar->getMaxSteps()) {
throw new \LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
}
if (!$bar->getProgress()) {
@@ -566,7 +540,7 @@ class ProgressBar
},
'estimated' => function (ProgressBar $bar) {
if (!$bar->getMaxSteps()) {
throw new \LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
}
if (!$bar->getProgress()) {

View File

@@ -0,0 +1,288 @@
<?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\Helper;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Output\OutputInterface;
/**
* @author Kevin Bond <kevinbond@gmail.com>
*/
class ProgressIndicator
{
private $output;
private $startTime;
private $format;
private $message;
private $indicatorValues;
private $indicatorCurrent;
private $indicatorChangeInterval;
private $indicatorUpdateTime;
private $lastMessagesLength;
private $started = false;
private static $formatters;
private static $formats;
/**
* @param OutputInterface $output
* @param string|null $format Indicator format
* @param int $indicatorChangeInterval Change interval in milliseconds
* @param array|null $indicatorValues Animated indicator characters
*/
public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
{
$this->output = $output;
if (null === $format) {
$format = $this->determineBestFormat();
}
if (null === $indicatorValues) {
$indicatorValues = array('-', '\\', '|', '/');
}
$indicatorValues = array_values($indicatorValues);
if (2 > count($indicatorValues)) {
throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
}
$this->format = self::getFormatDefinition($format);
$this->indicatorChangeInterval = $indicatorChangeInterval;
$this->indicatorValues = $indicatorValues;
$this->startTime = time();
}
/**
* Sets the current indicator message.
*
* @param string|null $message
*/
public function setMessage($message)
{
$this->message = $message;
$this->display();
}
/**
* Starts the indicator output.
*
* @param $message
*/
public function start($message)
{
if ($this->started) {
throw new LogicException('Progress indicator already started.');
}
$this->message = $message;
$this->started = true;
$this->lastMessagesLength = 0;
$this->startTime = time();
$this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
$this->indicatorCurrent = 0;
$this->display();
}
/**
* Advances the indicator.
*/
public function advance()
{
if (!$this->started) {
throw new LogicException('Progress indicator has not yet been started.');
}
if (!$this->output->isDecorated()) {
return;
}
$currentTime = $this->getCurrentTimeInMilliseconds();
if ($currentTime < $this->indicatorUpdateTime) {
return;
}
$this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
++$this->indicatorCurrent;
$this->display();
}
/**
* Finish the indicator with message.
*
* @param $message
*/
public function finish($message)
{
if (!$this->started) {
throw new LogicException('Progress indicator has not yet been started.');
}
$this->message = $message;
$this->display();
$this->output->writeln('');
$this->started = false;
}
/**
* Gets the format for a given name.
*
* @param string $name The format name
*
* @return string|null A format string
*/
public static function getFormatDefinition($name)
{
if (!self::$formats) {
self::$formats = self::initFormats();
}
return isset(self::$formats[$name]) ? self::$formats[$name] : null;
}
/**
* Sets a placeholder formatter for a given name.
*
* This method also allow you to override an existing placeholder.
*
* @param string $name The placeholder name (including the delimiter char like %)
* @param callable $callable A PHP callable
*/
public static function setPlaceholderFormatterDefinition($name, $callable)
{
if (!self::$formatters) {
self::$formatters = self::initPlaceholderFormatters();
}
self::$formatters[$name] = $callable;
}
/**
* Gets the placeholder formatter for a given name.
*
* @param string $name The placeholder name (including the delimiter char like %)
*
* @return callable|null A PHP callable
*/
public static function getPlaceholderFormatterDefinition($name)
{
if (!self::$formatters) {
self::$formatters = self::initPlaceholderFormatters();
}
return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
}
private function display()
{
if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
return;
}
$self = $this;
$this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
return call_user_func($formatter, $self);
}
return $matches[0];
}, $this->format));
}
private function determineBestFormat()
{
switch ($this->output->getVerbosity()) {
// OutputInterface::VERBOSITY_QUIET: display is disabled anyway
case OutputInterface::VERBOSITY_VERBOSE:
return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
case OutputInterface::VERBOSITY_VERY_VERBOSE:
case OutputInterface::VERBOSITY_DEBUG:
return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
default:
return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
}
}
/**
* Overwrites a previous message to the output.
*
* @param string $message The message
*/
private function overwrite($message)
{
// append whitespace to match the line's length
if (null !== $this->lastMessagesLength) {
if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $message)) {
$message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
}
}
if ($this->output->isDecorated()) {
$this->output->write("\x0D");
$this->output->write($message);
} else {
$this->output->writeln($message);
}
$this->lastMessagesLength = 0;
$len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $message);
if ($len > $this->lastMessagesLength) {
$this->lastMessagesLength = $len;
}
}
private function getCurrentTimeInMilliseconds()
{
return round(microtime(true) * 1000);
}
private static function initPlaceholderFormatters()
{
return array(
'indicator' => function (ProgressIndicator $indicator) {
return $indicator->indicatorValues[$indicator->indicatorCurrent % count($indicator->indicatorValues)];
},
'message' => function (ProgressIndicator $indicator) {
return $indicator->message;
},
'elapsed' => function (ProgressIndicator $indicator) {
return Helper::formatTime(time() - $indicator->startTime);
},
'memory' => function () {
return Helper::formatMemory(memory_get_usage(true));
},
);
}
private static function initFormats()
{
return array(
'normal' => ' %indicator% %message%',
'normal_no_ansi' => ' %message%',
'verbose' => ' %indicator% %message% (%elapsed:6s%)',
'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
);
}
}

View File

@@ -11,7 +11,10 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Question\Question;
@@ -37,10 +40,14 @@ class QuestionHelper extends Helper
*
* @return string The user answer
*
* @throws \RuntimeException If there is no data to read in the input stream
* @throws RuntimeException If there is no data to read in the input stream
*/
public function ask(InputInterface $input, OutputInterface $output, Question $question)
{
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
if (!$input->isInteractive()) {
return $question->getDefault();
}
@@ -49,10 +56,8 @@ class QuestionHelper extends Helper
return $this->doAsk($output, $question);
}
$that = $this;
$interviewer = function () use ($output, $question, $that) {
return $that->doAsk($output, $question);
$interviewer = function () use ($output, $question) {
return $this->doAsk($output, $question);
};
return $this->validateAttempts($interviewer, $output, $question);
@@ -65,19 +70,19 @@ class QuestionHelper extends Helper
*
* @param resource $stream The input stream
*
* @throws \InvalidArgumentException In case the stream is not a resource
* @throws InvalidArgumentException In case the stream is not a resource
*/
public function setInputStream($stream)
{
if (!is_resource($stream)) {
throw new \InvalidArgumentException('Input stream must be a valid resource.');
throw new InvalidArgumentException('Input stream must be a valid resource.');
}
$this->inputStream = $stream;
}
/**
* Returns the helper's input stream
* Returns the helper's input stream.
*
* @return resource
*/
@@ -97,8 +102,6 @@ class QuestionHelper extends Helper
/**
* Asks the question to the user.
*
* This method is public for PHP 5.3 compatibility, it should be private.
*
* @param OutputInterface $output
* @param Question $question
*
@@ -107,27 +110,13 @@ class QuestionHelper extends Helper
* @throws \Exception
* @throws \RuntimeException
*/
public function doAsk(OutputInterface $output, Question $question)
private function doAsk(OutputInterface $output, Question $question)
{
$this->writePrompt($output, $question);
$inputStream = $this->inputStream ?: STDIN;
$message = $question->getQuestion();
if ($question instanceof ChoiceQuestion) {
$width = max(array_map('strlen', array_keys($question->getChoices())));
$messages = (array) $question->getQuestion();
foreach ($question->getChoices() as $key => $value) {
$messages[] = sprintf(" [<info>%-${width}s</info>] %s", $key, $value);
}
$output->writeln($messages);
$message = $question->getPrompt();
}
$output->write($message);
$autocomplete = $question->getAutocompleterValues();
if (null === $autocomplete || !$this->hasSttyAvailable()) {
$ret = false;
if ($question->isHidden()) {
@@ -160,6 +149,50 @@ class QuestionHelper extends Helper
return $ret;
}
/**
* Outputs the question prompt.
*
* @param OutputInterface $output
* @param Question $question
*/
protected function writePrompt(OutputInterface $output, Question $question)
{
$message = $question->getQuestion();
if ($question instanceof ChoiceQuestion) {
$maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
$messages = (array) $question->getQuestion();
foreach ($question->getChoices() as $key => $value) {
$width = $maxWidth - $this->strlen($key);
$messages[] = ' [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
}
$output->writeln($messages);
$message = $question->getPrompt();
}
$output->write($message);
}
/**
* Outputs an error message.
*
* @param OutputInterface $output
* @param \Exception $error
*/
protected function writeError(OutputInterface $output, \Exception $error)
{
if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
$message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
} else {
$message = '<error>'.$error->getMessage().'</error>';
}
$output->writeln($message);
}
/**
* Autocompletes a question.
*
@@ -193,7 +226,7 @@ class QuestionHelper extends Helper
// Backspace Character
if ("\177" === $c) {
if (0 === $numMatches && 0 !== $i) {
$i--;
--$i;
// Move cursor backwards
$output->write("\033[1D");
}
@@ -246,7 +279,7 @@ class QuestionHelper extends Helper
} else {
$output->write($c);
$ret .= $c;
$i++;
++$i;
$numMatches = 0;
$ofs = 0;
@@ -285,7 +318,7 @@ class QuestionHelper extends Helper
*
* @return string The answer
*
* @throws \RuntimeException In case the fallback is deactivated and the response cannot be hidden
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
*/
private function getHiddenResponse(OutputInterface $output, $inputStream)
{
@@ -317,7 +350,7 @@ class QuestionHelper extends Helper
shell_exec(sprintf('stty %s', $sttyMode));
if (false === $value) {
throw new \RuntimeException('Aborted');
throw new RuntimeException('Aborted');
}
$value = trim($value);
@@ -335,7 +368,7 @@ class QuestionHelper extends Helper
return $value;
}
throw new \RuntimeException('Unable to hide the response.');
throw new RuntimeException('Unable to hide the response.');
}
/**
@@ -349,19 +382,13 @@ class QuestionHelper extends Helper
*
* @throws \Exception In case the max number of attempts has been reached and no valid response has been given
*/
private function validateAttempts($interviewer, OutputInterface $output, Question $question)
private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question)
{
$error = null;
$attempts = $question->getMaxAttempts();
while (null === $attempts || $attempts--) {
if (null !== $error) {
if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
$message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
} else {
$message = '<error>'.$error->getMessage().'</error>';
}
$output->writeln($message);
$this->writeError($output, $error);
}
try {

View File

@@ -0,0 +1,107 @@
<?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\Helper;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Symfony Style Guide compliant question helper.
*
* @author Kevin Bond <kevinbond@gmail.com>
*/
class SymfonyQuestionHelper extends QuestionHelper
{
/**
* {@inheritdoc}
*/
public function ask(InputInterface $input, OutputInterface $output, Question $question)
{
$validator = $question->getValidator();
$question->setValidator(function ($value) use ($validator) {
if (null !== $validator) {
$value = $validator($value);
}
// make required
if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
throw new LogicException('A value is required.');
}
return $value;
});
return parent::ask($input, $output, $question);
}
/**
* {@inheritdoc}
*/
protected function writePrompt(OutputInterface $output, Question $question)
{
$text = $question->getQuestion();
$default = $question->getDefault();
switch (true) {
case null === $default:
$text = sprintf(' <info>%s</info>:', $text);
break;
case $question instanceof ConfirmationQuestion:
$text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
break;
case $question instanceof ChoiceQuestion:
$choices = $question->getChoices();
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $choices[$default]);
break;
default:
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $default);
}
$output->writeln($text);
if ($question instanceof ChoiceQuestion) {
$width = max(array_map('strlen', array_keys($question->getChoices())));
foreach ($question->getChoices() as $key => $value) {
$output->writeln(sprintf(" [<comment>%-${width}s</comment>] %s", $key, $value));
}
}
$output->write(' > ');
}
/**
* {@inheritdoc}
*/
protected function writeError(OutputInterface $output, \Exception $error)
{
if ($output instanceof SymfonyStyle) {
$output->newLine();
$output->error($error->getMessage());
return;
}
parent::writeError($output, $error);
}
}

663
vendor/symfony/console/Helper/Table.php vendored Normal file
View File

@@ -0,0 +1,663 @@
<?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\Helper;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* Provides helpers to display a table.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Саша Стаменковић <umpirsky@gmail.com>
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
* @author Max Grigorian <maxakawizard@gmail.com>
*/
class Table
{
/**
* Table headers.
*
* @var array
*/
private $headers = array();
/**
* Table rows.
*
* @var array
*/
private $rows = array();
/**
* Column widths cache.
*
* @var array
*/
private $columnWidths = array();
/**
* Number of columns cache.
*
* @var array
*/
private $numberOfColumns;
/**
* @var OutputInterface
*/
private $output;
/**
* @var TableStyle
*/
private $style;
/**
* @var array
*/
private $columnStyles = array();
private static $styles;
public function __construct(OutputInterface $output)
{
$this->output = $output;
if (!self::$styles) {
self::$styles = self::initStyles();
}
$this->setStyle('default');
}
/**
* Sets a style definition.
*
* @param string $name The style name
* @param TableStyle $style A TableStyle instance
*/
public static function setStyleDefinition($name, TableStyle $style)
{
if (!self::$styles) {
self::$styles = self::initStyles();
}
self::$styles[$name] = $style;
}
/**
* Gets a style definition by name.
*
* @param string $name The style name
*
* @return TableStyle A TableStyle instance
*/
public static function getStyleDefinition($name)
{
if (!self::$styles) {
self::$styles = self::initStyles();
}
if (!self::$styles[$name]) {
throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
}
return self::$styles[$name];
}
/**
* Sets table style.
*
* @param TableStyle|string $name The style name or a TableStyle instance
*
* @return Table
*/
public function setStyle($name)
{
if ($name instanceof TableStyle) {
$this->style = $name;
} elseif (isset(self::$styles[$name])) {
$this->style = self::$styles[$name];
} else {
throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
}
return $this;
}
/**
* Gets the current table style.
*
* @return TableStyle
*/
public function getStyle()
{
return $this->style;
}
/**
* Sets table column style.
*
* @param int $columnIndex Column index
* @param TableStyle|string $name The style name or a TableStyle instance
*
* @return Table
*/
public function setColumnStyle($columnIndex, $name)
{
$columnIndex = intval($columnIndex);
if ($name instanceof TableStyle) {
$this->columnStyles[$columnIndex] = $name;
} elseif (isset(self::$styles[$name])) {
$this->columnStyles[$columnIndex] = self::$styles[$name];
} else {
throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
}
return $this;
}
/**
* Gets the current style for a column.
*
* If style was not set, it returns the global table style.
*
* @param int $columnIndex Column index
*
* @return TableStyle
*/
public function getColumnStyle($columnIndex)
{
if (isset($this->columnStyles[$columnIndex])) {
return $this->columnStyles[$columnIndex];
}
return $this->getStyle();
}
public function setHeaders(array $headers)
{
$headers = array_values($headers);
if (!empty($headers) && !is_array($headers[0])) {
$headers = array($headers);
}
$this->headers = $headers;
return $this;
}
public function setRows(array $rows)
{
$this->rows = array();
return $this->addRows($rows);
}
public function addRows(array $rows)
{
foreach ($rows as $row) {
$this->addRow($row);
}
return $this;
}
public function addRow($row)
{
if ($row instanceof TableSeparator) {
$this->rows[] = $row;
return $this;
}
if (!is_array($row)) {
throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
}
$this->rows[] = array_values($row);
return $this;
}
public function setRow($column, array $row)
{
$this->rows[$column] = $row;
return $this;
}
/**
* Renders table to output.
*
* Example:
* +---------------+-----------------------+------------------+
* | ISBN | Title | Author |
* +---------------+-----------------------+------------------+
* | 99921-58-10-7 | Divine Comedy | Dante Alighieri |
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
* | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
* +---------------+-----------------------+------------------+
*/
public function render()
{
$this->calculateNumberOfColumns();
$rows = $this->buildTableRows($this->rows);
$headers = $this->buildTableRows($this->headers);
$this->calculateColumnsWidth(array_merge($headers, $rows));
$this->renderRowSeparator();
if (!empty($headers)) {
foreach ($headers as $header) {
$this->renderRow($header, $this->style->getCellHeaderFormat());
$this->renderRowSeparator();
}
}
foreach ($rows as $row) {
if ($row instanceof TableSeparator) {
$this->renderRowSeparator();
} else {
$this->renderRow($row, $this->style->getCellRowFormat());
}
}
if (!empty($rows)) {
$this->renderRowSeparator();
}
$this->cleanup();
}
/**
* Renders horizontal header separator.
*
* Example: +-----+-----------+-------+
*/
private function renderRowSeparator()
{
if (0 === $count = $this->numberOfColumns) {
return;
}
if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
return;
}
$markup = $this->style->getCrossingChar();
for ($column = 0; $column < $count; ++$column) {
$markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
}
$this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
}
/**
* Renders vertical column separator.
*/
private function renderColumnSeparator()
{
return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
}
/**
* Renders table row.
*
* Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
*
* @param array $row
* @param string $cellFormat
*/
private function renderRow(array $row, $cellFormat)
{
if (empty($row)) {
return;
}
$rowContent = $this->renderColumnSeparator();
foreach ($this->getRowColumns($row) as $column) {
$rowContent .= $this->renderCell($row, $column, $cellFormat);
$rowContent .= $this->renderColumnSeparator();
}
$this->output->writeln($rowContent);
}
/**
* Renders table cell with padding.
*
* @param array $row
* @param int $column
* @param string $cellFormat
*/
private function renderCell(array $row, $column, $cellFormat)
{
$cell = isset($row[$column]) ? $row[$column] : '';
$width = $this->columnWidths[$column];
if ($cell instanceof TableCell && $cell->getColspan() > 1) {
// add the width of the following columns(numbers of colspan).
foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
$width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
}
}
// str_pad won't work properly with multi-byte strings, we need to fix the padding
if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
$width += strlen($cell) - mb_strwidth($cell, $encoding);
}
$style = $this->getColumnStyle($column);
if ($cell instanceof TableSeparator) {
return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
}
$width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
$content = sprintf($style->getCellRowContentFormat(), $cell);
return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
}
/**
* Calculate number of columns for this table.
*/
private function calculateNumberOfColumns()
{
if (null !== $this->numberOfColumns) {
return;
}
$columns = array(0);
foreach (array_merge($this->headers, $this->rows) as $row) {
if ($row instanceof TableSeparator) {
continue;
}
$columns[] = $this->getNumberOfColumns($row);
}
$this->numberOfColumns = max($columns);
}
private function buildTableRows($rows)
{
$unmergedRows = array();
for ($rowKey = 0; $rowKey < count($rows); ++$rowKey) {
$rows = $this->fillNextRows($rows, $rowKey);
// Remove any new line breaks and replace it with a new line
foreach ($rows[$rowKey] as $column => $cell) {
if (!strstr($cell, "\n")) {
continue;
}
$lines = explode("\n", $cell);
foreach ($lines as $lineKey => $line) {
if ($cell instanceof TableCell) {
$line = new TableCell($line, array('colspan' => $cell->getColspan()));
}
if (0 === $lineKey) {
$rows[$rowKey][$column] = $line;
} else {
$unmergedRows[$rowKey][$lineKey][$column] = $line;
}
}
}
}
$tableRows = array();
foreach ($rows as $rowKey => $row) {
$tableRows[] = $this->fillCells($row);
if (isset($unmergedRows[$rowKey])) {
$tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
}
}
return $tableRows;
}
/**
* fill rows that contains rowspan > 1.
*
* @param array $rows
* @param int $line
*
* @return array
*/
private function fillNextRows($rows, $line)
{
$unmergedRows = array();
foreach ($rows[$line] as $column => $cell) {
if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
$nbLines = $cell->getRowspan() - 1;
$lines = array($cell);
if (strstr($cell, "\n")) {
$lines = explode("\n", $cell);
$nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
$rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
unset($lines[0]);
}
// create a two dimensional array (rowspan x colspan)
$unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, ''), $unmergedRows);
foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
$value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
$unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
}
}
}
foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
// we need to know if $unmergedRow will be merged or inserted into $rows
if (isset($rows[$unmergedRowKey]) && is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
foreach ($unmergedRow as $cellKey => $cell) {
// insert cell into row at cellKey position
array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
}
} else {
$row = $this->copyRow($rows, $unmergedRowKey - 1);
foreach ($unmergedRow as $column => $cell) {
if (!empty($cell)) {
$row[$column] = $unmergedRow[$column];
}
}
array_splice($rows, $unmergedRowKey, 0, array($row));
}
}
return $rows;
}
/**
* fill cells for a row that contains colspan > 1.
*
* @param array $row
*
* @return array
*/
private function fillCells($row)
{
$newRow = array();
foreach ($row as $column => $cell) {
$newRow[] = $cell;
if ($cell instanceof TableCell && $cell->getColspan() > 1) {
foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
// insert empty value at column position
$newRow[] = '';
}
}
}
return $newRow ?: $row;
}
/**
* @param array $rows
* @param int $line
*
* @return array
*/
private function copyRow($rows, $line)
{
$row = $rows[$line];
foreach ($row as $cellKey => $cellValue) {
$row[$cellKey] = '';
if ($cellValue instanceof TableCell) {
$row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
}
}
return $row;
}
/**
* Gets number of columns by row.
*
* @param array $row
*
* @return int
*/
private function getNumberOfColumns(array $row)
{
$columns = count($row);
foreach ($row as $column) {
$columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
}
return $columns;
}
/**
* Gets list of columns for the given row.
*
* @param array $row
*
* @return array
*/
private function getRowColumns($row)
{
$columns = range(0, $this->numberOfColumns - 1);
foreach ($row as $cellKey => $cell) {
if ($cell instanceof TableCell && $cell->getColspan() > 1) {
// exclude grouped columns.
$columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
}
}
return $columns;
}
/**
* Calculates columns widths.
*
* @param array $rows
*/
private function calculateColumnsWidth($rows)
{
for ($column = 0; $column < $this->numberOfColumns; ++$column) {
$lengths = array();
foreach ($rows as $row) {
if ($row instanceof TableSeparator) {
continue;
}
foreach ($row as $i => $cell) {
if ($cell instanceof TableCell) {
$textLength = strlen($cell);
if ($textLength > 0) {
$contentColumns = str_split($cell, ceil($textLength / $cell->getColspan()));
foreach ($contentColumns as $position => $content) {
$row[$i + $position] = $content;
}
}
}
}
$lengths[] = $this->getCellWidth($row, $column);
}
$this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
}
}
/**
* Gets column width.
*
* @return int
*/
private function getColumnSeparatorWidth()
{
return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
}
/**
* Gets cell width.
*
* @param array $row
* @param int $column
*
* @return int
*/
private function getCellWidth(array $row, $column)
{
if (isset($row[$column])) {
$cell = $row[$column];
$cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
return $cellWidth;
}
return 0;
}
/**
* Called after rendering to cleanup cache data.
*/
private function cleanup()
{
$this->columnWidths = array();
$this->numberOfColumns = null;
}
private static function initStyles()
{
$borderless = new TableStyle();
$borderless
->setHorizontalBorderChar('=')
->setVerticalBorderChar(' ')
->setCrossingChar(' ')
;
$compact = new TableStyle();
$compact
->setHorizontalBorderChar('')
->setVerticalBorderChar(' ')
->setCrossingChar('')
->setCellRowContentFormat('%s')
;
$styleGuide = new TableStyle();
$styleGuide
->setHorizontalBorderChar('-')
->setVerticalBorderChar(' ')
->setCrossingChar(' ')
->setCellHeaderFormat('%s')
;
return array(
'default' => new TableStyle(),
'borderless' => $borderless,
'compact' => $compact,
'symfony-style-guide' => $styleGuide,
);
}
}

View File

@@ -0,0 +1,79 @@
<?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\Helper;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
*/
class TableCell
{
/**
* @var string
*/
private $value;
/**
* @var array
*/
private $options = array(
'rowspan' => 1,
'colspan' => 1,
);
/**
* @param string $value
* @param array $options
*/
public function __construct($value = '', array $options = array())
{
$this->value = $value;
// check option names
if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
}
$this->options = array_merge($this->options, $options);
}
/**
* Returns the cell value.
*
* @return string
*/
public function __toString()
{
return $this->value;
}
/**
* Gets number of colspan.
*
* @return int
*/
public function getColspan()
{
return (int) $this->options['colspan'];
}
/**
* Gets number of rowspan.
*
* @return int
*/
public function getRowspan()
{
return (int) $this->options['rowspan'];
}
}

View File

@@ -16,6 +16,14 @@ namespace Symfony\Component\Console\Helper;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class TableSeparator
class TableSeparator extends TableCell
{
/**
* @param string $value
* @param array $options
*/
public function __construct(array $options = array())
{
parent::__construct('', $options);
}
}

View File

@@ -11,6 +11,9 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
/**
* Defines the styles for a Table.
*
@@ -39,7 +42,7 @@ class TableStyle
public function setPaddingChar($paddingChar)
{
if (!$paddingChar) {
throw new \LogicException('The padding char must not be empty');
throw new LogicException('The padding char must not be empty');
}
$this->paddingChar = $paddingChar;
@@ -234,6 +237,10 @@ class TableStyle
*/
public function setPadType($padType)
{
if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
}
$this->padType = $padType;
return $this;

View File

@@ -11,6 +11,8 @@
namespace Symfony\Component\Console\Input;
use Symfony\Component\Console\Exception\RuntimeException;
/**
* ArgvInput represents an input coming from the CLI arguments.
*
@@ -35,8 +37,6 @@ namespace Symfony\Component\Console\Input;
*
* @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
* @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
*
* @api
*/
class ArgvInput extends Input
{
@@ -48,8 +48,6 @@ class ArgvInput extends Input
*
* @param array $argv An array of parameters from the CLI (in the argv format)
* @param InputDefinition $definition A InputDefinition instance
*
* @api
*/
public function __construct(array $argv = null, InputDefinition $definition = null)
{
@@ -118,14 +116,14 @@ class ArgvInput extends Input
*
* @param string $name The current token
*
* @throws \RuntimeException When option given doesn't exist
* @throws RuntimeException When option given doesn't exist
*/
private function parseShortOptionSet($name)
{
$len = strlen($name);
for ($i = 0; $i < $len; ++$i) {
if (!$this->definition->hasShortcut($name[$i])) {
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
}
$option = $this->definition->getOptionForShortcut($name[$i]);
@@ -160,7 +158,7 @@ class ArgvInput extends Input
*
* @param string $token The current token
*
* @throws \RuntimeException When too many arguments are given
* @throws RuntimeException When too many arguments are given
*/
private function parseArgument($token)
{
@@ -178,7 +176,7 @@ class ArgvInput extends Input
// unexpected argument
} else {
throw new \RuntimeException('Too many arguments.');
throw new RuntimeException('Too many arguments.');
}
}
@@ -188,12 +186,12 @@ class ArgvInput extends Input
* @param string $shortcut The short option key
* @param mixed $value The value for the option
*
* @throws \RuntimeException When option given doesn't exist
* @throws RuntimeException When option given doesn't exist
*/
private function addShortOption($shortcut, $value)
{
if (!$this->definition->hasShortcut($shortcut)) {
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
}
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
@@ -205,23 +203,23 @@ class ArgvInput extends Input
* @param string $name The long option key
* @param mixed $value The value for the option
*
* @throws \RuntimeException When option given doesn't exist
* @throws RuntimeException When option given doesn't exist
*/
private function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
}
$option = $this->definition->getOption($name);
// Convert false values (from a previous call to substr()) to null
if (false === $value) {
// Convert empty values to null
if (!isset($value[0])) {
$value = null;
}
if (null !== $value && !$option->acceptValue()) {
throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
}
if (null === $value && $option->acceptValue() && count($this->parsed)) {
@@ -239,7 +237,7 @@ class ArgvInput extends Input
if (null === $value) {
if ($option->isValueRequired()) {
throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
}
if (!$option->isArray()) {
@@ -276,15 +274,19 @@ class ArgvInput extends Input
* This method is to be used to introspect the input parameters
* before they have been validated. It must be used carefully.
*
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
*
* @return bool true if the value is contained in the raw parameters
*/
public function hasParameterOption($values)
public function hasParameterOption($values, $onlyParams = false)
{
$values = (array) $values;
foreach ($this->tokens as $token) {
if ($onlyParams && $token === '--') {
return false;
}
foreach ($values as $value) {
if ($token === $value || 0 === strpos($token, $value.'=')) {
return true;
@@ -301,18 +303,22 @@ class ArgvInput extends Input
* This method is to be used to introspect the input parameters
* before they have been validated. It must be used carefully.
*
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param mixed $default The default value to return if no result is found
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param mixed $default The default value to return if no result is found
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
*
* @return mixed The option value
*/
public function getParameterOption($values, $default = false)
public function getParameterOption($values, $default = false, $onlyParams = false)
{
$values = (array) $values;
$tokens = $this->tokens;
while (0 < count($tokens)) {
$token = array_shift($tokens);
if ($onlyParams && $token === '--') {
return false;
}
foreach ($values as $value) {
if ($token === $value || 0 === strpos($token, $value.'=')) {
@@ -335,14 +341,13 @@ class ArgvInput extends Input
*/
public function __toString()
{
$self = $this;
$tokens = array_map(function ($token) use ($self) {
$tokens = array_map(function ($token) {
if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
return $match[1].$self->escapeToken($match[2]);
return $match[1].$this->escapeToken($match[2]);
}
if ($token && $token[0] !== '-') {
return $self->escapeToken($token);
return $this->escapeToken($token);
}
return $token;

View File

@@ -11,6 +11,9 @@
namespace Symfony\Component\Console\Input;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\InvalidOptionException;
/**
* ArrayInput represents an input provided as an array.
*
@@ -19,8 +22,6 @@ namespace Symfony\Component\Console\Input;
* $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class ArrayInput extends Input
{
@@ -31,8 +32,6 @@ class ArrayInput extends Input
*
* @param array $parameters An array of parameters
* @param InputDefinition $definition A InputDefinition instance
*
* @api
*/
public function __construct(array $parameters, InputDefinition $definition = null)
{
@@ -63,11 +62,12 @@ class ArrayInput extends Input
* This method is to be used to introspect the input parameters
* before they have been validated. It must be used carefully.
*
* @param string|array $values The values to look for in the raw parameters (can be an array)
* @param string|array $values The values to look for in the raw parameters (can be an array)
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
*
* @return bool true if the value is contained in the raw parameters
*/
public function hasParameterOption($values)
public function hasParameterOption($values, $onlyParams = false)
{
$values = (array) $values;
@@ -76,6 +76,10 @@ class ArrayInput extends Input
$v = $k;
}
if ($onlyParams && $v === '--') {
return false;
}
if (in_array($v, $values)) {
return true;
}
@@ -90,16 +94,21 @@ class ArrayInput extends Input
* This method is to be used to introspect the input parameters
* before they have been validated. It must be used carefully.
*
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param mixed $default The default value to return if no result is found
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param mixed $default The default value to return if no result is found
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
*
* @return mixed The option value
*/
public function getParameterOption($values, $default = false)
public function getParameterOption($values, $default = false, $onlyParams = false)
{
$values = (array) $values;
foreach ($this->parameters as $k => $v) {
if ($onlyParams && ($k === '--' || (is_int($k) && $v === '--'))) {
return false;
}
if (is_int($k)) {
if (in_array($v, $values)) {
return true;
@@ -137,6 +146,9 @@ class ArrayInput extends Input
protected function parse()
{
foreach ($this->parameters as $key => $value) {
if ($key === '--') {
return;
}
if (0 === strpos($key, '--')) {
$this->addLongOption(substr($key, 2), $value);
} elseif ('-' === $key[0]) {
@@ -153,12 +165,12 @@ class ArrayInput extends Input
* @param string $shortcut The short option key
* @param mixed $value The value for the option
*
* @throws \InvalidArgumentException When option given doesn't exist
* @throws InvalidOptionException When option given doesn't exist
*/
private function addShortOption($shortcut, $value)
{
if (!$this->definition->hasShortcut($shortcut)) {
throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
}
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
@@ -170,20 +182,20 @@ class ArrayInput extends Input
* @param string $name The long option key
* @param mixed $value The value for the option
*
* @throws \InvalidArgumentException When option given doesn't exist
* @throws \InvalidArgumentException When a required value is missing
* @throws InvalidOptionException When option given doesn't exist
* @throws InvalidOptionException When a required value is missing
*/
private function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
}
$option = $this->definition->getOption($name);
if (null === $value) {
if ($option->isValueRequired()) {
throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name));
throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
}
$value = $option->isValueOptional() ? $option->getDefault() : true;
@@ -198,12 +210,12 @@ class ArrayInput extends Input
* @param string $name The argument name
* @param mixed $value The value for the argument
*
* @throws \InvalidArgumentException When argument given doesn't exist
* @throws InvalidArgumentException When argument given doesn't exist
*/
private function addArgument($name, $value)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
$this->arguments[$name] = $value;

View File

@@ -11,6 +11,9 @@
namespace Symfony\Component\Console\Input;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
/**
* Input is the base class for all concrete Input classes.
*
@@ -69,12 +72,19 @@ abstract class Input implements InputInterface
/**
* Validates the input.
*
* @throws \RuntimeException When not enough arguments are given
* @throws RuntimeException When not enough arguments are given
*/
public function validate()
{
if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
throw new \RuntimeException('Not enough arguments.');
$definition = $this->definition;
$givenArguments = $this->arguments;
$missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
});
if (count($missingArguments) > 0) {
throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
}
}
@@ -115,12 +125,12 @@ abstract class Input implements InputInterface
*
* @return mixed The argument value
*
* @throws \InvalidArgumentException When argument given doesn't exist
* @throws InvalidArgumentException When argument given doesn't exist
*/
public function getArgument($name)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
@@ -132,12 +142,12 @@ abstract class Input implements InputInterface
* @param string $name The argument name
* @param string $value The argument value
*
* @throws \InvalidArgumentException When argument given doesn't exist
* @throws InvalidArgumentException When argument given doesn't exist
*/
public function setArgument($name, $value)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
$this->arguments[$name] = $value;
@@ -172,12 +182,12 @@ abstract class Input implements InputInterface
*
* @return mixed The option value
*
* @throws \InvalidArgumentException When option given doesn't exist
* @throws InvalidArgumentException When option given doesn't exist
*/
public function getOption($name)
{
if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
}
return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
@@ -189,12 +199,12 @@ abstract class Input implements InputInterface
* @param string $name The option name
* @param string|bool $value The option value
*
* @throws \InvalidArgumentException When option given doesn't exist
* @throws InvalidArgumentException When option given doesn't exist
*/
public function setOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
}
$this->options[$name] = $value;

View File

@@ -11,12 +11,13 @@
namespace Symfony\Component\Console\Input;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
/**
* Represents a command line argument.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class InputArgument
{
@@ -37,16 +38,14 @@ class InputArgument
* @param string $description A description text
* @param mixed $default The default value (for self::OPTIONAL mode only)
*
* @throws \InvalidArgumentException When argument mode is not valid
*
* @api
* @throws InvalidArgumentException When argument mode is not valid
*/
public function __construct($name, $mode = null, $description = '', $default = null)
{
if (null === $mode) {
$mode = self::OPTIONAL;
} elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
}
$this->name = $name;
@@ -91,19 +90,19 @@ class InputArgument
*
* @param mixed $default The default value
*
* @throws \LogicException When incorrect default value is given
* @throws LogicException When incorrect default value is given
*/
public function setDefault($default = null)
{
if (self::REQUIRED === $this->mode && null !== $default) {
throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
}
if ($this->isArray()) {
if (null === $default) {
$default = array();
} elseif (!is_array($default)) {
throw new \LogicException('A default value for an array argument must be an array.');
throw new LogicException('A default value for an array argument must be an array.');
}
}

View File

@@ -11,9 +11,8 @@
namespace Symfony\Component\Console\Input;
use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
/**
* A InputDefinition represents a set of valid command line arguments and options.
@@ -26,8 +25,6 @@ use Symfony\Component\Console\Output\BufferedOutput;
* ));
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class InputDefinition
{
@@ -42,8 +39,6 @@ class InputDefinition
* Constructor.
*
* @param array $definition An array of InputArgument and InputOption instance
*
* @api
*/
public function __construct(array $definition = array())
{
@@ -54,8 +49,6 @@ class InputDefinition
* Sets the definition of the input.
*
* @param array $definition The definition array
*
* @api
*/
public function setDefinition(array $definition)
{
@@ -77,8 +70,6 @@ class InputDefinition
* Sets the InputArgument objects.
*
* @param InputArgument[] $arguments An array of InputArgument objects
*
* @api
*/
public function setArguments($arguments = array())
{
@@ -93,8 +84,6 @@ class InputDefinition
* Adds an array of InputArgument objects.
*
* @param InputArgument[] $arguments An array of InputArgument objects
*
* @api
*/
public function addArguments($arguments = array())
{
@@ -110,22 +99,20 @@ class InputDefinition
*
* @param InputArgument $argument An InputArgument object
*
* @throws \LogicException When incorrect argument is given
*
* @api
* @throws LogicException When incorrect argument is given
*/
public function addArgument(InputArgument $argument)
{
if (isset($this->arguments[$argument->getName()])) {
throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
}
if ($this->hasAnArrayArgument) {
throw new \LogicException('Cannot add an argument after an array argument.');
throw new LogicException('Cannot add an argument after an array argument.');
}
if ($argument->isRequired() && $this->hasOptional) {
throw new \LogicException('Cannot add a required argument after an optional one.');
throw new LogicException('Cannot add a required argument after an optional one.');
}
if ($argument->isArray()) {
@@ -148,14 +135,12 @@ class InputDefinition
*
* @return InputArgument An InputArgument object
*
* @throws \InvalidArgumentException When argument given doesn't exist
*
* @api
* @throws InvalidArgumentException When argument given doesn't exist
*/
public function getArgument($name)
{
if (!$this->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
@@ -169,8 +154,6 @@ class InputDefinition
* @param string|int $name The InputArgument name or position
*
* @return bool true if the InputArgument object exists, false otherwise
*
* @api
*/
public function hasArgument($name)
{
@@ -183,8 +166,6 @@ class InputDefinition
* Gets the array of InputArgument objects.
*
* @return InputArgument[] An array of InputArgument objects
*
* @api
*/
public function getArguments()
{
@@ -230,8 +211,6 @@ class InputDefinition
* Sets the InputOption objects.
*
* @param InputOption[] $options An array of InputOption objects
*
* @api
*/
public function setOptions($options = array())
{
@@ -244,8 +223,6 @@ class InputDefinition
* Adds an array of InputOption objects.
*
* @param InputOption[] $options An array of InputOption objects
*
* @api
*/
public function addOptions($options = array())
{
@@ -259,20 +236,18 @@ class InputDefinition
*
* @param InputOption $option An InputOption object
*
* @throws \LogicException When option given already exist
*
* @api
* @throws LogicException When option given already exist
*/
public function addOption(InputOption $option)
{
if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
}
if ($option->getShortcut()) {
foreach (explode('|', $option->getShortcut()) as $shortcut) {
if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
}
}
}
@@ -292,14 +267,12 @@ class InputDefinition
*
* @return InputOption A InputOption object
*
* @throws \InvalidArgumentException When option given doesn't exist
*
* @api
* @throws InvalidArgumentException When option given doesn't exist
*/
public function getOption($name)
{
if (!$this->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
}
return $this->options[$name];
@@ -311,8 +284,6 @@ class InputDefinition
* @param string $name The InputOption name
*
* @return bool true if the InputOption object exists, false otherwise
*
* @api
*/
public function hasOption($name)
{
@@ -323,8 +294,6 @@ class InputDefinition
* Gets the array of InputOption objects.
*
* @return InputOption[] An array of InputOption objects
*
* @api
*/
public function getOptions()
{
@@ -377,12 +346,12 @@ class InputDefinition
*
* @return string The InputOption name
*
* @throws \InvalidArgumentException When option given does not exist
* @throws InvalidArgumentException When option given does not exist
*/
private function shortcutToName($shortcut)
{
if (!isset($this->shortcuts[$shortcut])) {
throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
}
return $this->shortcuts[$shortcut];
@@ -391,63 +360,52 @@ class InputDefinition
/**
* Gets the synopsis.
*
* @param bool $short Whether to return the short version (with options folded) or not
*
* @return string The synopsis
*/
public function getSynopsis()
public function getSynopsis($short = false)
{
$elements = array();
foreach ($this->getOptions() as $option) {
$shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
$elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
if ($short && $this->getOptions()) {
$elements[] = '[options]';
} elseif (!$short) {
foreach ($this->getOptions() as $option) {
$value = '';
if ($option->acceptValue()) {
$value = sprintf(
' %s%s%s',
$option->isValueOptional() ? '[' : '',
strtoupper($option->getName()),
$option->isValueOptional() ? ']' : ''
);
}
$shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
$elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
}
}
if (count($elements) && $this->getArguments()) {
$elements[] = '[--]';
}
foreach ($this->getArguments() as $argument) {
$elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
$element = '<'.$argument->getName().'>';
if (!$argument->isRequired()) {
$element = '['.$element.']';
} elseif ($argument->isArray()) {
$element = $element.' ('.$element.')';
}
if ($argument->isArray()) {
$elements[] = sprintf('... [%sN]', $argument->getName());
$element .= '...';
}
$elements[] = $element;
}
return implode(' ', $elements);
}
/**
* Returns a textual representation of the InputDefinition.
*
* @return string A string representing the InputDefinition
*
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asText()
{
$descriptor = new TextDescriptor();
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
$descriptor->describe($output, $this, array('raw_output' => true));
return $output->fetch();
}
/**
* Returns an XML representation of the InputDefinition.
*
* @param bool $asDom Whether to return a DOM or an XML string
*
* @return string|\DOMDocument An XML string representing the InputDefinition
*
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
*/
public function asXml($asDom = false)
{
$descriptor = new XmlDescriptor();
if ($asDom) {
return $descriptor->getInputDefinitionDocument($this);
}
$output = new BufferedOutput();
$descriptor->describe($output, $this);
return $output->fetch();
}
}

View File

@@ -31,11 +31,12 @@ interface InputInterface
* This method is to be used to introspect the input parameters
* before they have been validated. It must be used carefully.
*
* @param string|array $values The values to look for in the raw parameters (can be an array)
* @param string|array $values The values to look for in the raw parameters (can be an array)
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
*
* @return bool true if the value is contained in the raw parameters
*/
public function hasParameterOption($values);
public function hasParameterOption($values, $onlyParams = false);
/**
* Returns the value of a raw option (not parsed).
@@ -43,12 +44,13 @@ interface InputInterface
* This method is to be used to introspect the input parameters
* before they have been validated. It must be used carefully.
*
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param mixed $default The default value to return if no result is found
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param mixed $default The default value to return if no result is found
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
*
* @return mixed The option value
*/
public function getParameterOption($values, $default = false);
public function getParameterOption($values, $default = false, $onlyParams = false);
/**
* Binds the current Input instance with the given arguments and options.
@@ -88,7 +90,7 @@ interface InputInterface
* @param string $name The argument name
* @param string $value The argument value
*
* @throws \InvalidArgumentException When argument given doesn't exist
* @throws InvalidArgumentException When argument given doesn't exist
*/
public function setArgument($name, $value);
@@ -123,7 +125,7 @@ interface InputInterface
* @param string $name The option name
* @param string|bool $value The option value
*
* @throws \InvalidArgumentException When option given doesn't exist
* @throws InvalidArgumentException When option given doesn't exist
*/
public function setOption($name, $value);

View File

@@ -11,12 +11,13 @@
namespace Symfony\Component\Console\Input;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
/**
* Represents a command line option.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class InputOption
{
@@ -38,11 +39,9 @@ class InputOption
* @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
* @param int $mode The option mode: One of the VALUE_* constants
* @param string $description A description text
* @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE)
* @param mixed $default The default value (must be null for self::VALUE_NONE)
*
* @throws \InvalidArgumentException If option mode is invalid or incompatible
*
* @api
* @throws InvalidArgumentException If option mode is invalid or incompatible
*/
public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
{
@@ -51,7 +50,7 @@ class InputOption
}
if (empty($name)) {
throw new \InvalidArgumentException('An option name cannot be empty.');
throw new InvalidArgumentException('An option name cannot be empty.');
}
if (empty($shortcut)) {
@@ -67,14 +66,14 @@ class InputOption
$shortcut = implode('|', $shortcuts);
if (empty($shortcut)) {
throw new \InvalidArgumentException('An option shortcut cannot be empty.');
throw new InvalidArgumentException('An option shortcut cannot be empty.');
}
}
if (null === $mode) {
$mode = self::VALUE_NONE;
} elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
}
$this->name = $name;
@@ -83,7 +82,7 @@ class InputOption
$this->description = $description;
if ($this->isArray() && !$this->acceptValue()) {
throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
}
$this->setDefault($default);
@@ -154,19 +153,19 @@ class InputOption
*
* @param mixed $default The default value
*
* @throws \LogicException When incorrect default value is given
* @throws LogicException When incorrect default value is given
*/
public function setDefault($default = null)
{
if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
}
if ($this->isArray()) {
if (null === $default) {
$default = array();
} elseif (!is_array($default)) {
throw new \LogicException('A default value for an array option must be an array.');
throw new LogicException('A default value for an array option must be an array.');
}
}

View File

@@ -11,6 +11,8 @@
namespace Symfony\Component\Console\Input;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* StringInput represents an input provided as a string.
*
@@ -19,8 +21,6 @@ namespace Symfony\Component\Console\Input;
* $input = new StringInput('foo --bar="foobar"');
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class StringInput extends ArgvInput
{
@@ -30,22 +30,13 @@ class StringInput extends ArgvInput
/**
* Constructor.
*
* @param string $input An array of parameters from the CLI (in the argv format)
* @param InputDefinition $definition A InputDefinition instance
*
* @deprecated The second argument is deprecated as it does not work (will be removed in 3.0), use 'bind' method instead
*
* @api
* @param string $input An array of parameters from the CLI (in the argv format)
*/
public function __construct($input, InputDefinition $definition = null)
public function __construct($input)
{
parent::__construct(array(), null);
parent::__construct(array());
$this->setTokens($this->tokenize($input));
if (null !== $definition) {
$this->bind($definition);
}
}
/**
@@ -55,7 +46,7 @@ class StringInput extends ArgvInput
*
* @return array An array of tokens
*
* @throws \InvalidArgumentException When unable to parse input (should never happen)
* @throws InvalidArgumentException When unable to parse input (should never happen)
*/
private function tokenize($input)
{
@@ -72,7 +63,7 @@ class StringInput extends ArgvInput
$tokens[] = stripcslashes($match[1]);
} else {
// should never happen
throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
}
$cursor += strlen($match[0]);

View File

@@ -18,9 +18,10 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
/**
* PSR-3 compliant console logger
* PSR-3 compliant console logger.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*
* @link http://www.php-fig.org/psr/psr-3/
*/
class ConsoleLogger extends AbstractLogger
@@ -93,7 +94,7 @@ class ConsoleLogger extends AbstractLogger
}
/**
* Interpolates context values into the message placeholders
* Interpolates context values into the message placeholders.
*
* @author PHP Framework Interoperability Group
*

View File

@@ -25,8 +25,6 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
* $output = new StreamOutput(fopen('php://stdout', 'w'));
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
{
@@ -41,14 +39,17 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
* @param bool|null $decorated Whether to decorate messages (null for auto-guessing)
* @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
*
* @api
*/
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
{
parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
$actualDecorated = $this->isDecorated();
$this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
if (null === $decorated) {
$this->setDecorated($actualDecorated && $this->stderr->isDecorated());
}
}
/**
@@ -124,7 +125,13 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
*/
private function isRunningOS400()
{
return 'OS400' === php_uname('s');
$checks = array(
function_exists('php_uname') ? php_uname('s') : '',
getenv('OSTYPE'),
PHP_OS,
);
return false !== stripos(implode(';', $checks), 'OS400');
}
/**

View File

@@ -21,8 +21,6 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Tobias Schultze <http://tobion.de>
*
* @api
*/
class NullOutput implements OutputInterface
{
@@ -98,7 +96,7 @@ class NullOutput implements OutputInterface
/**
* {@inheritdoc}
*/
public function writeln($messages, $type = self::OUTPUT_NORMAL)
public function writeln($messages, $options = self::OUTPUT_NORMAL)
{
// do nothing
}
@@ -106,7 +104,7 @@ class NullOutput implements OutputInterface
/**
* {@inheritdoc}
*/
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
{
// do nothing
}

View File

@@ -26,8 +26,6 @@ use Symfony\Component\Console\Formatter\OutputFormatter;
* * quiet: -q (no output)
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
abstract class Output implements OutputInterface
{
@@ -40,8 +38,6 @@ abstract class Output implements OutputInterface
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
* @param bool $decorated Whether to decorate messages
* @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
*
* @api
*/
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
{
@@ -121,22 +117,28 @@ abstract class Output implements OutputInterface
/**
* {@inheritdoc}
*/
public function writeln($messages, $type = self::OUTPUT_NORMAL)
public function writeln($messages, $options = self::OUTPUT_NORMAL)
{
$this->write($messages, true, $type);
$this->write($messages, true, $options);
}
/**
* {@inheritdoc}
*/
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
{
if (self::VERBOSITY_QUIET === $this->verbosity) {
$messages = (array) $messages;
$types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
$type = $types & $options ?: self::OUTPUT_NORMAL;
$verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
$verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
if ($verbosity > $this->getVerbosity()) {
return;
}
$messages = (array) $messages;
foreach ($messages as $message) {
switch ($type) {
case OutputInterface::OUTPUT_NORMAL:
@@ -147,8 +149,6 @@ abstract class Output implements OutputInterface
case OutputInterface::OUTPUT_PLAIN:
$message = strip_tags($this->formatter->format($message));
break;
default:
throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
}
$this->doWrite($message, $newline);

View File

@@ -17,52 +17,40 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
* OutputInterface is the interface implemented by all Output classes.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
interface OutputInterface
{
const VERBOSITY_QUIET = 0;
const VERBOSITY_NORMAL = 1;
const VERBOSITY_VERBOSE = 2;
const VERBOSITY_VERY_VERBOSE = 3;
const VERBOSITY_DEBUG = 4;
const VERBOSITY_QUIET = 16;
const VERBOSITY_NORMAL = 32;
const VERBOSITY_VERBOSE = 64;
const VERBOSITY_VERY_VERBOSE = 128;
const VERBOSITY_DEBUG = 256;
const OUTPUT_NORMAL = 0;
const OUTPUT_RAW = 1;
const OUTPUT_PLAIN = 2;
const OUTPUT_NORMAL = 1;
const OUTPUT_RAW = 2;
const OUTPUT_PLAIN = 4;
/**
* Writes a message to the output.
*
* @param string|array $messages The message as an array of lines or a single string
* @param bool $newline Whether to add a newline
* @param int $type The type of output (one of the OUTPUT constants)
*
* @throws \InvalidArgumentException When unknown output type is given
*
* @api
* @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
*/
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL);
public function write($messages, $newline = false, $options = 0);
/**
* Writes a message to the output and adds a newline at the end.
*
* @param string|array $messages The message as an array of lines of a single string
* @param int $type The type of output (one of the OUTPUT constants)
*
* @throws \InvalidArgumentException When unknown output type is given
*
* @api
* @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
*/
public function writeln($messages, $type = self::OUTPUT_NORMAL);
public function writeln($messages, $options = 0);
/**
* Sets the verbosity of the output.
*
* @param int $level The level of verbosity (one of the VERBOSITY constants)
*
* @api
*/
public function setVerbosity($level);
@@ -70,17 +58,41 @@ interface OutputInterface
* Gets the current verbosity of the output.
*
* @return int The current level of verbosity (one of the VERBOSITY constants)
*
* @api
*/
public function getVerbosity();
/**
* Returns whether verbosity is quiet (-q).
*
* @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise
*/
public function isQuiet();
/**
* Returns whether verbosity is verbose (-v).
*
* @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise
*/
public function isVerbose();
/**
* Returns whether verbosity is very verbose (-vv).
*
* @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise
*/
public function isVeryVerbose();
/**
* Returns whether verbosity is debug (-vvv).
*
* @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise
*/
public function isDebug();
/**
* Sets the decorated flag.
*
* @param bool $decorated Whether to decorate the messages
*
* @api
*/
public function setDecorated($decorated);
@@ -88,8 +100,6 @@ interface OutputInterface
* Gets the decorated flag.
*
* @return bool true if the output will decorate messages, false otherwise
*
* @api
*/
public function isDecorated();
@@ -97,8 +107,6 @@ interface OutputInterface
* Sets output formatter.
*
* @param OutputFormatterInterface $formatter
*
* @api
*/
public function setFormatter(OutputFormatterInterface $formatter);
@@ -106,8 +114,6 @@ interface OutputInterface
* Returns current output formatter instance.
*
* @return OutputFormatterInterface
*
* @api
*/
public function getFormatter();
}

View File

@@ -11,6 +11,8 @@
namespace Symfony\Component\Console\Output;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
@@ -25,8 +27,6 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
* $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class StreamOutput extends Output
{
@@ -35,19 +35,17 @@ class StreamOutput extends Output
/**
* Constructor.
*
* @param mixed $stream A stream resource
* @param resource $stream A stream resource
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
* @param bool|null $decorated Whether to decorate messages (null for auto-guessing)
* @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
*
* @throws \InvalidArgumentException When first argument is not a real stream
*
* @api
* @throws InvalidArgumentException When first argument is not a real stream
*/
public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
{
if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
}
$this->stream = $stream;
@@ -74,9 +72,9 @@ class StreamOutput extends Output
*/
protected function doWrite($message, $newline)
{
if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
// should never happen
throw new \RuntimeException('Unable to write output.');
throw new RuntimeException('Unable to write output.');
}
fflush($this->stream);
@@ -87,7 +85,7 @@ class StreamOutput extends Output
*
* Colorization is disabled if not supported by the stream:
*
* - Windows without Ansicon and ConEmu
* - Windows before 10.0.10586 without Ansicon, ConEmu or Mintty
* - non tty consoles
*
* @return bool true if the stream supports colorization, false otherwise
@@ -95,7 +93,11 @@ class StreamOutput extends Output
protected function hasColorSupport()
{
if (DIRECTORY_SEPARATOR === '\\') {
return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
return
0 >= version_compare('10.0.10586', PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD)
|| false !== getenv('ANSICON')
|| 'ON' === getenv('ConEmuANSI')
|| 'xterm' === getenv('TERM');
}
return function_exists('posix_isatty') && @posix_isatty($this->stream);

View File

@@ -11,6 +11,8 @@
namespace Symfony\Component\Console\Question;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* Represents a choice question.
*
@@ -36,7 +38,7 @@ class ChoiceQuestion extends Question
$this->choices = $choices;
$this->setValidator($this->getDefaultValidator());
$this->setAutocompleterValues(array_keys($choices));
$this->setAutocompleterValues($choices);
}
/**
@@ -117,15 +119,16 @@ class ChoiceQuestion extends Question
$choices = $this->choices;
$errorMessage = $this->errorMessage;
$multiselect = $this->multiselect;
$isAssoc = $this->isAssoc($choices);
return function ($selected) use ($choices, $errorMessage, $multiselect) {
return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
// Collapse all spaces.
$selectedChoices = str_replace(' ', '', $selected);
if ($multiselect) {
// Check for a separated comma values
if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
throw new \InvalidArgumentException(sprintf($errorMessage, $selected));
throw new InvalidArgumentException(sprintf($errorMessage, $selected));
}
$selectedChoices = explode(',', $selectedChoices);
} else {
@@ -134,18 +137,41 @@ class ChoiceQuestion extends Question
$multiselectChoices = array();
foreach ($selectedChoices as $value) {
if (empty($choices[$value])) {
throw new \InvalidArgumentException(sprintf($errorMessage, $value));
$results = array();
foreach ($choices as $key => $choice) {
if ($choice === $value) {
$results[] = $key;
}
}
$multiselectChoices[] = $choices[$value];
if (count($results) > 1) {
throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
}
$result = array_search($value, $choices);
if (!$isAssoc) {
if (false !== $result) {
$result = $choices[$result];
} elseif (isset($choices[$value])) {
$result = $choices[$value];
}
} elseif (false === $result && isset($choices[$value])) {
$result = $value;
}
if (false === $result) {
throw new InvalidArgumentException(sprintf($errorMessage, $value));
}
$multiselectChoices[] = (string) $result;
}
if ($multiselect) {
return $multiselectChoices;
}
return $choices[$selected];
return current($multiselectChoices);
};
}
}

View File

@@ -18,16 +18,20 @@ namespace Symfony\Component\Console\Question;
*/
class ConfirmationQuestion extends Question
{
private $trueAnswerRegex;
/**
* Constructor.
*
* @param string $question The question to ask to the user
* @param bool $default The default answer to return, true or false
* @param string $question The question to ask to the user
* @param bool $default The default answer to return, true or false
* @param string $trueAnswerRegex A regex to match the "yes" answer
*/
public function __construct($question, $default = true)
public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
{
parent::__construct($question, (bool) $default);
$this->trueAnswerRegex = $trueAnswerRegex;
$this->setNormalizer($this->getDefaultNormalizer());
}
@@ -39,17 +43,19 @@ class ConfirmationQuestion extends Question
private function getDefaultNormalizer()
{
$default = $this->getDefault();
$regex = $this->trueAnswerRegex;
return function ($answer) use ($default) {
return function ($answer) use ($default, $regex) {
if (is_bool($answer)) {
return $answer;
}
$answerIsTrue = (bool) preg_match($regex, $answer);
if (false === $default) {
return $answer && 'y' === strtolower($answer[0]);
return $answer && $answerIsTrue;
}
return !$answer || 'y' === strtolower($answer[0]);
return !$answer || $answerIsTrue;
};
}
}

View File

@@ -11,6 +11,9 @@
namespace Symfony\Component\Console\Question;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
/**
* Represents a Question.
*
@@ -76,12 +79,12 @@ class Question
*
* @return Question The current instance
*
* @throws \LogicException In case the autocompleter is also used
* @throws LogicException In case the autocompleter is also used
*/
public function setHidden($hidden)
{
if ($this->autocompleterValues) {
throw new \LogicException('A hidden question cannot use the autocompleter.');
throw new LogicException('A hidden question cannot use the autocompleter.');
}
$this->hidden = (bool) $hidden;
@@ -130,19 +133,23 @@ class Question
*
* @return Question The current instance
*
* @throws \InvalidArgumentException
* @throws \LogicException
* @throws InvalidArgumentException
* @throws LogicException
*/
public function setAutocompleterValues($values)
{
if (is_array($values)) {
$values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
}
if (null !== $values && !is_array($values)) {
if (!$values instanceof \Traversable || $values instanceof \Countable) {
throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
if (!$values instanceof \Traversable || !$values instanceof \Countable) {
throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
}
}
if ($this->hidden) {
throw new \LogicException('A hidden question cannot use the autocompleter.');
throw new LogicException('A hidden question cannot use the autocompleter.');
}
$this->autocompleterValues = $values;
@@ -157,7 +164,7 @@ class Question
*
* @return Question The current instance
*/
public function setValidator($validator)
public function setValidator(callable $validator = null)
{
$this->validator = $validator;
@@ -183,12 +190,12 @@ class Question
*
* @return Question The current instance
*
* @throws \InvalidArgumentException In case the number of attempts is invalid.
* @throws InvalidArgumentException In case the number of attempts is invalid.
*/
public function setMaxAttempts($attempts)
{
if (null !== $attempts && $attempts < 1) {
throw new \InvalidArgumentException('Maximum number of attempts must be a positive value.');
throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
}
$this->attempts = $attempts;
@@ -213,11 +220,11 @@ class Question
*
* The normalizer can be a callable (a string), a closure or a class implementing __invoke.
*
* @param string|\Closure $normalizer
* @param callable $normalizer
*
* @return Question The current instance
*/
public function setNormalizer($normalizer)
public function setNormalizer(callable $normalizer)
{
$this->normalizer = $normalizer;
@@ -229,10 +236,15 @@ class Question
*
* The normalizer can ba a callable (a string), a closure or a class implementing __invoke.
*
* @return string|\Closure
* @return callable
*/
public function getNormalizer()
{
return $this->normalizer;
}
protected function isAssoc($array)
{
return (bool) count(array_filter(array_keys($array), 'is_string'));
}
}

20
vendor/symfony/console/README.md vendored Normal file
View File

@@ -0,0 +1,20 @@
Console Component
=================
The Console component eases the creation of beautiful and testable command line
interfaces.
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/console/index.html)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)
Credits
-------
`Resources/bin/hiddeninput.exe` is a third party binary provided within this
component. Find sources and license at https://github.com/Seldaek/hidden-input.

View File

@@ -0,0 +1,148 @@
<?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\Style;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Decorates output to add console style guide helpers.
*
* @author Kevin Bond <kevinbond@gmail.com>
*/
abstract class OutputStyle implements OutputInterface, StyleInterface
{
private $output;
/**
* @param OutputInterface $output
*/
public function __construct(OutputInterface $output)
{
$this->output = $output;
}
/**
* {@inheritdoc}
*/
public function newLine($count = 1)
{
$this->output->write(str_repeat(PHP_EOL, $count));
}
/**
* @param int $max
*
* @return ProgressBar
*/
public function createProgressBar($max = 0)
{
return new ProgressBar($this->output, $max);
}
/**
* {@inheritdoc}
*/
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
{
$this->output->write($messages, $newline, $type);
}
/**
* {@inheritdoc}
*/
public function writeln($messages, $type = self::OUTPUT_NORMAL)
{
$this->output->writeln($messages, $type);
}
/**
* {@inheritdoc}
*/
public function setVerbosity($level)
{
$this->output->setVerbosity($level);
}
/**
* {@inheritdoc}
*/
public function getVerbosity()
{
return $this->output->getVerbosity();
}
/**
* {@inheritdoc}
*/
public function setDecorated($decorated)
{
$this->output->setDecorated($decorated);
}
/**
* {@inheritdoc}
*/
public function isDecorated()
{
return $this->output->isDecorated();
}
/**
* {@inheritdoc}
*/
public function setFormatter(OutputFormatterInterface $formatter)
{
$this->output->setFormatter($formatter);
}
/**
* {@inheritdoc}
*/
public function getFormatter()
{
return $this->output->getFormatter();
}
/**
* {@inheritdoc}
*/
public function isQuiet()
{
return $this->output->isQuiet();
}
/**
* {@inheritdoc}
*/
public function isVerbose()
{
return $this->output->isVerbose();
}
/**
* {@inheritdoc}
*/
public function isVeryVerbose()
{
return $this->output->isVeryVerbose();
}
/**
* {@inheritdoc}
*/
public function isDebug()
{
return $this->output->isDebug();
}
}

View File

@@ -0,0 +1,159 @@
<?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\Style;
/**
* Output style helpers.
*
* @author Kevin Bond <kevinbond@gmail.com>
*/
interface StyleInterface
{
/**
* Formats a command title.
*
* @param string $message
*/
public function title($message);
/**
* Formats a section title.
*
* @param string $message
*/
public function section($message);
/**
* Formats a list.
*
* @param array $elements
*/
public function listing(array $elements);
/**
* Formats informational text.
*
* @param string|array $message
*/
public function text($message);
/**
* Formats a success result bar.
*
* @param string|array $message
*/
public function success($message);
/**
* Formats an error result bar.
*
* @param string|array $message
*/
public function error($message);
/**
* Formats an warning result bar.
*
* @param string|array $message
*/
public function warning($message);
/**
* Formats a note admonition.
*
* @param string|array $message
*/
public function note($message);
/**
* Formats a caution admonition.
*
* @param string|array $message
*/
public function caution($message);
/**
* Formats a table.
*
* @param array $headers
* @param array $rows
*/
public function table(array $headers, array $rows);
/**
* Asks a question.
*
* @param string $question
* @param string|null $default
* @param callable|null $validator
*
* @return string
*/
public function ask($question, $default = null, $validator = null);
/**
* Asks a question with the user input hidden.
*
* @param string $question
* @param callable|null $validator
*
* @return string
*/
public function askHidden($question, $validator = null);
/**
* Asks for confirmation.
*
* @param string $question
* @param bool $default
*
* @return bool
*/
public function confirm($question, $default = true);
/**
* Asks a choice question.
*
* @param string $question
* @param array $choices
* @param string|int|null $default
*
* @return string
*/
public function choice($question, array $choices, $default = null);
/**
* Add newline(s).
*
* @param int $count The number of newlines
*/
public function newLine($count = 1);
/**
* Starts the progress output.
*
* @param int $max Maximum steps (0 if unknown)
*/
public function progressStart($max = 0);
/**
* Advances the progress output X steps.
*
* @param int $step Number of steps to advance
*/
public function progressAdvance($step = 1);
/**
* Finishes the progress output.
*/
public function progressFinish();
}

View File

@@ -0,0 +1,440 @@
<?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\Style;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
/**
* Output decorator helpers for the Symfony Style Guide.
*
* @author Kevin Bond <kevinbond@gmail.com>
*/
class SymfonyStyle extends OutputStyle
{
const MAX_LINE_LENGTH = 120;
private $input;
private $questionHelper;
private $progressBar;
private $lineLength;
private $bufferedOutput;
/**
* @param InputInterface $input
* @param OutputInterface $output
*/
public function __construct(InputInterface $input, OutputInterface $output)
{
$this->input = $input;
$this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
// Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
$this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
parent::__construct($output);
}
/**
* Formats a message as a block of text.
*
* @param string|array $messages The message to write in the block
* @param string|null $type The block type (added in [] on first line)
* @param string|null $style The style to apply to the whole block
* @param string $prefix The prefix for the block
* @param bool $padding Whether to add vertical padding
*/
public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
{
$this->autoPrependBlock();
$messages = is_array($messages) ? array_values($messages) : array($messages);
$indentLength = 0;
$lines = array();
if (null !== $type) {
$typePrefix = sprintf('[%s] ', $type);
$indentLength = strlen($typePrefix);
$lineIndentation = str_repeat(' ', $indentLength);
}
// wrap and add newlines for each element
foreach ($messages as $key => $message) {
$message = OutputFormatter::escape($message);
$lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - Helper::strlen($prefix) - $indentLength, PHP_EOL, true)));
// prefix each line with a number of spaces equivalent to the type length
if (null !== $type) {
foreach ($lines as &$line) {
$line = $lineIndentation === substr($line, 0, $indentLength) ? $line : $lineIndentation.$line;
}
}
if (count($messages) > 1 && $key < count($messages) - 1) {
$lines[] = '';
}
}
if (null !== $type) {
$lines[0] = substr_replace($lines[0], $typePrefix, 0, $indentLength);
}
if ($padding && $this->isDecorated()) {
array_unshift($lines, '');
$lines[] = '';
}
foreach ($lines as &$line) {
$line = sprintf('%s%s', $prefix, $line);
$line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
if ($style) {
$line = sprintf('<%s>%s</>', $style, $line);
}
}
$this->writeln($lines);
$this->newLine();
}
/**
* {@inheritdoc}
*/
public function title($message)
{
$this->autoPrependBlock();
$this->writeln(array(
sprintf('<comment>%s</>', $message),
sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
));
$this->newLine();
}
/**
* {@inheritdoc}
*/
public function section($message)
{
$this->autoPrependBlock();
$this->writeln(array(
sprintf('<comment>%s</>', $message),
sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
));
$this->newLine();
}
/**
* {@inheritdoc}
*/
public function listing(array $elements)
{
$this->autoPrependText();
$elements = array_map(function ($element) {
return sprintf(' * %s', $element);
}, $elements);
$this->writeln($elements);
$this->newLine();
}
/**
* {@inheritdoc}
*/
public function text($message)
{
$this->autoPrependText();
$messages = is_array($message) ? array_values($message) : array($message);
foreach ($messages as $message) {
$this->writeln(sprintf(' %s', $message));
}
}
/**
* Formats a command comment.
*
* @param string|array $message
*/
public function comment($message)
{
$messages = is_array($message) ? array_values($message) : array($message);
foreach ($messages as &$message) {
$message = $this->getFormatter()->format($message);
}
$this->block($messages, null, null, ' // ');
}
/**
* {@inheritdoc}
*/
public function success($message)
{
$this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
}
/**
* {@inheritdoc}
*/
public function error($message)
{
$this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
}
/**
* {@inheritdoc}
*/
public function warning($message)
{
$this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
}
/**
* {@inheritdoc}
*/
public function note($message)
{
$this->block($message, 'NOTE', 'fg=yellow', ' ! ');
}
/**
* {@inheritdoc}
*/
public function caution($message)
{
$this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
}
/**
* {@inheritdoc}
*/
public function table(array $headers, array $rows)
{
array_walk_recursive($headers, function (&$value) {
if ($value instanceof TableCell) {
$value = new TableCell(sprintf('<info>%s</>', $value), array(
'colspan' => $value->getColspan(),
'rowspan' => $value->getRowspan(),
));
} else {
$value = sprintf('<info>%s</>', $value);
}
});
$table = new Table($this);
$table->setHeaders($headers);
$table->setRows($rows);
$table->setStyle('symfony-style-guide');
$table->render();
$this->newLine();
}
/**
* {@inheritdoc}
*/
public function ask($question, $default = null, $validator = null)
{
$question = new Question($question, $default);
$question->setValidator($validator);
return $this->askQuestion($question);
}
/**
* {@inheritdoc}
*/
public function askHidden($question, $validator = null)
{
$question = new Question($question);
$question->setHidden(true);
$question->setValidator($validator);
return $this->askQuestion($question);
}
/**
* {@inheritdoc}
*/
public function confirm($question, $default = true)
{
return $this->askQuestion(new ConfirmationQuestion($question, $default));
}
/**
* {@inheritdoc}
*/
public function choice($question, array $choices, $default = null)
{
if (null !== $default) {
$values = array_flip($choices);
$default = $values[$default];
}
return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
}
/**
* {@inheritdoc}
*/
public function progressStart($max = 0)
{
$this->progressBar = $this->createProgressBar($max);
$this->progressBar->start();
}
/**
* {@inheritdoc}
*/
public function progressAdvance($step = 1)
{
$this->getProgressBar()->advance($step);
}
/**
* {@inheritdoc}
*/
public function progressFinish()
{
$this->getProgressBar()->finish();
$this->newLine(2);
$this->progressBar = null;
}
/**
* {@inheritdoc}
*/
public function createProgressBar($max = 0)
{
$progressBar = parent::createProgressBar($max);
if ('\\' !== DIRECTORY_SEPARATOR) {
$progressBar->setEmptyBarCharacter('░'); // light shade character \u2591
$progressBar->setProgressCharacter('');
$progressBar->setBarCharacter('▓'); // dark shade character \u2593
}
return $progressBar;
}
/**
* @param Question $question
*
* @return string
*/
public function askQuestion(Question $question)
{
if ($this->input->isInteractive()) {
$this->autoPrependBlock();
}
if (!$this->questionHelper) {
$this->questionHelper = new SymfonyQuestionHelper();
}
$answer = $this->questionHelper->ask($this->input, $this, $question);
if ($this->input->isInteractive()) {
$this->newLine();
$this->bufferedOutput->write("\n");
}
return $answer;
}
/**
* {@inheritdoc}
*/
public function writeln($messages, $type = self::OUTPUT_NORMAL)
{
parent::writeln($messages, $type);
$this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
}
/**
* {@inheritdoc}
*/
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
{
parent::write($messages, $newline, $type);
$this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
}
/**
* {@inheritdoc}
*/
public function newLine($count = 1)
{
parent::newLine($count);
$this->bufferedOutput->write(str_repeat("\n", $count));
}
/**
* @return ProgressBar
*/
private function getProgressBar()
{
if (!$this->progressBar) {
throw new RuntimeException('The ProgressBar is not started.');
}
return $this->progressBar;
}
private function getTerminalWidth()
{
$application = new Application();
$dimensions = $application->getTerminalDimensions();
return $dimensions[0] ?: self::MAX_LINE_LENGTH;
}
private function autoPrependBlock()
{
$chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
if (!isset($chars[0])) {
return $this->newLine(); //empty history, so we should start with a new line.
}
//Prepend new line for each non LF chars (This means no blank line was output before)
$this->newLine(2 - substr_count($chars, "\n"));
}
private function autoPrependText()
{
$fetched = $this->bufferedOutput->fetch();
//Prepend new line if last char isn't EOL:
if ("\n" !== substr($fetched, -1)) {
$this->newLine();
}
}
private function reduceBuffer($messages)
{
// We need to know if the two last chars are PHP_EOL
// Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer
return array_map(function ($value) {
return substr($value, -4);
}, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
}
}

View File

@@ -1,476 +0,0 @@
<?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\Helper;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
/**
* The Dialog class provides helpers to interact with the user.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated Deprecated since version 2.5, to be removed in 3.0.
* Use the question helper instead.
*/
class DialogHelper extends InputAwareHelper
{
private $inputStream;
private static $shell;
private static $stty;
/**
* Asks the user to select a value.
*
* @param OutputInterface $output An Output instance
* @param string|array $question The question to ask
* @param array $choices List of choices to pick from
* @param bool|string $default The default answer if the user enters nothing
* @param bool|int $attempts Max number of times to ask before giving up (false by default, which means infinite)
* @param string $errorMessage Message which will be shown if invalid value from choice list would be picked
* @param bool $multiselect Select more than one value separated by comma
*
* @return int|string|array The selected value or values (the key of the choices array)
*
* @throws \InvalidArgumentException
*/
public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
{
$width = max(array_map('strlen', array_keys($choices)));
$messages = (array) $question;
foreach ($choices as $key => $value) {
$messages[] = sprintf(" [<info>%-${width}s</info>] %s", $key, $value);
}
$output->writeln($messages);
$result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
// Collapse all spaces.
$selectedChoices = str_replace(' ', '', $picked);
if ($multiselect) {
// Check for a separated comma values
if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
throw new \InvalidArgumentException(sprintf($errorMessage, $picked));
}
$selectedChoices = explode(',', $selectedChoices);
} else {
$selectedChoices = array($picked);
}
$multiselectChoices = array();
foreach ($selectedChoices as $value) {
if (empty($choices[$value])) {
throw new \InvalidArgumentException(sprintf($errorMessage, $value));
}
$multiselectChoices[] = $value;
}
if ($multiselect) {
return $multiselectChoices;
}
return $picked;
}, $attempts, $default);
return $result;
}
/**
* Asks a question to the user.
*
* @param OutputInterface $output An Output instance
* @param string|array $question The question to ask
* @param string $default The default answer if none is given by the user
* @param array $autocomplete List of values to autocomplete
*
* @return string The user answer
*
* @throws \RuntimeException If there is no data to read in the input stream
*/
public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
{
if ($this->input && !$this->input->isInteractive()) {
return $default;
}
$output->write($question);
$inputStream = $this->inputStream ?: STDIN;
if (null === $autocomplete || !$this->hasSttyAvailable()) {
$ret = fgets($inputStream, 4096);
if (false === $ret) {
throw new \RuntimeException('Aborted');
}
$ret = trim($ret);
} else {
$ret = '';
$i = 0;
$ofs = -1;
$matches = $autocomplete;
$numMatches = count($matches);
$sttyMode = shell_exec('stty -g');
// Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
shell_exec('stty -icanon -echo');
// Add highlighted text style
$output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
// Read a keypress
while (!feof($inputStream)) {
$c = fread($inputStream, 1);
// Backspace Character
if ("\177" === $c) {
if (0 === $numMatches && 0 !== $i) {
--$i;
// Move cursor backwards
$output->write("\033[1D");
}
if ($i === 0) {
$ofs = -1;
$matches = $autocomplete;
$numMatches = count($matches);
} else {
$numMatches = 0;
}
// Pop the last character off the end of our string
$ret = substr($ret, 0, $i);
} elseif ("\033" === $c) {
// Did we read an escape sequence?
$c .= fread($inputStream, 2);
// A = Up Arrow. B = Down Arrow
if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
if ('A' === $c[2] && -1 === $ofs) {
$ofs = 0;
}
if (0 === $numMatches) {
continue;
}
$ofs += ('A' === $c[2]) ? -1 : 1;
$ofs = ($numMatches + $ofs) % $numMatches;
}
} elseif (ord($c) < 32) {
if ("\t" === $c || "\n" === $c) {
if ($numMatches > 0 && -1 !== $ofs) {
$ret = $matches[$ofs];
// Echo out remaining chars for current match
$output->write(substr($ret, $i));
$i = strlen($ret);
}
if ("\n" === $c) {
$output->write($c);
break;
}
$numMatches = 0;
}
continue;
} else {
$output->write($c);
$ret .= $c;
++$i;
$numMatches = 0;
$ofs = 0;
foreach ($autocomplete as $value) {
// If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
if (0 === strpos($value, $ret) && $i !== strlen($value)) {
$matches[$numMatches++] = $value;
}
}
}
// Erase characters from cursor to end of line
$output->write("\033[K");
if ($numMatches > 0 && -1 !== $ofs) {
// Save cursor position
$output->write("\0337");
// Write highlighted text
$output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
// Restore cursor position
$output->write("\0338");
}
}
// Reset stty so it behaves normally again
shell_exec(sprintf('stty %s', $sttyMode));
}
return strlen($ret) > 0 ? $ret : $default;
}
/**
* Asks a confirmation to the user.
*
* The question will be asked until the user answers by nothing, yes, or no.
*
* @param OutputInterface $output An Output instance
* @param string|array $question The question to ask
* @param bool $default The default answer if the user enters nothing
*
* @return bool true if the user has confirmed, false otherwise
*/
public function askConfirmation(OutputInterface $output, $question, $default = true)
{
$answer = 'z';
while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
$answer = $this->ask($output, $question);
}
if (false === $default) {
return $answer && 'y' == strtolower($answer[0]);
}
return !$answer || 'y' == strtolower($answer[0]);
}
/**
* Asks a question to the user, the response is hidden.
*
* @param OutputInterface $output An Output instance
* @param string|array $question The question
* @param bool $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not
*
* @return string The answer
*
* @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
*/
public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
{
if ('\\' === DIRECTORY_SEPARATOR) {
$exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
// handle code running from a phar
if ('phar:' === substr(__FILE__, 0, 5)) {
$tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
copy($exe, $tmpExe);
$exe = $tmpExe;
}
$output->write($question);
$value = rtrim(shell_exec($exe));
$output->writeln('');
if (isset($tmpExe)) {
unlink($tmpExe);
}
return $value;
}
if ($this->hasSttyAvailable()) {
$output->write($question);
$sttyMode = shell_exec('stty -g');
shell_exec('stty -echo');
$value = fgets($this->inputStream ?: STDIN, 4096);
shell_exec(sprintf('stty %s', $sttyMode));
if (false === $value) {
throw new \RuntimeException('Aborted');
}
$value = trim($value);
$output->writeln('');
return $value;
}
if (false !== $shell = $this->getShell()) {
$output->write($question);
$readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
$command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
$value = rtrim(shell_exec($command));
$output->writeln('');
return $value;
}
if ($fallback) {
return $this->ask($output, $question);
}
throw new \RuntimeException('Unable to hide the response');
}
/**
* Asks for a value and validates the response.
*
* The validator receives the data to validate. It must return the
* validated data when the data is valid and throw an exception
* otherwise.
*
* @param OutputInterface $output An Output instance
* @param string|array $question The question to ask
* @param callable $validator A PHP callback
* @param int|false $attempts Max number of times to ask before giving up (false by default, which means infinite)
* @param string $default The default answer if none is given by the user
* @param array $autocomplete List of values to autocomplete
*
* @return mixed
*
* @throws \Exception When any of the validators return an error
*/
public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
{
$that = $this;
$interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
return $that->ask($output, $question, $default, $autocomplete);
};
return $this->validateAttempts($interviewer, $output, $validator, $attempts);
}
/**
* Asks for a value, hide and validates the response.
*
* The validator receives the data to validate. It must return the
* validated data when the data is valid and throw an exception
* otherwise.
*
* @param OutputInterface $output An Output instance
* @param string|array $question The question to ask
* @param callable $validator A PHP callback
* @param int|false $attempts Max number of times to ask before giving up (false by default, which means infinite)
* @param bool $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not
*
* @return string The response
*
* @throws \Exception When any of the validators return an error
* @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
*/
public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
{
$that = $this;
$interviewer = function () use ($output, $question, $fallback, $that) {
return $that->askHiddenResponse($output, $question, $fallback);
};
return $this->validateAttempts($interviewer, $output, $validator, $attempts);
}
/**
* Sets the input stream to read from when interacting with the user.
*
* This is mainly useful for testing purpose.
*
* @param resource $stream The input stream
*/
public function setInputStream($stream)
{
$this->inputStream = $stream;
}
/**
* Returns the helper's input stream.
*
* @return string
*/
public function getInputStream()
{
return $this->inputStream;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'dialog';
}
/**
* Return a valid Unix shell.
*
* @return string|bool The valid shell name, false in case no valid shell is found
*/
private function getShell()
{
if (null !== self::$shell) {
return self::$shell;
}
self::$shell = false;
if (file_exists('/usr/bin/env')) {
// handle other OSs with bash/zsh/ksh/csh if available to hide the answer
$test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
self::$shell = $sh;
break;
}
}
}
return self::$shell;
}
private function hasSttyAvailable()
{
if (null !== self::$stty) {
return self::$stty;
}
exec('stty 2>&1', $output, $exitcode);
return self::$stty = $exitcode === 0;
}
/**
* Validate an attempt.
*
* @param callable $interviewer A callable that will ask for a question and return the result
* @param OutputInterface $output An Output instance
* @param callable $validator A PHP callback
* @param int|false $attempts Max number of times to ask before giving up ; false will ask infinitely
*
* @return string The validated response
*
* @throws \Exception In case the max number of attempts has been reached and no valid response has been given
*/
private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
{
$e = null;
while (false === $attempts || $attempts--) {
if (null !== $e) {
$output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
}
try {
return call_user_func($validator, $interviewer());
} catch (\Exception $e) {
}
}
throw $e;
}
}

View File

@@ -1,457 +0,0 @@
<?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\Helper;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
/**
* The Progress class provides helpers to display progress output.
*
* @author Chris Jones <leeked@gmail.com>
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated Deprecated since 2.5, to be removed in 3.0; use ProgressBar instead.
*/
class ProgressHelper extends Helper
{
const FORMAT_QUIET = ' %percent%%';
const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
const FORMAT_QUIET_NOMAX = ' %current%';
const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
// options
private $barWidth = 28;
private $barChar = '=';
private $emptyBarChar = '-';
private $progressChar = '>';
private $format = null;
private $redrawFreq = 1;
private $lastMessagesLength;
private $barCharOriginal;
/**
* @var OutputInterface
*/
private $output;
/**
* Current step.
*
* @var int
*/
private $current;
/**
* Maximum number of steps.
*
* @var int
*/
private $max;
/**
* Start time of the progress bar.
*
* @var int
*/
private $startTime;
/**
* List of formatting variables.
*
* @var array
*/
private $defaultFormatVars = array(
'current',
'max',
'bar',
'percent',
'elapsed',
);
/**
* Available formatting variables.
*
* @var array
*/
private $formatVars;
/**
* Stored format part widths (used for padding).
*
* @var array
*/
private $widths = array(
'current' => 4,
'max' => 4,
'percent' => 3,
'elapsed' => 6,
);
/**
* Various time formats.
*
* @var array
*/
private $timeFormats = array(
array(0, '???'),
array(2, '1 sec'),
array(59, 'secs', 1),
array(60, '1 min'),
array(3600, 'mins', 60),
array(5400, '1 hr'),
array(86400, 'hrs', 3600),
array(129600, '1 day'),
array(604800, 'days', 86400),
);
/**
* Sets the progress bar width.
*
* @param int $size The progress bar size
*/
public function setBarWidth($size)
{
$this->barWidth = (int) $size;
}
/**
* Sets the bar character.
*
* @param string $char A character
*/
public function setBarCharacter($char)
{
$this->barChar = $char;
}
/**
* Sets the empty bar character.
*
* @param string $char A character
*/
public function setEmptyBarCharacter($char)
{
$this->emptyBarChar = $char;
}
/**
* Sets the progress bar character.
*
* @param string $char A character
*/
public function setProgressCharacter($char)
{
$this->progressChar = $char;
}
/**
* Sets the progress bar format.
*
* @param string $format The format
*/
public function setFormat($format)
{
$this->format = $format;
}
/**
* Sets the redraw frequency.
*
* @param int $freq The frequency in steps
*/
public function setRedrawFrequency($freq)
{
$this->redrawFreq = (int) $freq;
}
/**
* Starts the progress output.
*
* @param OutputInterface $output An Output instance
* @param int|null $max Maximum steps
*/
public function start(OutputInterface $output, $max = null)
{
$this->startTime = time();
$this->current = 0;
$this->max = (int) $max;
// Disabling output when it does not support ANSI codes as it would result in a broken display anyway.
$this->output = $output->isDecorated() ? $output : new NullOutput();
$this->lastMessagesLength = 0;
$this->barCharOriginal = '';
if (null === $this->format) {
switch ($output->getVerbosity()) {
case OutputInterface::VERBOSITY_QUIET:
$this->format = self::FORMAT_QUIET_NOMAX;
if ($this->max > 0) {
$this->format = self::FORMAT_QUIET;
}
break;
case OutputInterface::VERBOSITY_VERBOSE:
case OutputInterface::VERBOSITY_VERY_VERBOSE:
case OutputInterface::VERBOSITY_DEBUG:
$this->format = self::FORMAT_VERBOSE_NOMAX;
if ($this->max > 0) {
$this->format = self::FORMAT_VERBOSE;
}
break;
default:
$this->format = self::FORMAT_NORMAL_NOMAX;
if ($this->max > 0) {
$this->format = self::FORMAT_NORMAL;
}
break;
}
}
$this->initialize();
}
/**
* Advances the progress output X steps.
*
* @param int $step Number of steps to advance
* @param bool $redraw Whether to redraw or not
*
* @throws \LogicException
*/
public function advance($step = 1, $redraw = false)
{
$this->setCurrent($this->current + $step, $redraw);
}
/**
* Sets the current progress.
*
* @param int $current The current progress
* @param bool $redraw Whether to redraw or not
*
* @throws \LogicException
*/
public function setCurrent($current, $redraw = false)
{
if (null === $this->startTime) {
throw new \LogicException('You must start the progress bar before calling setCurrent().');
}
$current = (int) $current;
if ($current < $this->current) {
throw new \LogicException('You can\'t regress the progress bar');
}
if (0 === $this->current) {
$redraw = true;
}
$prevPeriod = (int) ($this->current / $this->redrawFreq);
$this->current = $current;
$currPeriod = (int) ($this->current / $this->redrawFreq);
if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
$this->display();
}
}
/**
* Outputs the current progress string.
*
* @param bool $finish Forces the end result
*
* @throws \LogicException
*/
public function display($finish = false)
{
if (null === $this->startTime) {
throw new \LogicException('You must start the progress bar before calling display().');
}
$message = $this->format;
foreach ($this->generate($finish) as $name => $value) {
$message = str_replace("%{$name}%", $value, $message);
}
$this->overwrite($this->output, $message);
}
/**
* Removes the progress bar from the current line.
*
* This is useful if you wish to write some output
* while a progress bar is running.
* Call display() to show the progress bar again.
*/
public function clear()
{
$this->overwrite($this->output, '');
}
/**
* Finishes the progress output.
*/
public function finish()
{
if (null === $this->startTime) {
throw new \LogicException('You must start the progress bar before calling finish().');
}
if (null !== $this->startTime) {
if (!$this->max) {
$this->barChar = $this->barCharOriginal;
$this->display(true);
}
$this->startTime = null;
$this->output->writeln('');
$this->output = null;
}
}
/**
* Initializes the progress helper.
*/
private function initialize()
{
$this->formatVars = array();
foreach ($this->defaultFormatVars as $var) {
if (false !== strpos($this->format, "%{$var}%")) {
$this->formatVars[$var] = true;
}
}
if ($this->max > 0) {
$this->widths['max'] = $this->strlen($this->max);
$this->widths['current'] = $this->widths['max'];
} else {
$this->barCharOriginal = $this->barChar;
$this->barChar = $this->emptyBarChar;
}
}
/**
* Generates the array map of format variables to values.
*
* @param bool $finish Forces the end result
*
* @return array Array of format vars and values
*/
private function generate($finish = false)
{
$vars = array();
$percent = 0;
if ($this->max > 0) {
$percent = (float) $this->current / $this->max;
}
if (isset($this->formatVars['bar'])) {
$completeBars = 0;
if ($this->max > 0) {
$completeBars = floor($percent * $this->barWidth);
} else {
if (!$finish) {
$completeBars = floor($this->current % $this->barWidth);
} else {
$completeBars = $this->barWidth;
}
}
$emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
$bar = str_repeat($this->barChar, $completeBars);
if ($completeBars < $this->barWidth) {
$bar .= $this->progressChar;
$bar .= str_repeat($this->emptyBarChar, $emptyBars);
}
$vars['bar'] = $bar;
}
if (isset($this->formatVars['elapsed'])) {
$elapsed = time() - $this->startTime;
$vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
}
if (isset($this->formatVars['current'])) {
$vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
}
if (isset($this->formatVars['max'])) {
$vars['max'] = $this->max;
}
if (isset($this->formatVars['percent'])) {
$vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
}
return $vars;
}
/**
* Converts seconds into human-readable format.
*
* @param int $secs Number of seconds
*
* @return string Time in readable format
*/
private function humaneTime($secs)
{
$text = '';
foreach ($this->timeFormats as $format) {
if ($secs < $format[0]) {
if (count($format) == 2) {
$text = $format[1];
break;
} else {
$text = ceil($secs / $format[2]).' '.$format[1];
break;
}
}
}
return $text;
}
/**
* Overwrites a previous message to the output.
*
* @param OutputInterface $output An Output instance
* @param string $message The message
*/
private function overwrite(OutputInterface $output, $message)
{
$length = $this->strlen($message);
// append whitespace to match the last line's length
if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
$message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
}
// carriage return
$output->write("\x0D");
$output->write($message);
$this->lastMessagesLength = $this->strlen($message);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'progress';
}
}

View File

@@ -1,410 +0,0 @@
<?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\Helper;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Provides helpers to display a table.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Саша Стаменковић <umpirsky@gmail.com>
*/
class Table
{
/**
* Table headers.
*
* @var array
*/
private $headers = array();
/**
* Table rows.
*
* @var array
*/
private $rows = array();
/**
* Column widths cache.
*
* @var array
*/
private $columnWidths = array();
/**
* Number of columns cache.
*
* @var array
*/
private $numberOfColumns;
/**
* @var OutputInterface
*/
private $output;
/**
* @var TableStyle
*/
private $style;
private static $styles;
public function __construct(OutputInterface $output)
{
$this->output = $output;
if (!self::$styles) {
self::$styles = self::initStyles();
}
$this->setStyle('default');
}
/**
* Sets a style definition.
*
* @param string $name The style name
* @param TableStyle $style A TableStyle instance
*/
public static function setStyleDefinition($name, TableStyle $style)
{
if (!self::$styles) {
self::$styles = self::initStyles();
}
self::$styles[$name] = $style;
}
/**
* Gets a style definition by name.
*
* @param string $name The style name
*
* @return TableStyle A TableStyle instance
*/
public static function getStyleDefinition($name)
{
if (!self::$styles) {
self::$styles = self::initStyles();
}
if (!self::$styles[$name]) {
throw new \InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
}
return self::$styles[$name];
}
/**
* Sets table style.
*
* @param TableStyle|string $name The style name or a TableStyle instance
*
* @return Table
*/
public function setStyle($name)
{
if ($name instanceof TableStyle) {
$this->style = $name;
} elseif (isset(self::$styles[$name])) {
$this->style = self::$styles[$name];
} else {
throw new \InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
}
return $this;
}
/**
* Gets the current table style.
*
* @return TableStyle
*/
public function getStyle()
{
return $this->style;
}
public function setHeaders(array $headers)
{
$this->headers = array_values($headers);
return $this;
}
public function setRows(array $rows)
{
$this->rows = array();
return $this->addRows($rows);
}
public function addRows(array $rows)
{
foreach ($rows as $row) {
$this->addRow($row);
}
return $this;
}
public function addRow($row)
{
if ($row instanceof TableSeparator) {
$this->rows[] = $row;
return $this;
}
if (!is_array($row)) {
throw new \InvalidArgumentException('A row must be an array or a TableSeparator instance.');
}
$this->rows[] = array_values($row);
end($this->rows);
$rowKey = key($this->rows);
reset($this->rows);
foreach ($row as $key => $cellValue) {
if (false === strpos($cellValue, "\n")) {
continue;
}
$lines = explode("\n", $cellValue);
$this->rows[$rowKey][$key] = $lines[0];
unset($lines[0]);
foreach ($lines as $lineKey => $line) {
$nextRowKey = $rowKey + $lineKey + 1;
if (isset($this->rows[$nextRowKey])) {
$this->rows[$nextRowKey][$key] = $line;
} else {
$this->rows[$nextRowKey] = array($key => $line);
}
}
}
return $this;
}
public function setRow($column, array $row)
{
$this->rows[$column] = $row;
return $this;
}
/**
* Renders table to output.
*
* Example:
* +---------------+-----------------------+------------------+
* | ISBN | Title | Author |
* +---------------+-----------------------+------------------+
* | 99921-58-10-7 | Divine Comedy | Dante Alighieri |
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
* | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
* +---------------+-----------------------+------------------+
*/
public function render()
{
$this->renderRowSeparator();
$this->renderRow($this->headers, $this->style->getCellHeaderFormat());
if (!empty($this->headers)) {
$this->renderRowSeparator();
}
foreach ($this->rows as $row) {
if ($row instanceof TableSeparator) {
$this->renderRowSeparator();
} else {
$this->renderRow($row, $this->style->getCellRowFormat());
}
}
if (!empty($this->rows)) {
$this->renderRowSeparator();
}
$this->cleanup();
}
/**
* Renders horizontal header separator.
*
* Example: +-----+-----------+-------+
*/
private function renderRowSeparator()
{
if (0 === $count = $this->getNumberOfColumns()) {
return;
}
if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
return;
}
$markup = $this->style->getCrossingChar();
for ($column = 0; $column < $count; $column++) {
$markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->getColumnWidth($column)).$this->style->getCrossingChar();
}
$this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
}
/**
* Renders vertical column separator.
*/
private function renderColumnSeparator()
{
$this->output->write(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
}
/**
* Renders table row.
*
* Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
*
* @param array $row
* @param string $cellFormat
*/
private function renderRow(array $row, $cellFormat)
{
if (empty($row)) {
return;
}
$this->renderColumnSeparator();
for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) {
$this->renderCell($row, $column, $cellFormat);
$this->renderColumnSeparator();
}
$this->output->writeln('');
}
/**
* Renders table cell with padding.
*
* @param array $row
* @param int $column
* @param string $cellFormat
*/
private function renderCell(array $row, $column, $cellFormat)
{
$cell = isset($row[$column]) ? $row[$column] : '';
$width = $this->getColumnWidth($column);
// str_pad won't work properly with multi-byte strings, we need to fix the padding
if (function_exists('mb_strwidth') && false !== $encoding = mb_detect_encoding($cell)) {
$width += strlen($cell) - mb_strwidth($cell, $encoding);
}
$width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
$content = sprintf($this->style->getCellRowContentFormat(), $cell);
$this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->style->getPaddingChar(), $this->style->getPadType())));
}
/**
* Gets number of columns for this table.
*
* @return int
*/
private function getNumberOfColumns()
{
if (null !== $this->numberOfColumns) {
return $this->numberOfColumns;
}
$columns = array(count($this->headers));
foreach ($this->rows as $row) {
$columns[] = count($row);
}
return $this->numberOfColumns = max($columns);
}
/**
* Gets column width.
*
* @param int $column
*
* @return int
*/
private function getColumnWidth($column)
{
if (isset($this->columnWidths[$column])) {
return $this->columnWidths[$column];
}
$lengths = array($this->getCellWidth($this->headers, $column));
foreach ($this->rows as $row) {
if ($row instanceof TableSeparator) {
continue;
}
$lengths[] = $this->getCellWidth($row, $column);
}
return $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
}
/**
* Gets cell width.
*
* @param array $row
* @param int $column
*
* @return int
*/
private function getCellWidth(array $row, $column)
{
return isset($row[$column]) ? Helper::strlenWithoutDecoration($this->output->getFormatter(), $row[$column]) : 0;
}
/**
* Called after rendering to cleanup cache data.
*/
private function cleanup()
{
$this->columnWidths = array();
$this->numberOfColumns = null;
}
private static function initStyles()
{
$borderless = new TableStyle();
$borderless
->setHorizontalBorderChar('=')
->setVerticalBorderChar(' ')
->setCrossingChar(' ')
;
$compact = new TableStyle();
$compact
->setHorizontalBorderChar('')
->setVerticalBorderChar(' ')
->setCrossingChar('')
->setCellRowContentFormat('%s')
;
return array(
'default' => new TableStyle(),
'borderless' => $borderless,
'compact' => $compact,
);
}
}

View File

@@ -1,263 +0,0 @@
<?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\Helper;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\NullOutput;
/**
* Provides helpers to display table output.
*
* @author Саша Стаменковић <umpirsky@gmail.com>
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated Deprecated since 2.5, to be removed in 3.0; use Table instead.
*/
class TableHelper extends Helper
{
const LAYOUT_DEFAULT = 0;
const LAYOUT_BORDERLESS = 1;
const LAYOUT_COMPACT = 2;
/**
* @var Table
*/
private $table;
public function __construct()
{
$this->table = new Table(new NullOutput());
}
/**
* Sets table layout type.
*
* @param int $layout self::LAYOUT_*
*
* @return TableHelper
*
* @throws \InvalidArgumentException when the table layout is not known
*/
public function setLayout($layout)
{
switch ($layout) {
case self::LAYOUT_BORDERLESS:
$this->table->setStyle('borderless');
break;
case self::LAYOUT_COMPACT:
$this->table->setStyle('compact');
break;
case self::LAYOUT_DEFAULT:
$this->table->setStyle('default');
break;
default:
throw new \InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
};
return $this;
}
public function setHeaders(array $headers)
{
$this->table->setHeaders($headers);
return $this;
}
public function setRows(array $rows)
{
$this->table->setRows($rows);
return $this;
}
public function addRows(array $rows)
{
$this->table->addRows($rows);
return $this;
}
public function addRow(array $row)
{
$this->table->addRow($row);
return $this;
}
public function setRow($column, array $row)
{
$this->table->setRow($column, $row);
return $this;
}
/**
* Sets padding character, used for cell padding.
*
* @param string $paddingChar
*
* @return TableHelper
*/
public function setPaddingChar($paddingChar)
{
$this->table->getStyle()->setPaddingChar($paddingChar);
return $this;
}
/**
* Sets horizontal border character.
*
* @param string $horizontalBorderChar
*
* @return TableHelper
*/
public function setHorizontalBorderChar($horizontalBorderChar)
{
$this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
return $this;
}
/**
* Sets vertical border character.
*
* @param string $verticalBorderChar
*
* @return TableHelper
*/
public function setVerticalBorderChar($verticalBorderChar)
{
$this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
return $this;
}
/**
* Sets crossing character.
*
* @param string $crossingChar
*
* @return TableHelper
*/
public function setCrossingChar($crossingChar)
{
$this->table->getStyle()->setCrossingChar($crossingChar);
return $this;
}
/**
* Sets header cell format.
*
* @param string $cellHeaderFormat
*
* @return TableHelper
*/
public function setCellHeaderFormat($cellHeaderFormat)
{
$this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
return $this;
}
/**
* Sets row cell format.
*
* @param string $cellRowFormat
*
* @return TableHelper
*/
public function setCellRowFormat($cellRowFormat)
{
$this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
return $this;
}
/**
* Sets row cell content format.
*
* @param string $cellRowContentFormat
*
* @return TableHelper
*/
public function setCellRowContentFormat($cellRowContentFormat)
{
$this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
return $this;
}
/**
* Sets table border format.
*
* @param string $borderFormat
*
* @return TableHelper
*/
public function setBorderFormat($borderFormat)
{
$this->table->getStyle()->setBorderFormat($borderFormat);
return $this;
}
/**
* Sets cell padding type.
*
* @param int $padType STR_PAD_*
*
* @return TableHelper
*/
public function setPadType($padType)
{
$this->table->getStyle()->setPadType($padType);
return $this;
}
/**
* Renders table to output.
*
* Example:
* +---------------+-----------------------+------------------+
* | ISBN | Title | Author |
* +---------------+-----------------------+------------------+
* | 99921-58-10-7 | Divine Comedy | Dante Alighieri |
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
* | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
* +---------------+-----------------------+------------------+
*
* @param OutputInterface $output
*/
public function render(OutputInterface $output)
{
$p = new \ReflectionProperty($this->table, 'output');
$p->setAccessible(true);
$p->setValue($this->table, $output);
$this->table->render();
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'table';
}
}

View File

@@ -1,67 +0,0 @@
Console Component
=================
Console eases the creation of beautiful and testable command line interfaces.
The Application object manages the CLI application:
```php
use Symfony\Component\Console\Application;
$console = new Application();
$console->run();
```
The ``run()`` method parses the arguments and options passed on the command
line and executes the right command.
Registering a new command can easily be done via the ``register()`` method,
which returns a ``Command`` instance:
```php
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
$console
->register('ls')
->setDefinition(array(
new InputArgument('dir', InputArgument::REQUIRED, 'Directory name'),
))
->setDescription('Displays the files in the given directory')
->setCode(function (InputInterface $input, OutputInterface $output) {
$dir = $input->getArgument('dir');
$output->writeln(sprintf('Dir listing for <info>%s</info>', $dir));
})
;
```
You can also register new commands via classes.
The component provides a lot of features like output coloring, input and
output abstractions (so that you can easily unit-test your commands),
validation, automatic help messages, ...
Tests
-----
You can run the unit tests with the following command:
$ cd path/to/Symfony/Component/Console/
$ composer install
$ phpunit
Third Party
-----------
`Resources/bin/hiddeninput.exe` is a third party binary provided within this
component. Find sources and license at https://github.com/Seldaek/hidden-input.
Resources
---------
[The Console Component](https://symfony.com/doc/current/components/console.html)
[How to create a Console Command](https://symfony.com/doc/current/cookbook/console/console_command.html)

View File

@@ -1,228 +0,0 @@
<?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;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Process\ProcessBuilder;
use Symfony\Component\Process\PhpExecutableFinder;
/**
* A Shell wraps an Application to add shell capabilities to it.
*
* Support for history and completion only works with a PHP compiled
* with readline support (either --with-readline or --with-libedit)
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Martin Hasoň <martin.hason@gmail.com>
*/
class Shell
{
private $application;
private $history;
private $output;
private $hasReadline;
private $processIsolation = false;
/**
* Constructor.
*
* If there is no readline support for the current PHP executable
* a \RuntimeException exception is thrown.
*
* @param Application $application An application instance
*/
public function __construct(Application $application)
{
$this->hasReadline = function_exists('readline');
$this->application = $application;
$this->history = getenv('HOME').'/.history_'.$application->getName();
$this->output = new ConsoleOutput();
}
/**
* Runs the shell.
*/
public function run()
{
$this->application->setAutoExit(false);
$this->application->setCatchExceptions(true);
if ($this->hasReadline) {
readline_read_history($this->history);
readline_completion_function(array($this, 'autocompleter'));
}
$this->output->writeln($this->getHeader());
$php = null;
if ($this->processIsolation) {
$finder = new PhpExecutableFinder();
$php = $finder->find();
$this->output->writeln(<<<EOF
<info>Running with process isolation, you should consider this:</info>
* each command is executed as separate process,
* commands don't support interactivity, all params must be passed explicitly,
* commands output is not colorized.
EOF
);
}
while (true) {
$command = $this->readline();
if (false === $command) {
$this->output->writeln("\n");
break;
}
if ($this->hasReadline) {
readline_add_history($command);
readline_write_history($this->history);
}
if ($this->processIsolation) {
$pb = new ProcessBuilder();
$process = $pb
->add($php)
->add($_SERVER['argv'][0])
->add($command)
->inheritEnvironmentVariables(true)
->getProcess()
;
$output = $this->output;
$process->run(function ($type, $data) use ($output) {
$output->writeln($data);
});
$ret = $process->getExitCode();
} else {
$ret = $this->application->run(new StringInput($command), $this->output);
}
if (0 !== $ret) {
$this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
}
}
}
/**
* Returns the shell header.
*
* @return string The header string
*/
protected function getHeader()
{
return <<<EOF
Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
At the prompt, type <comment>help</comment> for some help,
or <comment>list</comment> to get a list of available commands.
To exit the shell, type <comment>^D</comment>.
EOF;
}
/**
* Renders a prompt.
*
* @return string The prompt
*/
protected function getPrompt()
{
// using the formatter here is required when using readline
return $this->output->getFormatter()->format($this->application->getName().' > ');
}
protected function getOutput()
{
return $this->output;
}
protected function getApplication()
{
return $this->application;
}
/**
* Tries to return autocompletion for the current entered text.
*
* @param string $text The last segment of the entered text
*
* @return bool|array A list of guessed strings or true
*/
private function autocompleter($text)
{
$info = readline_info();
$text = substr($info['line_buffer'], 0, $info['end']);
if ($info['point'] !== $info['end']) {
return true;
}
// task name?
if (false === strpos($text, ' ') || !$text) {
return array_keys($this->application->all());
}
// options and arguments?
try {
$command = $this->application->find(substr($text, 0, strpos($text, ' ')));
} catch (\Exception $e) {
return true;
}
$list = array('--help');
foreach ($command->getDefinition()->getOptions() as $option) {
$list[] = '--'.$option->getName();
}
return $list;
}
/**
* Reads a single line from standard input.
*
* @return string The single line from standard input
*/
private function readline()
{
if ($this->hasReadline) {
$line = readline($this->getPrompt());
} else {
$this->output->write($this->getPrompt());
$line = fgets(STDIN, 1024);
$line = (false === $line || '' === $line) ? false : rtrim($line);
}
return $line;
}
public function getProcessIsolation()
{
return $this->processIsolation;
}
public function setProcessIsolation($processIsolation)
{
$this->processIsolation = (bool) $processIsolation;
if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
}
}
}

View File

@@ -1 +0,0 @@
{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":"txt"}}}}],"namespaces":[{"id":"_global","commands":["help","list"]}]}

View File

@@ -1,17 +0,0 @@
<info>Console Tool</info>
<comment>Usage:</comment>
command [options] [arguments]
<comment>Options:</comment>
<info>--help</info> (-h) Display this help message
<info>--quiet</info> (-q) Do not output any message
<info>--verbose</info> (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
<info>--version</info> (-V) Display this application version
<info>--ansi</info> Force ANSI output
<info>--no-ansi</info> Disable ANSI output
<info>--no-interaction</info> (-n) Do not ask any interactive question
<comment>Available commands:</comment>
<info>help </info> Displays help for a command
<info>list </info> Lists commands

File diff suppressed because one or more lines are too long

View File

@@ -1,22 +0,0 @@
<info>My Symfony application</info> version <comment>v1.0</comment>
<comment>Usage:</comment>
command [options] [arguments]
<comment>Options:</comment>
<info>--help</info> (-h) Display this help message
<info>--quiet</info> (-q) Do not output any message
<info>--verbose</info> (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
<info>--version</info> (-V) Display this application version
<info>--ansi</info> Force ANSI output
<info>--no-ansi</info> Disable ANSI output
<info>--no-interaction</info> (-n) Do not ask any interactive question
<comment>Available commands:</comment>
<info>alias1 </info> command 1 description
<info>alias2 </info> command 1 description
<info>help </info> Displays help for a command
<info>list </info> Lists commands
<comment>descriptor</comment>
<info>descriptor:command1 </info> command 1 description
<info>descriptor:command2 </info> command 2 description

View File

@@ -1,20 +0,0 @@
<info>Console Tool</info>
<comment>Usage:</comment>
command [options] [arguments]
<comment>Options:</comment>
<info>--help</info> (-h) Display this help message
<info>--quiet</info> (-q) Do not output any message
<info>--verbose</info> (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
<info>--version</info> (-V) Display this application version
<info>--ansi</info> Force ANSI output
<info>--no-ansi</info> Disable ANSI output
<info>--no-interaction</info> (-n) Do not ask any interactive question
<comment>Available commands:</comment>
<info>afoobar </info> The foo:bar command
<info>help </info> Displays help for a command
<info>list </info> Lists commands
<comment>foo</comment>
<info>foo:bar </info> The foo:bar command

View File

@@ -1,16 +0,0 @@
<info>Console Tool</info>
<comment>Usage:</comment>
command [options] [arguments]
<comment>Options:</comment>
<info>--help</info> (-h) Display this help message
<info>--quiet</info> (-q) Do not output any message
<info>--verbose</info> (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
<info>--version</info> (-V) Display this application version
<info>--ansi</info> Force ANSI output
<info>--no-ansi</info> Disable ANSI output
<info>--no-interaction</info> (-n) Do not ask any interactive question
<comment>Available commands for the "foo" namespace:</comment>
<info>foo:bar </info> The foo:bar command

View File

@@ -1,144 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<symfony>
<commands>
<command id="help" name="help">
<usage>help [--xml] [--format="..."] [--raw] [command_name]</usage>
<description>Displays help for a command</description>
<help>The &lt;info&gt;help&lt;/info&gt; command displays help for a given command:
&lt;info&gt;php app/console help list&lt;/info&gt;
You can also output the help in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
&lt;info&gt;php app/console help --format=xml list&lt;/info&gt;
To display the list of available commands, please use the &lt;info&gt;list&lt;/info&gt; command.</help>
<aliases />
<arguments>
<argument name="command_name" is_required="0" is_array="0">
<description>The command name</description>
<defaults>
<default>help</default>
</defaults>
</argument>
</arguments>
<options>
<option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>To output help as XML</description>
</option>
<option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
<description>To output help in other formats</description>
<defaults>
<default>txt</default>
</defaults>
</option>
<option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>To output raw command help</description>
</option>
<option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
<description>Display this help message</description>
</option>
<option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
<description>Do not output any message</description>
</option>
<option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
<description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
</option>
<option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
<description>Display this application version</description>
</option>
<option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>Force ANSI output</description>
</option>
<option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>Disable ANSI output</description>
</option>
<option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
<description>Do not ask any interactive question</description>
</option>
</options>
</command>
<command id="list" name="list">
<usage>list [--xml] [--raw] [--format="..."] [namespace]</usage>
<description>Lists commands</description>
<help>The &lt;info&gt;list&lt;/info&gt; command lists all commands:
&lt;info&gt;php app/console list&lt;/info&gt;
You can also display the commands for a specific namespace:
&lt;info&gt;php app/console list test&lt;/info&gt;
You can also output the information in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
&lt;info&gt;php app/console list --format=xml&lt;/info&gt;
It's also possible to get raw list of commands (useful for embedding command runner):
&lt;info&gt;php app/console list --raw&lt;/info&gt;</help>
<aliases/>
<arguments>
<argument name="namespace" is_required="0" is_array="0">
<description>The namespace name</description>
<defaults/>
</argument>
</arguments>
<options>
<option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>To output list as XML</description>
</option>
<option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>To output raw command list</description>
</option>
<option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
<description>To output list in other formats</description>
<defaults>
<default>txt</default>
</defaults>
</option>
</options>
</command>
<command id="foo:bar" name="foo:bar">
<usage>foo:bar</usage>
<description>The foo:bar command</description>
<help/>
<aliases>
<alias>afoobar</alias>
</aliases>
<arguments/>
<options>
<option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
<description>Display this help message</description>
</option>
<option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
<description>Do not output any message</description>
</option>
<option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
<description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
</option>
<option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
<description>Display this application version</description>
</option>
<option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>Force ANSI output</description>
</option>
<option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>Disable ANSI output</description>
</option>
<option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
<description>Do not ask any interactive question</description>
</option>
</options>
</command>
</commands>
<namespaces>
<namespace id="_global">
<command>afoobar</command>
<command>help</command>
<command>list</command>
</namespace>
<namespace id="foo">
<command>foo:bar</command>
</namespace>
</namespaces>
</symfony>

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<symfony>
<commands namespace="foo">
<command id="foo:bar" name="foo:bar">
<usage>foo:bar</usage>
<description>The foo:bar command</description>
<help/>
<aliases>
<alias>afoobar</alias>
</aliases>
<arguments/>
<options>
<option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
<description>Display this help message</description>
</option>
<option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
<description>Do not output any message</description>
</option>
<option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
<description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
</option>
<option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
<description>Display this application version</description>
</option>
<option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>Force ANSI output</description>
</option>
<option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
<description>Disable ANSI output</description>
</option>
<option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
<description>Do not ask any interactive question</description>
</option>
</options>
</command>
</commands>
</symfony>

View File

@@ -1,8 +0,0 @@
[InvalidArgumentException]
Command "foo" is not defined.

View File

@@ -1,11 +0,0 @@
[InvalidArgumentException]
The "--foo" option does not exist.
list [--xml] [--raw] [--format="..."] [namespace]

View File

@@ -1,9 +0,0 @@
[InvalidArgumentException]
Command "foo" is not define
d.

View File

@@ -1,17 +0,0 @@
Console Tool
Usage:
command [options] [arguments]
Options:
--help (-h) Display this help message
--quiet (-q) Do not output any message
--verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
--version (-V) Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
--no-interaction (-n) Do not ask any interactive question
Available commands:
help Displays help for a command
list Lists commands

View File

@@ -1,29 +0,0 @@
Usage:
help [--xml] [--format="..."] [--raw] [command_name]
Arguments:
command The command to execute
command_name The command name (default: "help")
Options:
--xml To output help as XML
--format To output help in other formats (default: "txt")
--raw To output raw command help
--help (-h) Display this help message
--quiet (-q) Do not output any message
--verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
--version (-V) Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
--no-interaction (-n) Do not ask any interactive question
Help:
The help command displays help for a given command:
php app/console help list
You can also output the help in other formats by using the --format option:
php app/console help --format=xml list
To display the list of available commands, please use the list command.

View File

@@ -1 +0,0 @@
{"name":"descriptor:command1","usage":"descriptor:command1","description":"command 1 description","help":"command 1 help","aliases":["alias1","alias2"],"definition":{"arguments":[],"options":[]}}

View File

@@ -1,7 +0,0 @@
<comment>Usage:</comment>
descriptor:command1
<comment>Aliases:</comment> <info>alias1, alias2</info>
<comment>Help:</comment>
command 1 help

View File

@@ -1 +0,0 @@
{"name":"descriptor:command2","usage":"descriptor:command2 [-o|--option_name] argument_name","description":"command 2 description","help":"command 2 help","aliases":[],"definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}}

View File

@@ -1,11 +0,0 @@
<comment>Usage:</comment>
descriptor:command2 [-o|--option_name] argument_name
<comment>Arguments:</comment>
<info>argument_name </info>
<comment>Options:</comment>
<info>--option_name</info> (-o)
<comment>Help:</comment>
command 2 help

View File

@@ -1,18 +0,0 @@
<comment>Usage:</comment>
namespace:name
<comment>Aliases:</comment> <info>name</info>
<comment>Arguments:</comment>
<info>command </info> The command to execute
<comment>Options:</comment>
<info>--help</info> (-h) Display this help message
<info>--quiet</info> (-q) Do not output any message
<info>--verbose</info> (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
<info>--version</info> (-V) Display this application version
<info>--ansi</info> Force ANSI output
<info>--no-ansi</info> Disable ANSI output
<info>--no-interaction</info> (-n) Do not ask any interactive question
<comment>Help:</comment>
help

View File

@@ -1,11 +0,0 @@
<comment>Arguments:</comment>
<info>foo </info> The foo argument
<info>baz </info> The baz argument<comment> (default: true)</comment>
<info>bar </info> The bar argument<comment> (default: ["http://foo.com/"])</comment>
<comment>Options:</comment>
<info>--foo</info> (-f) The foo option
<info>--baz</info> The baz option<comment> (default: false)</comment>
<info>--bar</info> (-b) The bar option<comment> (default: "bar")</comment>
<info>--qux</info> The qux option<comment> (default: ["http://foo.com/","bar"])</comment><comment> (multiple values allowed)</comment>
<info>--qux2</info> The qux2 option<comment> (default: {"foo":"bar"})</comment><comment> (multiple values allowed)</comment>

View File

@@ -1 +0,0 @@
<info>argument_name</info>

View File

@@ -1 +0,0 @@
<info>argument_name</info> argument description

View File

@@ -1 +0,0 @@
<info>argument_name</info> argument description<comment> (default: "default_value")</comment>

View File

@@ -1,2 +0,0 @@
<comment>Options:</comment>
<info>--option_name</info> (-o)

Some files were not shown because too many files have changed in this diff Show More