1
0
mirror of synced 2024-12-14 15:16:04 +03:00

DBAL-16 - Update Symfony\Component\Console to latest version to fix upstream bug

This commit is contained in:
Benjamin Eberlei 2010-10-30 13:24:50 +02:00
parent aa2a80f3ff
commit b5c5ec3c69
25 changed files with 3170 additions and 3387 deletions

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application; use Symfony\Component\Console\Application;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -21,510 +21,492 @@ use Symfony\Component\Console\Application;
/** /**
* Base class for all commands. * Base class for all commands.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class Command class Command
{ {
protected $name; protected $name;
protected $namespace; protected $namespace;
protected $aliases; protected $aliases;
protected $definition; protected $definition;
protected $help; protected $help;
protected $application; protected $application;
protected $description; protected $description;
protected $ignoreValidationErrors; protected $ignoreValidationErrors;
protected $formatter; protected $applicationDefinitionMerged;
protected $applicationDefinitionMerged; protected $code;
protected $code;
/** /**
* Constructor. * Constructor.
* *
* @param string $name The name of the command * @param string $name The name of the command
*/ *
public function __construct($name = null) * @throws \LogicException When the command name is empty
{ */
$this->definition = new InputDefinition(); public function __construct($name = null)
$this->ignoreValidationErrors = false;
$this->applicationDefinitionMerged = false;
$this->aliases = array();
if (null !== $name)
{ {
$this->setName($name); $this->definition = new InputDefinition();
$this->ignoreValidationErrors = false;
$this->applicationDefinitionMerged = false;
$this->aliases = array();
if (null !== $name) {
$this->setName($name);
}
$this->configure();
if (!$this->name) {
throw new \LogicException('The command name cannot be empty.');
}
} }
$this->configure(); /**
* Sets the application instance for this command.
if (!$this->name) *
* @param Application $application An Application instance
*/
public function setApplication(Application $application = null)
{ {
throw new \LogicException('The command name cannot be empty.'); $this->application = $application;
}
}
/**
* Sets the application instance for this command.
*
* @param Application $application An Application instance
*/
public function setApplication(Application $application = null)
{
$this->application = $application;
}
/**
* Configures the current command.
*/
protected function configure()
{
}
/**
* Executes the current command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @return integer 0 if everything went fine, or an error code
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
throw new \LogicException('You must override the execute() method in the concrete command class.');
}
/**
* Interacts with the user.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
}
/**
* Initializes the command just after the input has been validated.
*
* This is mainly useful when a lot of commands extends one main command
* where some things need to be initialized based on the input arguments and options.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
}
/**
* Runs the command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
public function run(InputInterface $input, OutputInterface $output)
{
// add the application arguments and options
$this->mergeApplicationDefinition();
// bind the input against the command specific arguments/options
try
{
$input->bind($this->definition);
}
catch (\Exception $e)
{
if (!$this->ignoreValidationErrors)
{
throw $e;
}
} }
$this->initialize($input, $output); /**
* Configures the current command.
if ($input->isInteractive()) */
protected function configure()
{ {
$this->interact($input, $output);
} }
$input->validate(); /**
* Executes the current command.
if ($this->code) *
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @return integer 0 if everything went fine, or an error code
*
* @throws \LogicException When this abstract class is not implemented
*/
protected function execute(InputInterface $input, OutputInterface $output)
{ {
return call_user_func($this->code, $input, $output); throw new \LogicException('You must override the execute() method in the concrete command class.');
}
else
{
return $this->execute($input, $output);
}
}
/**
* Sets the code to execute when running this command.
*
* @param \Closure $code A \Closure
*
* @return Command The current instance
*/
public function setCode(\Closure $code)
{
$this->code = $code;
return $this;
}
/**
* Merges the application definition with the command definition.
*/
protected function mergeApplicationDefinition()
{
if (null === $this->application || true === $this->applicationDefinitionMerged)
{
return;
} }
$this->definition->setArguments(array_merge( /**
$this->application->getDefinition()->getArguments(), * Interacts with the user.
$this->definition->getArguments() *
)); * @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
$this->definition->addOptions($this->application->getDefinition()->getOptions()); */
protected function interact(InputInterface $input, OutputInterface $output)
$this->applicationDefinitionMerged = true;
}
/**
* Sets an array of argument and option instances.
*
* @param array|Definition $definition An array of argument and option instances or a definition instance
*
* @return Command The current instance
*/
public function setDefinition($definition)
{
if ($definition instanceof InputDefinition)
{ {
$this->definition = $definition;
}
else
{
$this->definition->setDefinition($definition);
} }
$this->applicationDefinitionMerged = false; /**
* Initializes the command just after the input has been validated.
return $this; *
} * This is mainly useful when a lot of commands extends one main command
* where some things need to be initialized based on the input arguments and options.
/** *
* Gets the InputDefinition attached to this Command. * @param InputInterface $input An InputInterface instance
* * @param OutputInterface $output An OutputInterface instance
* @return InputDefinition $definition An InputDefinition instance */
*/ protected function initialize(InputInterface $input, OutputInterface $output)
public function getDefinition()
{
return $this->definition;
}
/**
* Adds an argument.
*
* @param string $name The argument name
* @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
*
* @return Command The current instance
*/
public function addArgument($name, $mode = null, $description = '', $default = null)
{
$this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
return $this;
}
/**
* Adds an option.
*
* @param string $name The option name
* @param string $shortcut The shortcut (can be null)
* @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE)
*
* @return Command The current instance
*/
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
{
$this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
return $this;
}
/**
* Sets the name of the command.
*
* This method can set both the namespace and the name if
* you separate them by a colon (:)
*
* $command->setName('foo:bar');
*
* @param string $name The command name
*
* @return Command The current instance
*/
public function setName($name)
{
if (false !== $pos = strrpos($name, ':'))
{ {
$namespace = substr($name, 0, $pos);
$name = substr($name, $pos + 1);
}
else
{
$namespace = $this->namespace;
} }
if (!$name) /**
* Runs the command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
public function run(InputInterface $input, OutputInterface $output)
{ {
throw new \InvalidArgumentException('A command name cannot be empty'); // add the application arguments and options
$this->mergeApplicationDefinition();
// bind the input against the command specific arguments/options
try {
$input->bind($this->definition);
} catch (\Exception $e) {
if (!$this->ignoreValidationErrors) {
throw $e;
}
}
$this->initialize($input, $output);
if ($input->isInteractive()) {
$this->interact($input, $output);
}
$input->validate();
if ($this->code) {
return call_user_func($this->code, $input, $output);
} else {
return $this->execute($input, $output);
}
} }
$this->namespace = $namespace; /**
$this->name = $name; * Sets the code to execute when running this command.
*
return $this; * @param \Closure $code A \Closure
} *
* @return Command The current instance
/** */
* Returns the command namespace. public function setCode(\Closure $code)
*
* @return string The command namespace
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* Returns the command name
*
* @return string The command name
*/
public function getName()
{
return $this->name;
}
/**
* Returns the fully qualified command name.
*
* @return string The fully qualified command name
*/
public function getFullName()
{
return $this->getNamespace() ? $this->getNamespace().':'.$this->getName() : $this->getName();
}
/**
* Sets the description for the command.
*
* @param string $description The description for the command
*
* @return Command The current instance
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Returns the description for the command.
*
* @return string The description for the command
*/
public function getDescription()
{
return $this->description;
}
/**
* Sets the help for the command.
*
* @param string $help The help for the command
*
* @return Command The current instance
*/
public function setHelp($help)
{
$this->help = $help;
return $this;
}
/**
* Returns the help for the command.
*
* @return string The help for the command
*/
public function getHelp()
{
return $this->help;
}
/**
* Returns the processed help for the command replacing the %command.name% and
* %command.full_name% patterns with the real values dynamically.
*
* @return string The processed help for the command
*/
public function getProcessedHelp()
{
$name = $this->namespace.':'.$this->name;
$placeholders = array(
'%command.name%',
'%command.full_name%'
);
$replacements = array(
$name,
$_SERVER['PHP_SELF'].' '.$name
);
return str_replace($placeholders, $replacements, $this->getHelp());
}
/**
* Sets the aliases for the command.
*
* @param array $aliases An array of aliases for the command
*
* @return Command The current instance
*/
public function setAliases($aliases)
{
$this->aliases = $aliases;
return $this;
}
/**
* Returns the aliases for the command.
*
* @return array An array of aliases for the command
*/
public function getAliases()
{
return $this->aliases;
}
/**
* Returns the synopsis for the command.
*
* @return string The synopsis
*/
public function getSynopsis()
{
return sprintf('%s %s', $this->getFullName(), $this->definition->getSynopsis());
}
/**
* Gets a helper instance by name.
*
* @param string $name The helper name
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
*/
protected function getHelper($name)
{
return $this->application->getHelperSet()->get($name);
}
/**
* Gets a helper instance by name.
*
* @param string $name The helper name
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
*/
public function __get($name)
{
return $this->application->getHelperSet()->get($name);
}
/**
* Returns a text representation of the command.
*
* @return string A string representing the command
*/
public function asText()
{
$messages = array(
'<comment>Usage:</comment>',
' '.$this->getSynopsis(),
'',
);
if ($this->getAliases())
{ {
$messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $this->getAliases()).'</info>'; $this->code = $code;
return $this;
} }
$messages[] = $this->definition->asText(); /**
* Merges the application definition with the command definition.
if ($help = $this->getProcessedHelp()) */
protected function mergeApplicationDefinition()
{ {
$messages[] = '<comment>Help:</comment>'; if (null === $this->application || true === $this->applicationDefinitionMerged) {
$messages[] = ' '.implode("\n ", explode("\n", $help))."\n"; return;
}
$this->definition->setArguments(array_merge(
$this->application->getDefinition()->getArguments(),
$this->definition->getArguments()
));
$this->definition->addOptions($this->application->getDefinition()->getOptions());
$this->applicationDefinitionMerged = true;
} }
return implode("\n", $messages); /**
} * Sets an array of argument and option instances.
*
/** * @param array|Definition $definition An array of argument and option instances or a definition instance
* Returns an XML representation of the command. *
* * @return Command The current instance
* @param Boolean $asDom Whether to return a DOM or an XML string */
* public function setDefinition($definition)
* @return string|DOMDocument An XML string representing the command
*/
public function asXml($asDom = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($commandXML = $dom->createElement('command'));
$commandXML->setAttribute('id', $this->getFullName());
$commandXML->setAttribute('namespace', $this->getNamespace() ? $this->getNamespace() : '_global');
$commandXML->setAttribute('name', $this->getName());
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
$usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $this->getDescription()))));
$commandXML->appendChild($helpXML = $dom->createElement('help'));
$help = $this->help;
$helpXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $help))));
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
foreach ($this->getAliases() as $alias)
{ {
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias')); if ($definition instanceof InputDefinition) {
$aliasXML->appendChild($dom->createTextNode($alias)); $this->definition = $definition;
} else {
$this->definition->setDefinition($definition);
}
$this->applicationDefinitionMerged = false;
return $this;
} }
$definition = $this->definition->asXml(true); /**
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true)); * Gets the InputDefinition attached to this Command.
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true)); *
* @return InputDefinition An InputDefinition instance
*/
public function getDefinition()
{
return $this->definition;
}
return $asDom ? $dom : $dom->saveXml(); /**
} * Adds an argument.
*
* @param string $name The argument name
* @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
*
* @return Command The current instance
*/
public function addArgument($name, $mode = null, $description = '', $default = null)
{
$this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
return $this;
}
/**
* Adds an option.
*
* @param string $name The option name
* @param string $shortcut The shortcut (can be null)
* @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE)
*
* @return Command The current instance
*/
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
{
$this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
return $this;
}
/**
* Sets the name of the command.
*
* This method can set both the namespace and the name if
* you separate them by a colon (:)
*
* $command->setName('foo:bar');
*
* @param string $name The command name
*
* @return Command The current instance
*
* @throws \InvalidArgumentException When command name given is empty
*/
public function setName($name)
{
if (false !== $pos = strrpos($name, ':')) {
$namespace = substr($name, 0, $pos);
$name = substr($name, $pos + 1);
} else {
$namespace = $this->namespace;
}
if (!$name) {
throw new \InvalidArgumentException('A command name cannot be empty.');
}
$this->namespace = $namespace;
$this->name = $name;
return $this;
}
/**
* Returns the command namespace.
*
* @return string The command namespace
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* Returns the command name
*
* @return string The command name
*/
public function getName()
{
return $this->name;
}
/**
* Returns the fully qualified command name.
*
* @return string The fully qualified command name
*/
public function getFullName()
{
return $this->getNamespace() ? $this->getNamespace().':'.$this->getName() : $this->getName();
}
/**
* Sets the description for the command.
*
* @param string $description The description for the command
*
* @return Command The current instance
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Returns the description for the command.
*
* @return string The description for the command
*/
public function getDescription()
{
return $this->description;
}
/**
* Sets the help for the command.
*
* @param string $help The help for the command
*
* @return Command The current instance
*/
public function setHelp($help)
{
$this->help = $help;
return $this;
}
/**
* Returns the help for the command.
*
* @return string The help for the command
*/
public function getHelp()
{
return $this->help;
}
/**
* Returns the processed help for the command replacing the %command.name% and
* %command.full_name% patterns with the real values dynamically.
*
* @return string The processed help for the command
*/
public function getProcessedHelp()
{
$name = $this->namespace.':'.$this->name;
$placeholders = array(
'%command.name%',
'%command.full_name%'
);
$replacements = array(
$name,
$_SERVER['PHP_SELF'].' '.$name
);
return str_replace($placeholders, $replacements, $this->getHelp());
}
/**
* Sets the aliases for the command.
*
* @param array $aliases An array of aliases for the command
*
* @return Command The current instance
*/
public function setAliases($aliases)
{
$this->aliases = $aliases;
return $this;
}
/**
* Returns the aliases for the command.
*
* @return array An array of aliases for the command
*/
public function getAliases()
{
return $this->aliases;
}
/**
* Returns the synopsis for the command.
*
* @return string The synopsis
*/
public function getSynopsis()
{
return sprintf('%s %s', $this->getFullName(), $this->definition->getSynopsis());
}
/**
* Gets a helper instance by name.
*
* @param string $name The helper name
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
*/
protected function getHelper($name)
{
return $this->application->getHelperSet()->get($name);
}
/**
* Gets a helper instance by name.
*
* @param string $name The helper name
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
*/
public function __get($name)
{
return $this->application->getHelperSet()->get($name);
}
/**
* Returns a text representation of the command.
*
* @return string A string representing the command
*/
public function asText()
{
$messages = array(
'<comment>Usage:</comment>',
' '.$this->getSynopsis(),
'',
);
if ($this->getAliases()) {
$messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $this->getAliases()).'</info>';
}
$messages[] = $this->definition->asText();
if ($help = $this->getProcessedHelp()) {
$messages[] = '<comment>Help:</comment>';
$messages[] = ' '.implode("\n ", explode("\n", $help))."\n";
}
return implode("\n", $messages);
}
/**
* Returns an XML representation of the command.
*
* @param Boolean $asDom Whether to return a DOM or an XML string
*
* @return string|DOMDocument An XML string representing the command
*/
public function asXml($asDom = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($commandXML = $dom->createElement('command'));
$commandXML->setAttribute('id', $this->getFullName());
$commandXML->setAttribute('namespace', $this->getNamespace() ? $this->getNamespace() : '_global');
$commandXML->setAttribute('name', $this->getName());
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
$usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $this->getDescription()))));
$commandXML->appendChild($helpXML = $dom->createElement('help'));
$help = $this->help;
$helpXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $help))));
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
foreach ($this->getAliases() as $alias) {
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
$aliasXML->appendChild($dom->createTextNode($alias));
}
$definition = $this->definition->asXml(true);
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true));
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true));
return $asDom ? $dom : $dom->saveXml();
}
} }

View File

@ -10,7 +10,7 @@ use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -21,63 +21,57 @@ use Symfony\Component\Console\Command\Command;
/** /**
* HelpCommand displays the help for a given command. * HelpCommand displays the help for a given command.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class HelpCommand extends Command class HelpCommand extends Command
{ {
protected $command; protected $command;
/** /**
* @see Command * @see Command
*/ */
protected function configure() protected function configure()
{ {
$this->ignoreValidationErrors = true; $this->ignoreValidationErrors = true;
$this $this
->setDefinition(array( ->setDefinition(array(
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'), new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'),
)) ))
->setName('help') ->setName('help')
->setAliases(array('?')) ->setAliases(array('?'))
->setDescription('Displays help for a command') ->setDescription('Displays help for a command')
->setHelp(<<<EOF ->setHelp(<<<EOF
The <info>help</info> command displays help for a given command: The <info>help</info> command displays help for a given command:
<info>./symfony help test:all</info> <info>./symfony help list</info>
You can also output the help as XML by using the <comment>--xml</comment> option: You can also output the help as XML by using the <comment>--xml</comment> option:
<info>./symfony help --xml test:all</info> <info>./symfony help --xml list</info>
EOF EOF
); );
}
public function setCommand(Command $command)
{
$this->command = $command;
}
/**
* @see Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if (null === $this->command)
{
$this->command = $this->application->getCommand($input->getArgument('command_name'));
} }
if ($input->getOption('xml')) public function setCommand(Command $command)
{ {
$output->writeln($this->command->asXml(), Output::OUTPUT_RAW); $this->command = $command;
} }
else
/**
* @see Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{ {
$output->writeln($this->command->asText()); if (null === $this->command) {
$this->command = $this->application->getCommand($input->getArgument('command_name'));
}
if ($input->getOption('xml')) {
$output->writeln($this->command->asXml(), Output::OUTPUT_RAW);
} else {
$output->writeln($this->command->asText());
}
} }
}
} }

View File

@ -10,7 +10,7 @@ use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -21,25 +21,23 @@ use Symfony\Component\Console\Command\Command;
/** /**
* ListCommand displays the list of all available commands for the application. * ListCommand displays the list of all available commands for the application.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class ListCommand extends Command class ListCommand extends Command
{ {
/** /**
* @see Command * @see Command
*/ */
protected function configure() protected function configure()
{ {
$this $this
->setDefinition(array( ->setDefinition(array(
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'), new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'),
)) ))
->setName('list') ->setName('list')
->setDescription('Lists commands') ->setDescription('Lists commands')
->setHelp(<<<EOF ->setHelp(<<<EOF
The <info>list</info> command lists all commands: The <info>list</info> command lists all commands:
<info>./symfony list</info> <info>./symfony list</info>
@ -52,21 +50,18 @@ You can also output the information as XML by using the <comment>--xml</comment>
<info>./symfony list --xml</info> <info>./symfony list --xml</info>
EOF EOF
); );
} }
/** /**
* @see Command * @see Command
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('xml'))
{ {
$output->writeln($this->application->asXml($input->getArgument('namespace')), Output::OUTPUT_RAW); if ($input->getOption('xml')) {
$output->writeln($this->application->asXml($input->getArgument('namespace')), Output::OUTPUT_RAW);
} else {
$output->writeln($this->application->asText($input->getArgument('namespace')));
}
} }
else
{
$output->writeln($this->application->asText($input->getArgument('namespace')));
}
}
} }

View File

@ -5,7 +5,7 @@ namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -16,104 +16,95 @@ use Symfony\Component\Console\Output\OutputInterface;
/** /**
* The Dialog class provides helpers to interact with the user. * The Dialog class provides helpers to interact with the user.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class DialogHelper extends Helper class DialogHelper extends Helper
{ {
/** /**
* Asks a question to the user. * Asks a question to the user.
* *
* @param OutputInterface $output * @param OutputInterface $output
* @param string|array $question The question to ask * @param string|array $question The question to ask
* @param string $default The default answer if none is given by the user * @param string $default The default answer if none is given by the user
* *
* @param string The user answer * @return string The user answer
*/ */
public function ask(OutputInterface $output, $question, $default = null) public function ask(OutputInterface $output, $question, $default = null)
{
// @codeCoverageIgnoreStart
$output->writeln($question);
$ret = trim(fgets(STDIN));
return $ret ? $ret : $default;
// @codeCoverageIgnoreEnd
}
/**
* Asks a confirmation to the user.
*
* The question will be asked until the user answer by nothing, yes, or no.
*
* @param OutputInterface $output
* @param string|array $question The question to ask
* @param Boolean $default The default answer if the user enters nothing
*
* @param Boolean true if the user has confirmed, false otherwise
*/
public function askConfirmation(OutputInterface $output, $question, $default = true)
{
// @codeCoverageIgnoreStart
$answer = 'z';
while ($answer && !in_array(strtolower($answer[0]), array('y', 'n')))
{ {
$answer = $this->ask($output, $question); // @codeCoverageIgnoreStart
$output->writeln($question);
$ret = trim(fgets(STDIN));
return $ret ? $ret : $default;
// @codeCoverageIgnoreEnd
} }
if (false === $default) /**
* Asks a confirmation to the user.
*
* The question will be asked until the user answer by nothing, yes, or no.
*
* @param OutputInterface $output
* @param string|array $question The question to ask
* @param Boolean $default The default answer if the user enters nothing
*
* @return Boolean true if the user has confirmed, false otherwise
*/
public function askConfirmation(OutputInterface $output, $question, $default = true)
{ {
return $answer && 'y' == strtolower($answer[0]); // @codeCoverageIgnoreStart
} $answer = 'z';
else while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
{ $answer = $this->ask($output, $question);
return !$answer || 'y' == strtolower($answer[0]); }
}
// @codeCoverageIgnoreEnd
}
/** if (false === $default) {
* Asks for a value and validates the response. return $answer && 'y' == strtolower($answer[0]);
* } else {
* @param OutputInterface $output return !$answer || 'y' == strtolower($answer[0]);
* @param string|array $question }
* @param Closure $validator // @codeCoverageIgnoreEnd
* @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite)
*
* @return mixed
*/
public function askAndValidate(OutputInterface $output, $question, \Closure $validator, $attempts = false)
{
// @codeCoverageIgnoreStart
$error = null;
while (false === $attempts || $attempts--)
{
if (null !== $error)
{
$output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
}
$value = $this->ask($output, $question, null);
try
{
return $validator($value);
}
catch (\Exception $error)
{
}
} }
throw $error; /**
// @codeCoverageIgnoreEnd * Asks for a value and validates the response.
} *
* @param OutputInterface $output
* @param string|array $question
* @param Closure $validator
* @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite)
*
* @return mixed
*
* @throws \Exception When any of the validator returns an error
*/
public function askAndValidate(OutputInterface $output, $question, \Closure $validator, $attempts = false)
{
// @codeCoverageIgnoreStart
$error = null;
while (false === $attempts || $attempts--) {
if (null !== $error) {
$output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
}
/** $value = $this->ask($output, $question, null);
* Returns the helper's canonical name
*/ try {
public function getName() return $validator($value);
{ } catch (\Exception $error) {
return 'dialog'; }
} }
throw $error;
// @codeCoverageIgnoreEnd
}
/**
* Returns the helper's canonical name
*/
public function getName()
{
return 'dialog';
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Helper; namespace Symfony\Component\Console\Helper;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -14,76 +14,69 @@ namespace Symfony\Component\Console\Helper;
/** /**
* The Formatter class provides helpers to format messages. * The Formatter class provides helpers to format messages.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class FormatterHelper extends Helper class FormatterHelper extends Helper
{ {
/** /**
* Formats a message within a section. * Formats a message within a section.
* *
* @param string $section The section name * @param string $section The section name
* @param string $message The message * @param string $message The message
* @param string $style The style to apply to the section * @param string $style The style to apply to the section
*/ */
public function formatSection($section, $message, $style = 'info') public function formatSection($section, $message, $style = 'info')
{
return sprintf("<%s>[%s]</%s> %s", $style, $section, $style, $message);
}
/**
* Formats a message as a block of text.
*
* @param string|array $messages The message to write in the block
* @param string $style The style to apply to the whole block
* @param Boolean $large Whether to return a large block
*
* @return string The formatter message
*/
public function formatBlock($messages, $style, $large = false)
{
if (!is_array($messages))
{ {
$messages = array($messages); return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
} }
$len = 0; /**
$lines = array(); * Formats a message as a block of text.
foreach ($messages as $message) *
* @param string|array $messages The message to write in the block
* @param string $style The style to apply to the whole block
* @param Boolean $large Whether to return a large block
*
* @return string The formatter message
*/
public function formatBlock($messages, $style, $large = false)
{ {
$lines[] = sprintf($large ? ' %s ' : ' %s ', $message); if (!is_array($messages)) {
$len = max($this->strlen($message) + ($large ? 4 : 2), $len); $messages = array($messages);
}
$len = 0;
$lines = array();
foreach ($messages as $message) {
$lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
$len = max($this->strlen($message) + ($large ? 4 : 2), $len);
}
$messages = $large ? array(str_repeat(' ', $len)) : array();
foreach ($lines as $line) {
$messages[] = $line.str_repeat(' ', $len - $this->strlen($line));
}
if ($large) {
$messages[] = str_repeat(' ', $len);
}
foreach ($messages as &$message) {
$message = sprintf('<%s>%s</%s>', $style, $message, $style);
}
return implode("\n", $messages);
} }
$messages = $large ? array(str_repeat(' ', $len)) : array(); protected function strlen($string)
foreach ($lines as $line)
{ {
$messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string);
}
if ($large)
{
$messages[] = str_repeat(' ', $len);
} }
foreach ($messages as &$message) /**
* Returns the helper's canonical name
*/
public function getName()
{ {
$message = sprintf('<%s>%s</%s>', $style, $message, $style); return 'formatter';
} }
return implode("\n", $messages);
}
protected function strlen($string)
{
return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string);
}
/**
* Returns the helper's canonical name
*/
public function getName()
{
return 'formatter';
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Helper; namespace Symfony\Component\Console\Helper;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -14,32 +14,29 @@ namespace Symfony\Component\Console\Helper;
/** /**
* Helper is the base class for all helper classes. * Helper is the base class for all helper classes.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
abstract class Helper implements HelperInterface abstract class Helper implements HelperInterface
{ {
protected protected $helperSet = null;
$helperSet = null;
/** /**
* Sets the helper set associated with this helper. * Sets the helper set associated with this helper.
* *
* @param HelperSet $helperSet A HelperSet instance * @param HelperSet $helperSet A HelperSet instance
*/ */
public function setHelperSet(HelperSet $helperSet = null) public function setHelperSet(HelperSet $helperSet = null)
{ {
$this->helperSet = $helperSet; $this->helperSet = $helperSet;
} }
/** /**
* Gets the helper set associated with this helper. * Gets the helper set associated with this helper.
* *
* @return HelperSet A HelperSet instance * @return HelperSet A HelperSet instance
*/ */
public function getHelperSet() public function getHelperSet()
{ {
return $this->helperSet; return $this->helperSet;
} }
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Helper; namespace Symfony\Component\Console\Helper;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -14,30 +14,28 @@ namespace Symfony\Component\Console\Helper;
/** /**
* HelperInterface is the interface all helpers must implement. * HelperInterface is the interface all helpers must implement.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
interface HelperInterface interface HelperInterface
{ {
/** /**
* Sets the helper set associated with this helper. * Sets the helper set associated with this helper.
* *
* @param HelperSet $helperSet A HelperSet instance * @param HelperSet $helperSet A HelperSet instance
*/ */
function setHelperSet(HelperSet $helperSet = null); function setHelperSet(HelperSet $helperSet = null);
/** /**
* Gets the helper set associated with this helper. * Gets the helper set associated with this helper.
* *
* @return HelperSet A HelperSet instance * @return HelperSet A HelperSet instance
*/ */
function getHelperSet(); function getHelperSet();
/** /**
* Returns the canonical name of this helper. * Returns the canonical name of this helper.
* *
* @return string The canonical name * @return string The canonical name
*/ */
function getName(); function getName();
} }

View File

@ -5,7 +5,7 @@ namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -16,89 +16,87 @@ use Symfony\Component\Console\Command\Command;
/** /**
* HelperSet represents a set of helpers to be used with a command. * HelperSet represents a set of helpers to be used with a command.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class HelperSet class HelperSet
{ {
protected protected $helpers;
$helpers = array(), protected $command;
$command = null;
public function __construct(array $helpers = array()) /**
{ * @param Helper[] $helpers An array of helper.
foreach ($helpers as $alias => $helper) */
public function __construct(array $helpers = array())
{ {
$this->set($helper, is_int($alias) ? null : $alias); $this->helpers = array();
} foreach ($helpers as $alias => $helper) {
} $this->set($helper, is_int($alias) ? null : $alias);
}
/**
* Sets a helper.
*
* @param HelperInterface $value The helper instance
* @param string $alias An alias
*/
public function set(HelperInterface $helper, $alias = null)
{
$this->helpers[$helper->getName()] = $helper;
if (null !== $alias)
{
$this->helpers[$alias] = $helper;
} }
$helper->setHelperSet($this); /**
} * Sets a helper.
*
/** * @param HelperInterface $value The helper instance
* Returns true if the helper if defined. * @param string $alias An alias
* */
* @param string $name The helper name public function set(HelperInterface $helper, $alias = null)
*
* @return Boolean true if the helper is defined, false otherwise
*/
public function has($name)
{
return isset($this->helpers[$name]);
}
/**
* Gets a helper value.
*
* @param string $name The helper name
*
* @return HelperInterface The helper instance
*
* @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)); $this->helpers[$helper->getName()] = $helper;
if (null !== $alias) {
$this->helpers[$alias] = $helper;
}
$helper->setHelperSet($this);
} }
return $this->helpers[$name]; /**
} * Returns true if the helper if defined.
*
* @param string $name The helper name
*
* @return Boolean true if the helper is defined, false otherwise
*/
public function has($name)
{
return isset($this->helpers[$name]);
}
/** /**
* Sets the command associated with this helper set. * Gets a helper value.
* *
* @param Command $command A Command instance * @param string $name The helper name
*/ *
public function setCommand(Command $command = null) * @return HelperInterface The helper instance
{ *
$this->command = $command; * @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));
}
/** return $this->helpers[$name];
* Gets the command associated with this helper set. }
*
* @return Command A Command instance /**
*/ * Sets the command associated with this helper set.
public function getCommand() *
{ * @param Command $command A Command instance
return $this->command; */
} public function setCommand(Command $command = null)
{
$this->command = $command;
}
/**
* Gets the command associated with this helper set.
*
* @return Command A Command instance
*/
public function getCommand()
{
return $this->command;
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Input; namespace Symfony\Component\Console\Input;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -20,7 +20,7 @@ namespace Symfony\Component\Console\Input;
* *
* By default, the `$_SERVER['argv']` array is used for the input values. * By default, the `$_SERVER['argv']` array is used for the input values.
* *
* This can be overriden by explicitly passing the input values in the constructor: * This can be overridden by explicitly passing the input values in the constructor:
* *
* $input = new ArgvInput($_SERVER['argv']); * $input = new ArgvInput($_SERVER['argv']);
* *
@ -31,254 +31,225 @@ namespace Symfony\Component\Console\Input;
* the same rules as the argv one. It's almost always better to use the * the same rules as the argv one. It's almost always better to use the
* `StringInput` when you want to provide your own input. * `StringInput` when you want to provide your own input.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* *
* @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html * @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 * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
*/ */
class ArgvInput extends Input class ArgvInput extends Input
{ {
protected $tokens; protected $tokens;
protected $parsed; protected $parsed;
/** /**
* Constructor. * Constructor.
* *
* @param array $argv An array of parameters from the CLI (in the argv format) * @param array $argv An array of parameters from the CLI (in the argv format)
* @param InputDefinition $definition A InputDefinition instance * @param InputDefinition $definition A InputDefinition instance
*/ */
public function __construct(array $argv = null, InputDefinition $definition = null) public function __construct(array $argv = null, InputDefinition $definition = null)
{
if (null === $argv)
{ {
$argv = $_SERVER['argv']; if (null === $argv) {
$argv = $_SERVER['argv'];
}
// strip the program name
array_shift($argv);
$this->tokens = $argv;
parent::__construct($definition);
} }
// strip the program name /**
array_shift($argv); * Processes command line arguments.
*/
$this->tokens = $argv; protected function parse()
parent::__construct($definition);
}
/**
* Processes command line arguments.
*/
protected function parse()
{
$this->parsed = $this->tokens;
while (null !== ($token = array_shift($this->parsed)))
{ {
if ('--' === substr($token, 0, 2)) $this->parsed = $this->tokens;
{ while (null !== $token = array_shift($this->parsed)) {
$this->parseLongOption($token); if ('--' === substr($token, 0, 2)) {
} $this->parseLongOption($token);
elseif ('-' === $token[0]) } elseif ('-' === $token[0]) {
{ $this->parseShortOption($token);
$this->parseShortOption($token); } else {
} $this->parseArgument($token);
else }
{ }
$this->parseArgument($token);
}
}
}
/**
* Parses a short option.
*
* @param string $token The current token.
*/
protected function parseShortOption($token)
{
$name = substr($token, 1);
if (strlen($name) > 1)
{
if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptParameter())
{
// an option with a value (with no space)
$this->addShortOption($name[0], substr($name, 1));
}
else
{
$this->parseShortOptionSet($name);
}
}
else
{
$this->addShortOption($name, null);
}
}
/**
* Parses a short option set.
*
* @param string $token The current token
*/
protected 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]));
}
$option = $this->definition->getOptionForShortcut($name[$i]);
if ($option->acceptParameter())
{
$this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
break;
}
else
{
$this->addLongOption($option->getName(), true);
}
}
}
/**
* Parses a long option.
*
* @param string $token The current token
*/
protected function parseLongOption($token)
{
$name = substr($token, 2);
if (false !== $pos = strpos($name, '='))
{
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
}
else
{
$this->addLongOption($name, null);
}
}
/**
* Parses an argument.
*
* @param string $token The current token
*/
protected function parseArgument($token)
{
if (!$this->definition->hasArgument(count($this->arguments)))
{
throw new \RuntimeException('Too many arguments.');
} }
$this->arguments[$this->definition->getArgument(count($this->arguments))->getName()] = $token; /**
} * Parses a short option.
*
/** * @param string $token The current token.
* Adds a short option value. */
* protected function parseShortOption($token)
* @param string $shortcut The short option key
* @param mixed $value The value for the option
*/
protected function addShortOption($shortcut, $value)
{
if (!$this->definition->hasShortcut($shortcut))
{ {
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); $name = substr($token, 1);
if (strlen($name) > 1) {
if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptParameter()) {
// an option with a value (with no space)
$this->addShortOption($name[0], substr($name, 1));
} else {
$this->parseShortOptionSet($name);
}
} else {
$this->addShortOption($name, null);
}
} }
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); /**
} * Parses a short option set.
*
/** * @param string $token The current token
* Adds a long option value. *
* * @throws \RuntimeException When option given doesn't exist
* @param string $name The long option key */
* @param mixed $value The value for the option protected function parseShortOptionSet($name)
*/
protected function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name))
{ {
throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $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]));
}
$option = $this->definition->getOptionForShortcut($name[$i]);
if ($option->acceptParameter()) {
$this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
break;
} else {
$this->addLongOption($option->getName(), true);
}
}
} }
$option = $this->definition->getOption($name); /**
* Parses a long option.
if (null === $value && $option->acceptParameter()) *
* @param string $token The current token
*/
protected function parseLongOption($token)
{ {
// if option accepts an optional or mandatory argument $name = substr($token, 2);
// let's see if there is one provided
$next = array_shift($this->parsed); if (false !== $pos = strpos($name, '=')) {
if ('-' !== $next[0]) $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
{ } else {
$value = $next; $this->addLongOption($name, null);
} }
else
{
array_unshift($this->parsed, $next);
}
} }
if (null === $value) /**
* Parses an argument.
*
* @param string $token The current token
*
* @throws \RuntimeException When too many arguments are given
*/
protected function parseArgument($token)
{ {
if ($option->isParameterRequired()) if (!$this->definition->hasArgument(count($this->arguments))) {
{ throw new \RuntimeException('Too many arguments.');
throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); }
}
$value = $option->isParameterOptional() ? $option->getDefault() : true; $this->arguments[$this->definition->getArgument(count($this->arguments))->getName()] = $token;
} }
$this->options[$name] = $value; /**
} * Adds a short option value.
*
/** * @param string $shortcut The short option key
* Returns the first argument from the raw parameters (not parsed). * @param mixed $value The value for the option
* *
* @return string The value of the first argument or null otherwise * @throws \RuntimeException When option given doesn't exist
*/ */
public function getFirstArgument() protected function addShortOption($shortcut, $value)
{
foreach ($this->tokens as $token)
{ {
if ($token && '-' === $token[0]) if (!$this->definition->hasShortcut($shortcut)) {
{ throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
continue; }
}
return $token; $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
}
}
/**
* Returns true if the raw parameters (not parsed) contains a value.
*
* This method is to be used to introspect the input parameters
* before it has 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)
*
* @return Boolean true if the value is contained in the raw parameters
*/
public function hasParameterOption($values)
{
if (!is_array($values))
{
$values = array($values);
} }
foreach ($this->tokens as $v) /**
* Adds a long option value.
*
* @param string $name The long option key
* @param mixed $value The value for the option
*
* @throws \RuntimeException When option given doesn't exist
*/
protected function addLongOption($name, $value)
{ {
if (in_array($v, $values)) if (!$this->definition->hasOption($name)) {
{ throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
return true; }
}
$option = $this->definition->getOption($name);
if (null === $value && $option->acceptParameter()) {
// if option accepts an optional or mandatory argument
// let's see if there is one provided
$next = array_shift($this->parsed);
if ('-' !== $next[0]) {
$value = $next;
} else {
array_unshift($this->parsed, $next);
}
}
if (null === $value) {
if ($option->isParameterRequired()) {
throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
}
$value = $option->isParameterOptional() ? $option->getDefault() : true;
}
$this->options[$name] = $value;
} }
return false; /**
} * Returns the first argument from the raw parameters (not parsed).
*
* @return string The value of the first argument or null otherwise
*/
public function getFirstArgument()
{
foreach ($this->tokens as $token) {
if ($token && '-' === $token[0]) {
continue;
}
return $token;
}
}
/**
* Returns true if the raw parameters (not parsed) contains a value.
*
* This method is to be used to introspect the input parameters
* before it has 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)
*
* @return Boolean true if the value is contained in the raw parameters
*/
public function hasParameterOption($values)
{
if (!is_array($values)) {
$values = array($values);
}
foreach ($this->tokens as $v) {
if (in_array($v, $values)) {
return true;
}
}
return false;
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Input; namespace Symfony\Component\Console\Input;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -18,157 +18,145 @@ namespace Symfony\Component\Console\Input;
* *
* $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class ArrayInput extends Input class ArrayInput extends Input
{ {
protected $parameters; protected $parameters;
/** /**
* Constructor. * Constructor.
* *
* @param array $param An array of parameters * @param array $param An array of parameters
* @param InputDefinition $definition A InputDefinition instance * @param InputDefinition $definition A InputDefinition instance
*/ */
public function __construct(array $parameters, InputDefinition $definition = null) public function __construct(array $parameters, InputDefinition $definition = null)
{
$this->parameters = $parameters;
parent::__construct($definition);
}
/**
* Returns the first argument from the raw parameters (not parsed).
*
* @return string The value of the first argument or null otherwise
*/
public function getFirstArgument()
{
foreach ($this->parameters as $key => $value)
{ {
if ($key && '-' === $key[0]) $this->parameters = $parameters;
{
continue;
}
return $value; parent::__construct($definition);
}
}
/**
* Returns true if the raw parameters (not parsed) contains a value.
*
* This method is to be used to introspect the input parameters
* before it has been validated. It must be used carefully.
*
* @param string|array $value The values to look for in the raw parameters (can be an array)
*
* @return Boolean true if the value is contained in the raw parameters
*/
public function hasParameterOption($values)
{
if (!is_array($values))
{
$values = array($values);
} }
foreach ($this->parameters as $k => $v) /**
* Returns the first argument from the raw parameters (not parsed).
*
* @return string The value of the first argument or null otherwise
*/
public function getFirstArgument()
{ {
if (!is_int($k)) foreach ($this->parameters as $key => $value) {
{ if ($key && '-' === $key[0]) {
$v = $k; continue;
} }
if (in_array($v, $values)) return $value;
{ }
return true;
}
} }
return false; /**
} * Returns true if the raw parameters (not parsed) contains a value.
*
/** * This method is to be used to introspect the input parameters
* Processes command line arguments. * before it has been validated. It must be used carefully.
*/ *
protected function parse() * @param string|array $value The values to look for in the raw parameters (can be an array)
{ *
foreach ($this->parameters as $key => $value) * @return Boolean true if the value is contained in the raw parameters
*/
public function hasParameterOption($values)
{ {
if ('--' === substr($key, 0, 2)) if (!is_array($values)) {
{ $values = array($values);
$this->addLongOption(substr($key, 2), $value); }
}
elseif ('-' === $key[0])
{
$this->addShortOption(substr($key, 1), $value);
}
else
{
$this->addArgument($key, $value);
}
}
}
/** foreach ($this->parameters as $k => $v) {
* Adds a short option value. if (!is_int($k)) {
* $v = $k;
* @param string $shortcut The short option key }
* @param mixed $value The value for the option
*/ if (in_array($v, $values)) {
protected function addShortOption($shortcut, $value) return true;
{ }
if (!$this->definition->hasShortcut($shortcut)) }
{
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); return false;
} }
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); /**
} * Processes command line arguments.
*/
/** protected function parse()
* Adds a long option value.
*
* @param string $name The long option key
* @param mixed $value The value for the option
*/
protected function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name))
{ {
throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); foreach ($this->parameters as $key => $value) {
if ('--' === substr($key, 0, 2)) {
$this->addLongOption(substr($key, 2), $value);
} elseif ('-' === $key[0]) {
$this->addShortOption(substr($key, 1), $value);
} else {
$this->addArgument($key, $value);
}
}
} }
$option = $this->definition->getOption($name); /**
* Adds a short option value.
if (null === $value) *
* @param string $shortcut The short option key
* @param mixed $value The value for the option
*
* @throws \RuntimeException When option given doesn't exist
*/
protected function addShortOption($shortcut, $value)
{ {
if ($option->isParameterRequired()) if (!$this->definition->hasShortcut($shortcut)) {
{ throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); }
}
$value = $option->isParameterOptional() ? $option->getDefault() : true; $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
} }
$this->options[$name] = $value; /**
} * Adds a long option value.
*
/** * @param string $name The long option key
* Adds an argument value. * @param mixed $value The value for the option
* *
* @param string $name The argument name * @throws \InvalidArgumentException When option given doesn't exist
* @param mixed $value The value for the argument * @throws \InvalidArgumentException When a required value is missing
*/ */
protected function addArgument($name, $value) protected function addLongOption($name, $value)
{
if (!$this->definition->hasArgument($name))
{ {
throw new \RuntimeException(sprintf('The "%s" argument does not exist.', $name)); if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
}
$option = $this->definition->getOption($name);
if (null === $value) {
if ($option->isParameterRequired()) {
throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name));
}
$value = $option->isParameterOptional() ? $option->getDefault() : true;
}
$this->options[$name] = $value;
} }
$this->arguments[$name] = $value; /**
} * Adds an argument value.
*
* @param string $name The argument name
* @param mixed $value The value for the argument
*
* @throws \InvalidArgumentException When argument given doesn't exist
*/
protected function addArgument($name, $value)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
$this->arguments[$name] = $value;
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Input; namespace Symfony\Component\Console\Input;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -20,179 +20,180 @@ namespace Symfony\Component\Console\Input;
* * `StringInput`: The input is provided as a string * * `StringInput`: The input is provided as a string
* * `ArrayInput`: The input is provided as an array * * `ArrayInput`: The input is provided as an array
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
abstract class Input implements InputInterface abstract class Input implements InputInterface
{ {
protected $definition; protected $definition;
protected $options; protected $options;
protected $arguments; protected $arguments;
protected $interactive = true; protected $interactive = true;
/** /**
* Constructor. * Constructor.
* *
* @param InputDefinition $definition A InputDefinition instance * @param InputDefinition $definition A InputDefinition instance
*/ */
public function __construct(InputDefinition $definition = null) public function __construct(InputDefinition $definition = null)
{
if (null === $definition)
{ {
$this->definition = new InputDefinition(); if (null === $definition) {
} $this->definition = new InputDefinition();
else } else {
{ $this->bind($definition);
$this->bind($definition); $this->validate();
$this->validate(); }
}
}
/**
* Binds the current Input instance with the given arguments and options.
*
* @param InputDefinition $definition A InputDefinition instance
*/
public function bind(InputDefinition $definition)
{
$this->arguments = array();
$this->options = array();
$this->definition = $definition;
$this->parse();
}
/**
* Processes command line arguments.
*/
abstract protected function parse();
public function validate()
{
if (count($this->arguments) < $this->definition->getArgumentRequiredCount())
{
throw new \RuntimeException('Not enough arguments.');
}
}
public function isInteractive()
{
return $this->interactive;
}
public function setInteractive($interactive)
{
$this->interactive = (Boolean) $interactive;
}
/**
* Returns the argument values.
*
* @return array An array of argument values
*/
public function getArguments()
{
return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
}
/**
* Returns the argument value for a given argument name.
*
* @param string $name The argument name
*
* @return mixed The argument value
*/
public function getArgument($name)
{
if (!$this->definition->hasArgument($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(); /**
} * Binds the current Input instance with the given arguments and options.
*
/** * @param InputDefinition $definition A InputDefinition instance
* Sets an argument value by name. */
* public function bind(InputDefinition $definition)
* @param string $name The argument name
* @param string $value The argument value
*/
public function setArgument($name, $value)
{
if (!$this->definition->hasArgument($name))
{ {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); $this->arguments = array();
$this->options = array();
$this->definition = $definition;
$this->parse();
} }
$this->arguments[$name] = $value; /**
} * Processes command line arguments.
*/
abstract protected function parse();
/** /**
* Returns true if an InputArgument object exists by name or position. * @throws \RuntimeException When not enough arguments are given
* */
* @param string|integer $name The InputArgument name or position public function validate()
*
* @return Boolean true if the InputArgument object exists, false otherwise
*/
public function hasArgument($name)
{
return $this->definition->hasArgument($name);
}
/**
* Returns the options values.
*
* @return array An array of option values
*/
public function getOptions()
{
return array_merge($this->definition->getOptionDefaults(), $this->options);
}
/**
* Returns the option value for a given option name.
*
* @param string $name The option name
*
* @return mixed The option value
*/
public function getOption($name)
{
if (!$this->definition->hasOption($name))
{ {
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
throw new \RuntimeException('Not enough arguments.');
}
} }
return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); public function isInteractive()
}
/**
* Sets an option value by name.
*
* @param string $name The option name
* @param string $value The option value
*/
public function setOption($name, $value)
{
if (!$this->definition->hasOption($name))
{ {
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); return $this->interactive;
} }
$this->options[$name] = $value; public function setInteractive($interactive)
} {
$this->interactive = (Boolean) $interactive;
}
/** /**
* Returns true if an InputOption object exists by name. * Returns the argument values.
* *
* @param string $name The InputOption name * @return array An array of argument values
* */
* @return Boolean true if the InputOption object exists, false otherwise public function getArguments()
*/ {
public function hasOption($name) return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
{ }
return $this->definition->hasOption($name);
} /**
* Returns the argument value for a given argument name.
*
* @param string $name The argument name
*
* @return mixed The argument value
*
* @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));
}
return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
}
/**
* Sets an argument value by name.
*
* @param string $name The argument name
* @param string $value The argument value
*
* @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));
}
$this->arguments[$name] = $value;
}
/**
* Returns true if an InputArgument object exists by name or position.
*
* @param string|integer $name The InputArgument name or position
*
* @return Boolean true if the InputArgument object exists, false otherwise
*/
public function hasArgument($name)
{
return $this->definition->hasArgument($name);
}
/**
* Returns the options values.
*
* @return array An array of option values
*/
public function getOptions()
{
return array_merge($this->definition->getOptionDefaults(), $this->options);
}
/**
* Returns the option value for a given option name.
*
* @param string $name The option name
*
* @return mixed The option value
*
* @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));
}
return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
}
/**
* Sets an option value by name.
*
* @param string $name The option name
* @param string $value The option value
*
* @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));
}
$this->options[$name] = $value;
}
/**
* Returns true if an InputOption object exists by name.
*
* @param string $name The InputOption name
*
* @return Boolean true if the InputOption object exists, false otherwise
*/
public function hasOption($name)
{
return $this->definition->hasOption($name);
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Input; namespace Symfony\Component\Console\Input;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -14,121 +14,115 @@ namespace Symfony\Component\Console\Input;
/** /**
* Represents a command line argument. * Represents a command line argument.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class InputArgument class InputArgument
{ {
const REQUIRED = 1; const REQUIRED = 1;
const OPTIONAL = 2; const OPTIONAL = 2;
const IS_ARRAY = 4; const IS_ARRAY = 4;
protected $name; protected $name;
protected $mode; protected $mode;
protected $default; protected $default;
protected $description; protected $description;
/** /**
* Constructor. * Constructor.
* *
* @param string $name The argument name * @param string $name The argument name
* @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL
* @param string $description A description text * @param string $description A description text
* @param mixed $default The default value (for self::OPTIONAL mode only) * @param mixed $default The default value (for self::OPTIONAL mode only)
*/ *
public function __construct($name, $mode = null, $description = '', $default = null) * @throws \InvalidArgumentException When argument mode is not valid
{ */
if (null === $mode) public function __construct($name, $mode = null, $description = '', $default = null)
{ {
$mode = self::OPTIONAL; if (null === $mode) {
} $mode = self::OPTIONAL;
else if (is_string($mode) || $mode > 7) } else if (is_string($mode) || $mode > 7) {
{ 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;
$this->mode = $mode;
$this->description = $description;
$this->setDefault($default);
} }
$this->name = $name; /**
$this->mode = $mode; * Returns the argument name.
$this->description = $description; *
* @return string The argument name
$this->setDefault($default); */
} public function getName()
/**
* Returns the argument name.
*
* @return string The argument name
*/
public function getName()
{
return $this->name;
}
/**
* Returns true if the argument is required.
*
* @return Boolean true if parameter mode is self::REQUIRED, false otherwise
*/
public function isRequired()
{
return self::REQUIRED === (self::REQUIRED & $this->mode);
}
/**
* Returns true if the argument can take multiple values.
*
* @return Boolean true if mode is self::IS_ARRAY, false otherwise
*/
public function isArray()
{
return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
}
/**
* Sets the default value.
*
* @param mixed $default The default value
*/
public function setDefault($default = null)
{
if (self::REQUIRED === $this->mode && null !== $default)
{ {
throw new \LogicException('Cannot set a default value except for Parameter::OPTIONAL mode.'); return $this->name;
} }
if ($this->isArray()) /**
* Returns true if the argument is required.
*
* @return Boolean true if parameter mode is self::REQUIRED, false otherwise
*/
public function isRequired()
{ {
if (null === $default) return self::REQUIRED === (self::REQUIRED & $this->mode);
{
$default = array();
}
else if (!is_array($default))
{
throw new \LogicException('A default value for an array argument must be an array.');
}
} }
$this->default = $default; /**
} * Returns true if the argument can take multiple values.
*
* @return Boolean true if mode is self::IS_ARRAY, false otherwise
*/
public function isArray()
{
return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
}
/** /**
* Returns the default value. * Sets the default value.
* *
* @return mixed The default value * @param mixed $default The default value
*/ *
public function getDefault() * @throws \LogicException When incorrect default value is given
{ */
return $this->default; public function setDefault($default = null)
} {
if (self::REQUIRED === $this->mode && null !== $default) {
throw new \LogicException('Cannot set a default value except for Parameter::OPTIONAL mode.');
}
/** if ($this->isArray()) {
* Returns the description text. if (null === $default) {
* $default = array();
* @return string The description text } else if (!is_array($default)) {
*/ throw new \LogicException('A default value for an array argument must be an array.');
public function getDescription() }
{ }
return $this->description;
} $this->default = $default;
}
/**
* Returns the default value.
*
* @return mixed The default value
*/
public function getDefault()
{
return $this->default;
}
/**
* Returns the description text.
*
* @return string The description text
*/
public function getDescription()
{
return $this->description;
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Input; namespace Symfony\Component\Console\Input;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -21,487 +21,451 @@ namespace Symfony\Component\Console\Input;
* new InputOption('foo', 'f', InputOption::PARAMETER_REQUIRED), * new InputOption('foo', 'f', InputOption::PARAMETER_REQUIRED),
* )); * ));
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class InputDefinition class InputDefinition
{ {
protected $arguments; protected $arguments;
protected $requiredCount; protected $requiredCount;
protected $hasAnArrayArgument = false; protected $hasAnArrayArgument = false;
protected $hasOptional; protected $hasOptional;
protected $options; protected $options;
protected $shortcuts; protected $shortcuts;
/** /**
* Constructor. * Constructor.
* *
* @param array $definition An array of InputArgument and InputOption instance * @param array $definition An array of InputArgument and InputOption instance
*/ */
public function __construct(array $definition = array()) public function __construct(array $definition = array())
{
$this->setDefinition($definition);
}
public function setDefinition(array $definition)
{
$arguments = array();
$options = array();
foreach ($definition as $item)
{ {
if ($item instanceof InputOption) $this->setDefinition($definition);
{
$options[] = $item;
}
else
{
$arguments[] = $item;
}
} }
$this->setArguments($arguments); public function setDefinition(array $definition)
$this->setOptions($options);
}
/**
* Sets the InputArgument objects.
*
* @param array $arguments An array of InputArgument objects
*/
public function setArguments($arguments = array())
{
$this->arguments = array();
$this->requiredCount = 0;
$this->hasOptional = false;
$this->addArguments($arguments);
}
/**
* Add an array of InputArgument objects.
*
* @param array $arguments An array of InputArgument objects
*/
public function addArguments($arguments = array())
{
if (null !== $arguments)
{ {
foreach ($arguments as $argument) $arguments = array();
{ $options = array();
$this->addArgument($argument); foreach ($definition as $item) {
} if ($item instanceof InputOption) {
} $options[] = $item;
} } else {
$arguments[] = $item;
/** }
* Add an InputArgument object.
*
* @param InputArgument $argument An InputArgument object
*/
public function addArgument(InputArgument $argument)
{
if (isset($this->arguments[$argument->getName()]))
{
throw new \LogicException(sprintf('An argument with name "%s" already exist.', $argument->getName()));
}
if ($this->hasAnArrayArgument)
{
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.');
}
if ($argument->isArray())
{
$this->hasAnArrayArgument = true;
}
if ($argument->isRequired())
{
++$this->requiredCount;
}
else
{
$this->hasOptional = true;
}
$this->arguments[$argument->getName()] = $argument;
}
/**
* Returns an InputArgument by name or by position.
*
* @param string|integer $name The InputArgument name or position
*
* @return InputArgument An InputArgument object
*/
public function getArgument($name)
{
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
if (!$this->hasArgument($name))
{
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
return $arguments[$name];
}
/**
* Returns true if an InputArgument object exists by name or position.
*
* @param string|integer $name The InputArgument name or position
*
* @return Boolean true if the InputArgument object exists, false otherwise
*/
public function hasArgument($name)
{
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
return isset($arguments[$name]);
}
/**
* Gets the array of InputArgument objects.
*
* @return array An array of InputArgument objects
*/
public function getArguments()
{
return $this->arguments;
}
/**
* Returns the number of InputArguments.
*
* @return integer The number of InputArguments
*/
public function getArgumentCount()
{
return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
}
/**
* Returns the number of required InputArguments.
*
* @return integer The number of required InputArguments
*/
public function getArgumentRequiredCount()
{
return $this->requiredCount;
}
/**
* Gets the default values.
*
* @return array An array of default values
*/
public function getArgumentDefaults()
{
$values = array();
foreach ($this->arguments as $argument)
{
$values[$argument->getName()] = $argument->getDefault();
}
return $values;
}
/**
* Sets the InputOption objects.
*
* @param array $options An array of InputOption objects
*/
public function setOptions($options = array())
{
$this->options = array();
$this->shortcuts = array();
$this->addOptions($options);
}
/**
* Add an array of InputOption objects.
*
* @param array $options An array of InputOption objects
*/
public function addOptions($options = array())
{
foreach ($options as $option)
{
$this->addOption($option);
}
}
/**
* Add an InputOption object.
*
* @param InputOption $option An InputOption object
*/
public function addOption(InputOption $option)
{
if (isset($this->options[$option->getName()]))
{
throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName()));
}
else if (isset($this->shortcuts[$option->getShortcut()]))
{
throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut()));
}
$this->options[$option->getName()] = $option;
if ($option->getShortcut())
{
$this->shortcuts[$option->getShortcut()] = $option->getName();
}
}
/**
* Returns an InputOption by name.
*
* @param string $name The InputOption name
*
* @return InputOption A InputOption object
*/
public function getOption($name)
{
if (!$this->hasOption($name))
{
throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
}
return $this->options[$name];
}
/**
* Returns true if an InputOption object exists by name.
*
* @param string $name The InputOption name
*
* @return Boolean true if the InputOption object exists, false otherwise
*/
public function hasOption($name)
{
return isset($this->options[$name]);
}
/**
* Gets the array of InputOption objects.
*
* @return array An array of InputOption objects
*/
public function getOptions()
{
return $this->options;
}
/**
* Returns true if an InputOption object exists by shortcut.
*
* @param string $name The InputOption shortcut
*
* @return Boolean true if the InputOption object exists, false otherwise
*/
public function hasShortcut($name)
{
return isset($this->shortcuts[$name]);
}
/**
* Gets an InputOption by shortcut.
*
* @return InputOption An InputOption object
*/
public function getOptionForShortcut($shortcut)
{
return $this->getOption($this->shortcutToName($shortcut));
}
/**
* Gets an array of default values.
*
* @return array An array of all default values
*/
public function getOptionDefaults()
{
$values = array();
foreach ($this->options as $option)
{
$values[$option->getName()] = $option->getDefault();
}
return $values;
}
/**
* Returns the InputOption name given a shortcut.
*
* @param string $shortcut The shortcut
*
* @return string The InputOption name
*/
protected function shortcutToName($shortcut)
{
if (!isset($this->shortcuts[$shortcut]))
{
throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
}
return $this->shortcuts[$shortcut];
}
/**
* Gets the synopsis.
*
* @return string The synopsis
*/
public function getSynopsis()
{
$elements = array();
foreach ($this->getOptions() as $option)
{
$shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
$elements[] = sprintf('['.($option->isParameterRequired() ? '%s--%s="..."' : ($option->isParameterOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
}
foreach ($this->getArguments() as $argument)
{
$elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
if ($argument->isArray())
{
$elements[] = sprintf('... [%sN]', $argument->getName());
}
}
return implode(' ', $elements);
}
/**
* Returns a textual representation of the InputDefinition.
*
* @return string A string representing the InputDefinition
*/
public function asText()
{
// find the largest option or argument name
$max = 0;
foreach ($this->getOptions() as $option)
{
$max = strlen($option->getName()) + 2 > $max ? strlen($option->getName()) + 2 : $max;
}
foreach ($this->getArguments() as $argument)
{
$max = strlen($argument->getName()) > $max ? strlen($argument->getName()) : $max;
}
++$max;
$text = array();
if ($this->getArguments())
{
$text[] = '<comment>Arguments:</comment>';
foreach ($this->getArguments() as $argument)
{
if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault())))
{
$default = sprintf('<comment> (default: %s)</comment>', is_array($argument->getDefault()) ? str_replace("\n", '', var_export($argument->getDefault(), true)): $argument->getDefault());
}
else
{
$default = '';
} }
$text[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $argument->getDescription(), $default); $this->setArguments($arguments);
} $this->setOptions($options);
$text[] = '';
} }
if ($this->getOptions()) /**
* Sets the InputArgument objects.
*
* @param array $arguments An array of InputArgument objects
*/
public function setArguments($arguments = array())
{ {
$text[] = '<comment>Options:</comment>'; $this->arguments = array();
$this->requiredCount = 0;
$this->hasOptional = false;
$this->hasAnArrayArgument = false;
$this->addArguments($arguments);
}
foreach ($this->getOptions() as $option) /**
{ * Add an array of InputArgument objects.
if ($option->acceptParameter() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) *
{ * @param InputArgument[] $arguments An array of InputArgument objects
$default = sprintf('<comment> (default: %s)</comment>', is_array($option->getDefault()) ? str_replace("\n", '', print_r($option->getDefault(), true)): $option->getDefault()); */
public function addArguments($arguments = array())
{
if (null !== $arguments) {
foreach ($arguments as $argument) {
$this->addArgument($argument);
}
} }
else }
{
$default = ''; /**
* Add an InputArgument object.
*
* @param InputArgument $argument An InputArgument object
*
* @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 exist.', $argument->getName()));
} }
$multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''; if ($this->hasAnArrayArgument) {
$text[] = sprintf(' %-'.$max.'s %s%s%s%s', '<info>--'.$option->getName().'</info>', $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', $option->getDescription(), $default, $multiple); throw new \LogicException('Cannot add an argument after an array argument.');
}
$text[] = '';
}
return implode("\n", $text);
}
/**
* Returns an XML representation of the InputDefinition.
*
* @param Boolean $asDom Whether to return a DOM or an XML string
*
* @return string|DOMDocument An XML string representing the InputDefinition
*/
public function asXml($asDom = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($definitionXML = $dom->createElement('definition'));
$definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
foreach ($this->getArguments() as $argument)
{
$argumentsXML->appendChild($argumentXML = $dom->createElement('argument'));
$argumentXML->setAttribute('name', $argument->getName());
$argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
$argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
$argumentXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
$argumentXML->appendChild($defaultsXML = $dom->createElement('defaults'));
$defaults = is_array($argument->getDefault()) ? $argument->getDefault() : ($argument->getDefault() ? array($argument->getDefault()) : array());
foreach ($defaults as $default)
{
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
$defaultXML->appendChild($dom->createTextNode($default));
}
}
$definitionXML->appendChild($optionsXML = $dom->createElement('options'));
foreach ($this->getOptions() as $option)
{
$optionsXML->appendChild($optionXML = $dom->createElement('option'));
$optionXML->setAttribute('name', '--'.$option->getName());
$optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
$optionXML->setAttribute('accept_parameter', $option->acceptParameter() ? 1 : 0);
$optionXML->setAttribute('is_parameter_required', $option->isParameterRequired() ? 1 : 0);
$optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
$optionXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
if ($option->acceptParameter())
{
$optionXML->appendChild($defaultsXML = $dom->createElement('defaults'));
$defaults = is_array($option->getDefault()) ? $option->getDefault() : ($option->getDefault() ? array($option->getDefault()) : array());
foreach ($defaults as $default)
{
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
$defaultXML->appendChild($dom->createTextNode($default));
} }
}
if ($argument->isRequired() && $this->hasOptional) {
throw new \LogicException('Cannot add a required argument after an optional one.');
}
if ($argument->isArray()) {
$this->hasAnArrayArgument = true;
}
if ($argument->isRequired()) {
++$this->requiredCount;
} else {
$this->hasOptional = true;
}
$this->arguments[$argument->getName()] = $argument;
} }
return $asDom ? $dom : $dom->saveXml(); /**
} * Returns an InputArgument by name or by position.
*
* @param string|integer $name The InputArgument name or position
*
* @return InputArgument An InputArgument object
*
* @throws \InvalidArgumentException When argument given doesn't exist
*/
public function getArgument($name)
{
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
if (!$this->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
return $arguments[$name];
}
/**
* Returns true if an InputArgument object exists by name or position.
*
* @param string|integer $name The InputArgument name or position
*
* @return Boolean true if the InputArgument object exists, false otherwise
*/
public function hasArgument($name)
{
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
return isset($arguments[$name]);
}
/**
* Gets the array of InputArgument objects.
*
* @return array An array of InputArgument objects
*/
public function getArguments()
{
return $this->arguments;
}
/**
* Returns the number of InputArguments.
*
* @return integer The number of InputArguments
*/
public function getArgumentCount()
{
return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
}
/**
* Returns the number of required InputArguments.
*
* @return integer The number of required InputArguments
*/
public function getArgumentRequiredCount()
{
return $this->requiredCount;
}
/**
* Gets the default values.
*
* @return array An array of default values
*/
public function getArgumentDefaults()
{
$values = array();
foreach ($this->arguments as $argument) {
$values[$argument->getName()] = $argument->getDefault();
}
return $values;
}
/**
* Sets the InputOption objects.
*
* @param array $options An array of InputOption objects
*/
public function setOptions($options = array())
{
$this->options = array();
$this->shortcuts = array();
$this->addOptions($options);
}
/**
* Add an array of InputOption objects.
*
* @param InputOption[] $options An array of InputOption objects
*/
public function addOptions($options = array())
{
foreach ($options as $option) {
$this->addOption($option);
}
}
/**
* Add an InputOption object.
*
* @param InputOption $option An InputOption object
*
* @throws \LogicException When option given already exist
*/
public function addOption(InputOption $option)
{
if (isset($this->options[$option->getName()])) {
throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName()));
} else if (isset($this->shortcuts[$option->getShortcut()])) {
throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut()));
}
$this->options[$option->getName()] = $option;
if ($option->getShortcut()) {
$this->shortcuts[$option->getShortcut()] = $option->getName();
}
}
/**
* Returns an InputOption by name.
*
* @param string $name The InputOption name
*
* @return InputOption A InputOption object
*/
public function getOption($name)
{
if (!$this->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
}
return $this->options[$name];
}
/**
* Returns true if an InputOption object exists by name.
*
* @param string $name The InputOption name
*
* @return Boolean true if the InputOption object exists, false otherwise
*/
public function hasOption($name)
{
return isset($this->options[$name]);
}
/**
* Gets the array of InputOption objects.
*
* @return array An array of InputOption objects
*/
public function getOptions()
{
return $this->options;
}
/**
* Returns true if an InputOption object exists by shortcut.
*
* @param string $name The InputOption shortcut
*
* @return Boolean true if the InputOption object exists, false otherwise
*/
public function hasShortcut($name)
{
return isset($this->shortcuts[$name]);
}
/**
* Gets an InputOption by shortcut.
*
* @return InputOption An InputOption object
*/
public function getOptionForShortcut($shortcut)
{
return $this->getOption($this->shortcutToName($shortcut));
}
/**
* Gets an array of default values.
*
* @return array An array of all default values
*/
public function getOptionDefaults()
{
$values = array();
foreach ($this->options as $option) {
$values[$option->getName()] = $option->getDefault();
}
return $values;
}
/**
* Returns the InputOption name given a shortcut.
*
* @param string $shortcut The shortcut
*
* @return string The InputOption name
*
* @throws \InvalidArgumentException When option given does not exist
*/
protected function shortcutToName($shortcut)
{
if (!isset($this->shortcuts[$shortcut])) {
throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
}
return $this->shortcuts[$shortcut];
}
/**
* Gets the synopsis.
*
* @return string The synopsis
*/
public function getSynopsis()
{
$elements = array();
foreach ($this->getOptions() as $option) {
$shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
$elements[] = sprintf('['.($option->isParameterRequired() ? '%s--%s="..."' : ($option->isParameterOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
}
foreach ($this->getArguments() as $argument) {
$elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
if ($argument->isArray()) {
$elements[] = sprintf('... [%sN]', $argument->getName());
}
}
return implode(' ', $elements);
}
/**
* Returns a textual representation of the InputDefinition.
*
* @return string A string representing the InputDefinition
*/
public function asText()
{
// find the largest option or argument name
$max = 0;
foreach ($this->getOptions() as $option) {
$max = strlen($option->getName()) + 2 > $max ? strlen($option->getName()) + 2 : $max;
}
foreach ($this->getArguments() as $argument) {
$max = strlen($argument->getName()) > $max ? strlen($argument->getName()) : $max;
}
++$max;
$text = array();
if ($this->getArguments()) {
$text[] = '<comment>Arguments:</comment>';
foreach ($this->getArguments() as $argument) {
if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
$default = sprintf('<comment> (default: %s)</comment>', is_array($argument->getDefault()) ? str_replace("\n", '', var_export($argument->getDefault(), true)): $argument->getDefault());
} else {
$default = '';
}
$text[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $argument->getDescription(), $default);
}
$text[] = '';
}
if ($this->getOptions()) {
$text[] = '<comment>Options:</comment>';
foreach ($this->getOptions() as $option) {
if ($option->acceptParameter() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
$default = sprintf('<comment> (default: %s)</comment>', is_array($option->getDefault()) ? str_replace("\n", '', print_r($option->getDefault(), true)): $option->getDefault());
} else {
$default = '';
}
$multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '';
$text[] = sprintf(' %-'.$max.'s %s%s%s%s', '<info>--'.$option->getName().'</info>', $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', $option->getDescription(), $default, $multiple);
}
$text[] = '';
}
return implode("\n", $text);
}
/**
* Returns an XML representation of the InputDefinition.
*
* @param Boolean $asDom Whether to return a DOM or an XML string
*
* @return string|DOMDocument An XML string representing the InputDefinition
*/
public function asXml($asDom = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($definitionXML = $dom->createElement('definition'));
$definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
foreach ($this->getArguments() as $argument) {
$argumentsXML->appendChild($argumentXML = $dom->createElement('argument'));
$argumentXML->setAttribute('name', $argument->getName());
$argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
$argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
$argumentXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
$argumentXML->appendChild($defaultsXML = $dom->createElement('defaults'));
$defaults = is_array($argument->getDefault()) ? $argument->getDefault() : ($argument->getDefault() ? array($argument->getDefault()) : array());
foreach ($defaults as $default) {
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
$defaultXML->appendChild($dom->createTextNode($default));
}
}
$definitionXML->appendChild($optionsXML = $dom->createElement('options'));
foreach ($this->getOptions() as $option) {
$optionsXML->appendChild($optionXML = $dom->createElement('option'));
$optionXML->setAttribute('name', '--'.$option->getName());
$optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
$optionXML->setAttribute('accept_parameter', $option->acceptParameter() ? 1 : 0);
$optionXML->setAttribute('is_parameter_required', $option->isParameterRequired() ? 1 : 0);
$optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
$optionXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
if ($option->acceptParameter()) {
$optionXML->appendChild($defaultsXML = $dom->createElement('defaults'));
$defaults = is_array($option->getDefault()) ? $option->getDefault() : ($option->getDefault() ? array($option->getDefault()) : array());
foreach ($defaults as $default) {
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
$defaultXML->appendChild($dom->createTextNode($default));
}
}
}
return $asDom ? $dom : $dom->saveXml();
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Input; namespace Symfony\Component\Console\Input;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -14,45 +14,43 @@ namespace Symfony\Component\Console\Input;
/** /**
* InputInterface is the interface implemented by all input classes. * InputInterface is the interface implemented by all input classes.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
interface InputInterface interface InputInterface
{ {
/** /**
* Returns the first argument from the raw parameters (not parsed). * Returns the first argument from the raw parameters (not parsed).
* *
* @return string The value of the first argument or null otherwise * @return string The value of the first argument or null otherwise
*/ */
function getFirstArgument(); function getFirstArgument();
/** /**
* Returns true if the raw parameters (not parsed) contains a value. * Returns true if the raw parameters (not parsed) contains a value.
* *
* This method is to be used to introspect the input parameters * This method is to be used to introspect the input parameters
* before it has been validated. It must be used carefully. * before it has been validated. It must be used carefully.
* *
* @param string $value The value to look for in the raw parameters * @param string $value The value to look for in the raw parameters
* *
* @return Boolean true if the value is contained in the raw parameters * @return Boolean true if the value is contained in the raw parameters
*/ */
function hasParameterOption($value); function hasParameterOption($value);
/** /**
* Binds the current Input instance with the given arguments and options. * Binds the current Input instance with the given arguments and options.
* *
* @param InputDefinition $definition A InputDefinition instance * @param InputDefinition $definition A InputDefinition instance
*/ */
function bind(InputDefinition $definition); function bind(InputDefinition $definition);
function validate(); function validate();
function getArguments(); function getArguments();
function getArgument($name); function getArgument($name);
function getOptions(); function getOptions();
function getOption($name); function getOption($name);
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Input; namespace Symfony\Component\Console\Input;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -14,178 +14,165 @@ namespace Symfony\Component\Console\Input;
/** /**
* Represents a command line option. * Represents a command line option.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class InputOption class InputOption
{ {
const PARAMETER_NONE = 1; const PARAMETER_NONE = 1;
const PARAMETER_REQUIRED = 2; const PARAMETER_REQUIRED = 2;
const PARAMETER_OPTIONAL = 4; const PARAMETER_OPTIONAL = 4;
const PARAMETER_IS_ARRAY = 8; const PARAMETER_IS_ARRAY = 8;
protected $name; protected $name;
protected $shortcut; protected $shortcut;
protected $mode; protected $mode;
protected $default; protected $default;
protected $description; protected $description;
/** /**
* Constructor. * Constructor.
* *
* @param string $name The option name * @param string $name The option name
* @param string $shortcut The shortcut (can be null) * @param string $shortcut The shortcut (can be null)
* @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL * @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL
* @param string $description A description text * @param string $description A description text
* @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE) * @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE)
*/ *
public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) * @throws \InvalidArgumentException If option mode is invalid or incompatible
{ */
if ('--' === substr($name, 0, 2)) public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
{ {
$name = substr($name, 2); if ('--' === substr($name, 0, 2)) {
$name = substr($name, 2);
}
if (empty($shortcut)) {
$shortcut = null;
}
if (null !== $shortcut) {
if ('-' === $shortcut[0]) {
$shortcut = substr($shortcut, 1);
}
}
if (null === $mode) {
$mode = self::PARAMETER_NONE;
} else if (!is_int($mode) || $mode > 15) {
throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
}
$this->name = $name;
$this->shortcut = $shortcut;
$this->mode = $mode;
$this->description = $description;
if ($this->isArray() && !$this->acceptParameter()) {
throw new \InvalidArgumentException('Impossible to have an option mode PARAMETER_IS_ARRAY if the option does not accept a parameter.');
}
$this->setDefault($default);
} }
if (empty($shortcut)) /**
* Returns the shortcut.
*
* @return string The shortcut
*/
public function getShortcut()
{ {
$shortcut = null; return $this->shortcut;
} }
if (null !== $shortcut) /**
* Returns the name.
*
* @return string The name
*/
public function getName()
{ {
if ('-' === $shortcut[0]) return $this->name;
{
$shortcut = substr($shortcut, 1);
}
} }
if (null === $mode) /**
* Returns true if the option accept a parameter.
*
* @return Boolean true if parameter mode is not self::PARAMETER_NONE, false otherwise
*/
public function acceptParameter()
{ {
$mode = self::PARAMETER_NONE; return $this->isParameterRequired() || $this->isParameterOptional();
}
else if (!is_int($mode) || $mode > 15)
{
throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
} }
$this->name = $name; /**
$this->shortcut = $shortcut; * Returns true if the option requires a parameter.
$this->mode = $mode; *
$this->description = $description; * @return Boolean true if parameter mode is self::PARAMETER_REQUIRED, false otherwise
*/
if ($this->isArray() && !$this->acceptParameter()) public function isParameterRequired()
{ {
throw new \InvalidArgumentException('Impossible to have an option mode PARAMETER_IS_ARRAY if the option does not accept a parameter.'); return self::PARAMETER_REQUIRED === (self::PARAMETER_REQUIRED & $this->mode);
} }
$this->setDefault($default); /**
} * Returns true if the option takes an optional parameter.
*
/** * @return Boolean true if parameter mode is self::PARAMETER_OPTIONAL, false otherwise
* Returns the shortcut. */
* public function isParameterOptional()
* @return string The shortcut
*/
public function getShortcut()
{
return $this->shortcut;
}
/**
* Returns the name.
*
* @return string The name
*/
public function getName()
{
return $this->name;
}
/**
* Returns true if the option accept a parameter.
*
* @return Boolean true if parameter mode is not self::PARAMETER_NONE, false otherwise
*/
public function acceptParameter()
{
return $this->isParameterRequired() || $this->isParameterOptional();
}
/**
* Returns true if the option requires a parameter.
*
* @return Boolean true if parameter mode is self::PARAMETER_REQUIRED, false otherwise
*/
public function isParameterRequired()
{
return self::PARAMETER_REQUIRED === (self::PARAMETER_REQUIRED & $this->mode);
}
/**
* Returns true if the option takes an optional parameter.
*
* @return Boolean true if parameter mode is self::PARAMETER_OPTIONAL, false otherwise
*/
public function isParameterOptional()
{
return self::PARAMETER_OPTIONAL === (self::PARAMETER_OPTIONAL & $this->mode);
}
/**
* Returns true if the option can take multiple values.
*
* @return Boolean true if mode is self::PARAMETER_IS_ARRAY, false otherwise
*/
public function isArray()
{
return self::PARAMETER_IS_ARRAY === (self::PARAMETER_IS_ARRAY & $this->mode);
}
/**
* Sets the default value.
*
* @param mixed $default The default value
*/
public function setDefault($default = null)
{
if (self::PARAMETER_NONE === (self::PARAMETER_NONE & $this->mode) && null !== $default)
{ {
throw new \LogicException('Cannot set a default value when using Option::PARAMETER_NONE mode.'); return self::PARAMETER_OPTIONAL === (self::PARAMETER_OPTIONAL & $this->mode);
} }
if ($this->isArray()) /**
* Returns true if the option can take multiple values.
*
* @return Boolean true if mode is self::PARAMETER_IS_ARRAY, false otherwise
*/
public function isArray()
{ {
if (null === $default) return self::PARAMETER_IS_ARRAY === (self::PARAMETER_IS_ARRAY & $this->mode);
{
$default = array();
}
elseif (!is_array($default))
{
throw new \LogicException('A default value for an array option must be an array.');
}
} }
$this->default = $this->acceptParameter() ? $default : false; /**
} * Sets the default value.
*
* @param mixed $default The default value
*/
public function setDefault($default = null)
{
if (self::PARAMETER_NONE === (self::PARAMETER_NONE & $this->mode) && null !== $default) {
throw new \LogicException('Cannot set a default value when using Option::PARAMETER_NONE mode.');
}
/** if ($this->isArray()) {
* Returns the default value. if (null === $default) {
* $default = array();
* @return mixed The default value } elseif (!is_array($default)) {
*/ throw new \LogicException('A default value for an array option must be an array.');
public function getDefault() }
{ }
return $this->default;
}
/** $this->default = $this->acceptParameter() ? $default : false;
* Returns the description text. }
*
* @return string The description text /**
*/ * Returns the default value.
public function getDescription() *
{ * @return mixed The default value
return $this->description; */
} public function getDefault()
{
return $this->default;
}
/**
* Returns the description text.
*
* @return string The description text
*/
public function getDescription()
{
return $this->description;
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Input; namespace Symfony\Component\Console\Input;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -18,63 +18,54 @@ namespace Symfony\Component\Console\Input;
* *
* $input = new StringInput('foo --bar="foobar"'); * $input = new StringInput('foo --bar="foobar"');
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class StringInput extends ArgvInput class StringInput extends ArgvInput
{ {
const REGEX_STRING = '([^ ]+?)(?: |(?<!\\\\)"|(?<!\\\\)\'|$)'; const REGEX_STRING = '([^ ]+?)(?: |(?<!\\\\)"|(?<!\\\\)\'|$)';
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')'; const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
/** /**
* Constructor. * Constructor.
* *
* @param string $input An array of parameters from the CLI (in the argv format) * @param string $input An array of parameters from the CLI (in the argv format)
* @param InputDefinition $definition A InputDefinition instance * @param InputDefinition $definition A InputDefinition instance
*/ */
public function __construct($input, InputDefinition $definition = null) public function __construct($input, InputDefinition $definition = null)
{
parent::__construct(array(), $definition);
$this->tokens = $this->tokenize($input);
}
protected function tokenize($input)
{
$input = preg_replace('/(\r\n|\r|\n|\t)/', ' ', $input);
$tokens = array();
$length = strlen($input);
$cursor = 0;
while ($cursor < $length)
{ {
if (preg_match('/\s+/A', $input, $match, null, $cursor)) parent::__construct(array(), $definition);
{
}
elseif (preg_match('/([^="\' ]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor))
{
$tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
}
elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor))
{
$tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
}
elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor))
{
$tokens[] = stripcslashes($match[1]);
}
else
{
// should never happen
// @codeCoverageIgnoreStart
throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
// @codeCoverageIgnoreEnd
}
$cursor += strlen($match[0]); $this->tokens = $this->tokenize($input);
} }
return $tokens; /**
} * @throws \InvalidArgumentException When unable to parse input (should never happen)
*/
protected function tokenize($input)
{
$input = preg_replace('/(\r\n|\r|\n|\t)/', ' ', $input);
$tokens = array();
$length = strlen($input);
$cursor = 0;
while ($cursor < $length) {
if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
} elseif (preg_match('/([^="\' ]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
$tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
} elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
$tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
} elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
$tokens[] = stripcslashes($match[1]);
} else {
// should never happen
// @codeCoverageIgnoreStart
throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
// @codeCoverageIgnoreEnd
}
$cursor += strlen($match[0]);
}
return $tokens;
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Output; namespace Symfony\Component\Console\Output;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -22,20 +22,18 @@ namespace Symfony\Component\Console\Output;
* *
* $output = new StreamOutput(fopen('php://stdout', 'w')); * $output = new StreamOutput(fopen('php://stdout', 'w'));
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class ConsoleOutput extends StreamOutput class ConsoleOutput extends StreamOutput
{ {
/** /**
* Constructor. * Constructor.
* *
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
*/ */
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null) public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null)
{ {
parent::__construct(fopen('php://stdout', 'w'), $verbosity, $decorated); parent::__construct(fopen('php://stdout', 'w'), $verbosity, $decorated);
} }
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Output; namespace Symfony\Component\Console\Output;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -16,19 +16,17 @@ namespace Symfony\Component\Console\Output;
* *
* $output = new NullOutput(); * $output = new NullOutput();
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class NullOutput extends Output class NullOutput extends Output
{ {
/** /**
* Writes a message to the output. * Writes a message to the output.
* *
* @param string $message A message to write to the output * @param string $message A message to write to the output
* @param Boolean $newline Whether to add a newline or not * @param Boolean $newline Whether to add a newline or not
*/ */
public function doWrite($message, $newline) public function doWrite($message, $newline)
{ {
} }
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Output; namespace Symfony\Component\Console\Output;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -20,211 +20,212 @@ namespace Symfony\Component\Console\Output;
* * verbose: -v (more output - debug) * * verbose: -v (more output - debug)
* * quiet: -q (no output) * * quiet: -q (no output)
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
abstract class Output implements OutputInterface abstract class Output implements OutputInterface
{ {
const VERBOSITY_QUIET = 0; const VERBOSITY_QUIET = 0;
const VERBOSITY_NORMAL = 1; const VERBOSITY_NORMAL = 1;
const VERBOSITY_VERBOSE = 2; const VERBOSITY_VERBOSE = 2;
const OUTPUT_NORMAL = 0; const OUTPUT_NORMAL = 0;
const OUTPUT_RAW = 1; const OUTPUT_RAW = 1;
const OUTPUT_PLAIN = 2; const OUTPUT_PLAIN = 2;
protected $verbosity; protected $verbosity;
protected $decorated; protected $decorated;
static protected $styles = array( static protected $styles = array(
'error' => array('bg' => 'red', 'fg' => 'white'), 'error' => array('bg' => 'red', 'fg' => 'white'),
'info' => array('fg' => 'green'), 'info' => array('fg' => 'green'),
'comment' => array('fg' => 'yellow'), 'comment' => array('fg' => 'yellow'),
'question' => array('bg' => 'cyan', 'fg' => 'black'), 'question' => array('bg' => 'cyan', 'fg' => 'black'),
); );
static protected $options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8); static protected $options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8);
static protected $foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37); static protected $foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37);
static protected $background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47); static protected $background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47);
/** /**
* Constructor. * Constructor.
* *
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
*/ */
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null) public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null)
{
$this->decorated = (Boolean) $decorated;
$this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
}
/**
* Sets a new style.
*
* @param string $name The style name
* @param array $options An array of options
*/
static public function setStyle($name, $options = array())
{
static::$styles[strtolower($name)] = $options;
}
/**
* Sets the decorated flag.
*
* @param Boolean $decorated Whether to decorated the messages or not
*/
public function setDecorated($decorated)
{
$this->decorated = (Boolean) $decorated;
}
/**
* Gets the decorated flag.
*
* @return Boolean true if the output will decorate messages, false otherwise
*/
public function isDecorated()
{
return $this->decorated;
}
/**
* Sets the verbosity of the output.
*
* @param integer $level The level of verbosity
*/
public function setVerbosity($level)
{
$this->verbosity = (int) $level;
}
/**
* Gets the current verbosity of the output.
*
* @return integer The current level of verbosity
*/
public function getVerbosity()
{
return $this->verbosity;
}
/**
* 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 integer $type The type of output
*/
public function writeln($messages, $type = 0)
{
$this->write($messages, true, $type);
}
/**
* Writes a message to the output.
*
* @param string|array $messages The message as an array of lines of a single string
* @param Boolean $newline Whether to add a newline or not
* @param integer $type The type of output
*/
public function write($messages, $newline = false, $type = 0)
{
if (self::VERBOSITY_QUIET === $this->verbosity)
{ {
return; $this->decorated = (Boolean) $decorated;
$this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
} }
if (!is_array($messages)) /**
* Sets a new style.
*
* @param string $name The style name
* @param array $options An array of options
*/
static public function setStyle($name, $options = array())
{ {
$messages = array($messages); static::$styles[strtolower($name)] = $options;
} }
foreach ($messages as $message) /**
* Sets the decorated flag.
*
* @param Boolean $decorated Whether to decorated the messages or not
*/
public function setDecorated($decorated)
{ {
switch ($type) $this->decorated = (Boolean) $decorated;
{
case Output::OUTPUT_NORMAL:
$message = $this->format($message);
break;
case Output::OUTPUT_RAW:
break;
case Output::OUTPUT_PLAIN:
$message = strip_tags($this->format($message));
break;
default:
throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
}
$this->doWrite($message, $newline);
}
}
/**
* Writes a message to the output.
*
* @param string $message A message to write to the output
* @param Boolean $newline Whether to add a newline or not
*/
abstract public function doWrite($message, $newline);
/**
* Formats a message according to the given styles.
*
* @param string $message The message to style
*
* @return string The styled message
*/
protected function format($message)
{
$message = preg_replace_callback('#<([a-z][a-z0-9\-_]+)>#i', array($this, 'replaceStartStyle'), $message);
return preg_replace_callback('#</([a-z][a-z0-9\-_]+)>#i', array($this, 'replaceEndStyle'), $message);
}
protected function replaceStartStyle($match)
{
if (!$this->decorated)
{
return '';
} }
if (!isset(static::$styles[strtolower($match[1])])) /**
* Gets the decorated flag.
*
* @return Boolean true if the output will decorate messages, false otherwise
*/
public function isDecorated()
{ {
throw new \InvalidArgumentException(sprintf('Unknown style "%s".', $match[1])); return $this->decorated;
} }
$parameters = static::$styles[strtolower($match[1])]; /**
$codes = array(); * Sets the verbosity of the output.
*
if (isset($parameters['fg'])) * @param integer $level The level of verbosity
*/
public function setVerbosity($level)
{ {
$codes[] = static::$foreground[$parameters['fg']]; $this->verbosity = (int) $level;
} }
if (isset($parameters['bg'])) /**
* Gets the current verbosity of the output.
*
* @return integer The current level of verbosity
*/
public function getVerbosity()
{ {
$codes[] = static::$background[$parameters['bg']]; return $this->verbosity;
} }
foreach (static::$options as $option => $value) /**
* 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 integer $type The type of output
*/
public function writeln($messages, $type = 0)
{ {
if (isset($parameters[$option]) && $parameters[$option]) $this->write($messages, true, $type);
{
$codes[] = $value;
}
} }
return "\033[".implode(';', $codes)."m"; /**
} * Writes a message to the output.
*
protected function replaceEndStyle($match) * @param string|array $messages The message as an array of lines of a single string
{ * @param Boolean $newline Whether to add a newline or not
if (!$this->decorated) * @param integer $type The type of output
*
* @throws \InvalidArgumentException When unknown output type is given
*/
public function write($messages, $newline = false, $type = 0)
{ {
return ''; if (self::VERBOSITY_QUIET === $this->verbosity) {
return;
}
if (!is_array($messages)) {
$messages = array($messages);
}
foreach ($messages as $message) {
switch ($type) {
case Output::OUTPUT_NORMAL:
$message = $this->format($message);
break;
case Output::OUTPUT_RAW:
break;
case Output::OUTPUT_PLAIN:
$message = strip_tags($this->format($message));
break;
default:
throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
}
$this->doWrite($message, $newline);
}
} }
return "\033[0m"; /**
} * Writes a message to the output.
*
* @param string $message A message to write to the output
* @param Boolean $newline Whether to add a newline or not
*/
abstract public function doWrite($message, $newline);
/**
* Formats a message according to the given styles.
*
* @param string $message The message to style
*
* @return string The styled message
*/
protected function format($message)
{
$message = preg_replace_callback('#<([a-z][a-z0-9\-_=;]+)>#i', array($this, 'replaceStartStyle'), $message);
return preg_replace_callback('#</([a-z][a-z0-9\-_]*)?>#i', array($this, 'replaceEndStyle'), $message);
}
/**
* @throws \InvalidArgumentException When style is unknown
*/
protected function replaceStartStyle($match)
{
if (!$this->decorated) {
return '';
}
if (isset(static::$styles[strtolower($match[1])])) {
$parameters = static::$styles[strtolower($match[1])];
} else {
// bg=blue;fg=red
if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($match[1]), $matches, PREG_SET_ORDER)) {
throw new \InvalidArgumentException(sprintf('Unknown style "%s".', $match[1]));
}
$parameters = array();
foreach ($matches as $match) {
$parameters[$match[1]] = $match[2];
}
}
$codes = array();
if (isset($parameters['fg'])) {
$codes[] = static::$foreground[$parameters['fg']];
}
if (isset($parameters['bg'])) {
$codes[] = static::$background[$parameters['bg']];
}
foreach (static::$options as $option => $value) {
if (isset($parameters[$option]) && $parameters[$option]) {
$codes[] = $value;
}
}
return "\033[".implode(';', $codes).'m';
}
protected function replaceEndStyle($match)
{
if (!$this->decorated) {
return '';
}
return "\033[0m";
}
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Output; namespace Symfony\Component\Console\Output;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -14,31 +14,32 @@ namespace Symfony\Component\Console\Output;
/** /**
* OutputInterface is the interface implemented by all Output classes. * OutputInterface is the interface implemented by all Output classes.
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
interface OutputInterface interface OutputInterface
{ {
/** /**
* Writes a message to the output. * Writes a message to the output.
* *
* @param string|array $messages The message as an array of lines of a single string * @param string|array $messages The message as an array of lines of a single string
* @param integer $type The type of output * @param Boolean $newline Whether to add a newline or not
*/ * @param integer $type The type of output
public function write($messages, $type = 0); *
* @throws \InvalidArgumentException When unknown output type is given
*/
function write($messages, $newline = false, $type = 0);
/** /**
* Sets the verbosity of the output. * Sets the verbosity of the output.
* *
* @param integer $level The level of verbosity * @param integer $level The level of verbosity
*/ */
public function setVerbosity($level); function setVerbosity($level);
/** /**
* Sets the decorated flag. * Sets the decorated flag.
* *
* @param Boolean $decorated Whether to decorated the messages or not * @param Boolean $decorated Whether to decorated the messages or not
*/ */
public function setDecorated($decorated); function setDecorated($decorated);
} }

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Console\Output; namespace Symfony\Component\Console\Output;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -22,88 +22,84 @@ namespace Symfony\Component\Console\Output;
* *
* $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class StreamOutput extends Output class StreamOutput extends Output
{ {
protected $stream; protected $stream;
/** /**
* Constructor. * Constructor.
* *
* @param mixed $stream A stream resource * @param mixed $stream A stream resource
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
*/ *
public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null) * @throws \InvalidArgumentException When first argument is not a real stream
{ */
if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null)
{ {
throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
}
$this->stream = $stream;
if (null === $decorated) {
$decorated = $this->hasColorSupport($decorated);
}
parent::__construct($verbosity, $decorated);
} }
$this->stream = $stream; /**
* Gets the stream attached to this StreamOutput instance.
if (null === $decorated) *
* @return resource A stream resource
*/
public function getStream()
{ {
$decorated = $this->hasColorSupport($decorated); return $this->stream;
} }
parent::__construct($verbosity, $decorated); /**
} * Writes a message to the output.
*
/** * @param string $message A message to write to the output
* Gets the stream attached to this StreamOutput instance. * @param Boolean $newline Whether to add a newline or not
* *
* @return resource A stream resource * @throws \RuntimeException When unable to write output (should never happen)
*/ */
public function getStream() public function doWrite($message, $newline)
{
return $this->stream;
}
/**
* Writes a message to the output.
*
* @param string $message A message to write to the output
* @param Boolean $newline Whether to add a newline or not
*/
public function doWrite($message, $newline)
{
if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : '')))
{ {
// @codeCoverageIgnoreStart if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
// should never happen // @codeCoverageIgnoreStart
throw new \RuntimeException('Unable to write output.'); // should never happen
// @codeCoverageIgnoreEnd throw new \RuntimeException('Unable to write output.');
// @codeCoverageIgnoreEnd
}
flush();
} }
flush(); /**
} * Returns true if the stream supports colorization.
*
/** * Colorization is disabled if not supported by the stream:
* Returns true if the stream supports colorization. *
* * - windows without ansicon
* Colorization is disabled if not supported by the stream: * - non tty consoles
* *
* - windows without ansicon * @return Boolean true if the stream supports colorization, false otherwise
* - non tty consoles */
* protected function hasColorSupport()
* @return Boolean true if the stream supports colorization, false otherwise
*/
protected function hasColorSupport()
{
// @codeCoverageIgnoreStart
if (DIRECTORY_SEPARATOR == '\\')
{ {
return false !== getenv('ANSICON'); // @codeCoverageIgnoreStart
if (DIRECTORY_SEPARATOR == '\\') {
return false !== getenv('ANSICON');
} else {
return function_exists('posix_isatty') && @posix_isatty($this->stream);
}
// @codeCoverageIgnoreEnd
} }
else
{
return function_exists('posix_isatty') && @posix_isatty($this->stream);
}
// @codeCoverageIgnoreEnd
}
} }

View File

@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutput;
/* /*
* This file is part of the symfony framework. * This file is part of the Symfony framework.
* *
* (c) Fabien Potencier <fabien.potencier@symfony-project.com> * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* *
@ -21,118 +21,108 @@ use Symfony\Component\Console\Output\ConsoleOutput;
* This class only works with a PHP compiled with readline support * This class only works with a PHP compiled with readline support
* (either --with-readline or --with-libedit) * (either --with-readline or --with-libedit)
* *
* @package symfony * @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @subpackage cli
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/ */
class Shell class Shell
{ {
protected $application; protected $application;
protected $history; protected $history;
protected $output; protected $output;
/** /**
* Constructor. * Constructor.
* *
* If there is no readline support for the current PHP executable * If there is no readline support for the current PHP executable
* a \RuntimeException exception is thrown. * a \RuntimeException exception is thrown.
* *
* @param Application $application An application instance * @param Application $application An application instance
*/ *
public function __construct(Application $application) * @throws \RuntimeException When Readline extension is not enabled
{ */
if (!function_exists('readline')) public function __construct(Application $application)
{ {
throw new \RuntimeException('Unable to start the shell as the Readline extension is not enabled.'); if (!function_exists('readline')) {
throw new \RuntimeException('Unable to start the shell as the Readline extension is not enabled.');
}
$this->application = $application;
$this->history = getenv('HOME').'/.history_'.$application->getName();
$this->output = new ConsoleOutput();
} }
$this->application = $application; /**
$this->history = getenv('HOME').'/.history_'.$application->getName(); * Runs the shell.
$this->output = new ConsoleOutput(); */
} public function run()
/**
* Runs the shell.
*/
public function run()
{
$this->application->setAutoExit(false);
$this->application->setCatchExceptions(true);
readline_read_history($this->history);
readline_completion_function(array($this, 'autocompleter'));
$this->output->writeln($this->getHeader());
while (true)
{ {
$command = readline($this->application->getName().' > '); $this->application->setAutoExit(false);
$this->application->setCatchExceptions(true);
if (false === $command) readline_read_history($this->history);
{ readline_completion_function(array($this, 'autocompleter'));
$this->output->writeln("\n");
break; $this->output->writeln($this->getHeader());
} while (true) {
$command = readline($this->application->getName().' > ');
readline_add_history($command); if (false === $command) {
readline_write_history($this->history); $this->output->writeln("\n");
if (0 !== $ret = $this->application->run(new StringInput($command), $this->output)) break;
{ }
$this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
}
}
}
/** readline_add_history($command);
* Tries to return autocompletion for the current entered text. readline_write_history($this->history);
*
* @param string $text The last segment of the entered text
* @param integer $position The current position
*/
protected function autocompleter($text, $position)
{
$info = readline_info();
$text = substr($info['line_buffer'], 0, $info['end']);
if ($info['point'] !== $info['end']) if (0 !== $ret = $this->application->run(new StringInput($command), $this->output)) {
{ $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
return true; }
}
} }
// task name? /**
if (false === strpos($text, ' ') || !$text) * Tries to return autocompletion for the current entered text.
*
* @param string $text The last segment of the entered text
* @param integer $position The current position
*/
protected function autocompleter($text, $position)
{ {
return array_keys($this->application->getCommands()); $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->getCommands());
}
// options and arguments?
try {
$command = $this->application->findCommand(substr($text, 0, strpos($text, ' ')));
} catch (\Exception $e) {
return true;
}
$list = array('--help');
foreach ($command->getDefinition()->getOptions() as $option) {
$list[] = '--'.$option->getName();
}
return $list;
} }
// options and arguments? /**
try * Returns the shell header.
*
* @return string The header string
*/
protected function getHeader()
{ {
$command = $this->application->findCommand(substr($text, 0, strpos($text, ' '))); return <<<EOF
}
catch (\Exception $e)
{
return true;
}
$list = array('--help');
foreach ($command->getDefinition()->getOptions() as $option)
{
$list[] = '--'.$option->getName();
}
return $list;
}
/**
* 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>). Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
@ -142,5 +132,5 @@ or <comment>list</comment> to get a list available commands.
To exit the shell, type <comment>^D</comment>. To exit the shell, type <comment>^D</comment>.
EOF; EOF;
} }
} }

View File

@ -6,87 +6,96 @@ use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Output\StreamOutput;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class ApplicationTester class ApplicationTester
{ {
protected $application; protected $application;
protected $display; protected $display;
protected $input; protected $input;
protected $output; protected $output;
/** /**
* Constructor. * Constructor.
* *
* @param Application $application A Application instance to test. * @param Application $application A Application instance to test.
*/ */
public function __construct(Application $application) public function __construct(Application $application)
{
$this->application = $application;
}
/**
* Executes the application.
*
* Available options:
*
* * interactive: Sets the input interactive flag
* * decorated: Sets the output decorated flag
* * verbosity: Sets the output verbosity flag
*
* @param array $input An array of arguments and options
* @param array $options An array of options
*/
public function run(array $input, $options = array())
{
$this->input = new ArrayInput($input);
if (isset($options['interactive']))
{ {
$this->input->setInteractive($options['interactive']); $this->application = $application;
} }
$this->output = new StreamOutput(fopen('php://memory', 'w', false)); /**
if (isset($options['decorated'])) * Executes the application.
*
* Available options:
*
* * interactive: Sets the input interactive flag
* * decorated: Sets the output decorated flag
* * verbosity: Sets the output verbosity flag
*
* @param array $input An array of arguments and options
* @param array $options An array of options
*/
public function run(array $input, $options = array())
{ {
$this->output->setDecorated($options['decorated']); $this->input = new ArrayInput($input);
} if (isset($options['interactive'])) {
if (isset($options['verbosity'])) $this->input->setInteractive($options['interactive']);
{ }
$this->output->setVerbosity($options['verbosity']);
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
if (isset($options['decorated'])) {
$this->output->setDecorated($options['decorated']);
}
if (isset($options['verbosity'])) {
$this->output->setVerbosity($options['verbosity']);
}
$ret = $this->application->run($this->input, $this->output);
rewind($this->output->getStream());
return $this->display = stream_get_contents($this->output->getStream());
} }
$ret = $this->application->run($this->input, $this->output); /**
* Gets the display returned by the last execution of the application.
*
* @return string The display
*/
public function getDisplay()
{
return $this->display;
}
rewind($this->output->getStream()); /**
* Gets the input instance used by the last execution of the application.
*
* @return InputInterface The current input instance
*/
public function getInput()
{
return $this->input;
}
return $this->display = stream_get_contents($this->output->getStream()); /**
} * Gets the output instance used by the last execution of the application.
*
/** * @return OutputInterface The current output instance
* Gets the display returned by the last execution of the application. */
* public function getOutput()
* @return string The display {
*/ return $this->output;
public function getDisplay() }
{
return $this->display;
}
/**
* Gets the input instance used by the last execution of the application.
*
* @return InputInterface The current input instance
*/
public function getInput()
{
return $this->input;
}
/**
* Gets the output instance used by the last execution of the application.
*
* @return OutputInterface The current output instance
*/
public function getOutput()
{
return $this->output;
}
} }

View File

@ -6,87 +6,96 @@ use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Output\StreamOutput;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class CommandTester class CommandTester
{ {
protected $command; protected $command;
protected $display; protected $display;
protected $input; protected $input;
protected $output; protected $output;
/** /**
* Constructor. * Constructor.
* *
* @param Command $command A Command instance to test. * @param Command $command A Command instance to test.
*/ */
public function __construct(Command $command) public function __construct(Command $command)
{
$this->command = $command;
}
/**
* Executes the command.
*
* Available options:
*
* * interactive: Sets the input interactive flag
* * decorated: Sets the output decorated flag
* * verbosity: Sets the output verbosity flag
*
* @param array $input An array of arguments and options
* @param array $options An array of options
*/
public function execute(array $input, array $options = array())
{
$this->input = new ArrayInput(array_merge($input, array('command' => $this->command->getFullName())));
if (isset($options['interactive']))
{ {
$this->input->setInteractive($options['interactive']); $this->command = $command;
} }
$this->output = new StreamOutput(fopen('php://memory', 'w', false)); /**
if (isset($options['decorated'])) * Executes the command.
*
* Available options:
*
* * interactive: Sets the input interactive flag
* * decorated: Sets the output decorated flag
* * verbosity: Sets the output verbosity flag
*
* @param array $input An array of arguments and options
* @param array $options An array of options
*/
public function execute(array $input, array $options = array())
{ {
$this->output->setDecorated($options['decorated']); $this->input = new ArrayInput($input);
} if (isset($options['interactive'])) {
if (isset($options['verbosity'])) $this->input->setInteractive($options['interactive']);
{ }
$this->output->setVerbosity($options['verbosity']);
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
if (isset($options['decorated'])) {
$this->output->setDecorated($options['decorated']);
}
if (isset($options['verbosity'])) {
$this->output->setVerbosity($options['verbosity']);
}
$ret = $this->command->run($this->input, $this->output);
rewind($this->output->getStream());
return $this->display = stream_get_contents($this->output->getStream());
} }
$ret = $this->command->run($this->input, $this->output); /**
* Gets the display returned by the last execution of the command.
*
* @return string The display
*/
public function getDisplay()
{
return $this->display;
}
rewind($this->output->getStream()); /**
* Gets the input instance used by the last execution of the command.
*
* @return InputInterface The current input instance
*/
public function getInput()
{
return $this->input;
}
return $this->display = stream_get_contents($this->output->getStream()); /**
} * Gets the output instance used by the last execution of the command.
*
/** * @return OutputInterface The current output instance
* Gets the display returned by the last execution of the command. */
* public function getOutput()
* @return string The display {
*/ return $this->output;
public function getDisplay() }
{
return $this->display;
}
/**
* Gets the input instance used by the last execution of the command.
*
* @return InputInterface The current input instance
*/
public function getInput()
{
return $this->input;
}
/**
* Gets the output instance used by the last execution of the command.
*
* @return OutputInterface The current output instance
*/
public function getOutput()
{
return $this->output;
}
} }