update Piwik to version 2.16 (fixes #91)

This commit is contained in:
oliver 2016-04-10 18:55:57 +02:00
commit 47263617c5
59 changed files with 418860 additions and 226988 deletions

View file

@ -1,3 +0,0 @@
vendor/
composer.lock
phpunit.xml

View file

@ -13,6 +13,9 @@ namespace Symfony\Component\Console;
use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Helper\DebugFormatterHelper;
use Symfony\Component\Console\Helper\ProcessHelper;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
@ -67,6 +70,7 @@ class Application
private $helperSet;
private $dispatcher;
private $terminalDimensions;
private $defaultCommand;
/**
* Constructor.
@ -80,6 +84,7 @@ class Application
{
$this->name = $name;
$this->version = $version;
$this->defaultCommand = 'list';
$this->helperSet = $this->getDefaultHelperSet();
$this->definition = $this->getDefaultInputDefinition();
@ -99,7 +104,7 @@ class Application
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @return integer 0 if everything went fine, or an error code
* @return int 0 if everything went fine, or an error code
*
* @throws \Exception When doRun returns Exception
*
@ -145,9 +150,8 @@ class Application
if ($exitCode > 255) {
$exitCode = 255;
}
// @codeCoverageIgnoreStart
exit($exitCode);
// @codeCoverageIgnoreEnd
}
return $exitCode;
@ -159,7 +163,7 @@ class Application
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @return integer 0 if everything went fine, or an error code
* @return int 0 if everything went fine, or an error code
*/
public function doRun(InputInterface $input, OutputInterface $output)
{
@ -180,8 +184,8 @@ class Application
}
if (!$name) {
$name = 'list';
$input = new ArrayInput(array('command' => 'list'));
$name = $this->defaultCommand;
$input = new ArrayInput(array('command' => $this->defaultCommand));
}
// the command name MUST be the first element of the input
@ -219,7 +223,7 @@ class Application
}
/**
* Set an input definition set to be used with this application
* Set an input definition set to be used with this application.
*
* @param InputDefinition $definition The input definition
*
@ -247,48 +251,31 @@ class Application
*/
public function getHelp()
{
$messages = array(
$this->getLongVersion(),
'',
'<comment>Usage:</comment>',
' [options] command [arguments]',
'',
'<comment>Options:</comment>',
);
foreach ($this->getDefinition()->getOptions() as $option) {
$messages[] = sprintf(' %-29s %s %s',
'<info>--'.$option->getName().'</info>',
$option->getShortcut() ? '<info>-'.$option->getShortcut().'</info>' : ' ',
$option->getDescription()
);
}
return implode(PHP_EOL, $messages);
return $this->getLongVersion();
}
/**
* Sets whether to catch exceptions or not during commands execution.
*
* @param Boolean $boolean Whether to catch exceptions or not during commands execution
* @param bool $boolean Whether to catch exceptions or not during commands execution
*
* @api
*/
public function setCatchExceptions($boolean)
{
$this->catchExceptions = (Boolean) $boolean;
$this->catchExceptions = (bool) $boolean;
}
/**
* Sets whether to automatically exit after a command execution or not.
*
* @param Boolean $boolean Whether to automatically exit after a command execution or not
* @param bool $boolean Whether to automatically exit after a command execution or not
*
* @api
*/
public function setAutoExit($boolean)
{
$this->autoExit = (Boolean) $boolean;
$this->autoExit = (bool) $boolean;
}
/**
@ -453,7 +440,7 @@ class Application
*
* @param string $name The command name or alias
*
* @return Boolean true if the command exists, false otherwise
* @return bool true if the command exists, false otherwise
*
* @api
*/
@ -473,10 +460,10 @@ class Application
{
$namespaces = array();
foreach ($this->commands as $command) {
$namespaces[] = $this->extractNamespace($command->getName());
$namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
foreach ($command->getAliases() as $alias) {
$namespaces[] = $this->extractNamespace($alias);
$namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
}
}
@ -501,7 +488,7 @@ class Application
if (empty($namespaces)) {
$message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
if ($alternatives = $this->findAlternatives($namespace, $allNamespaces, array())) {
if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
if (1 == count($alternatives)) {
$message .= "\n\nDid you mean this?\n ";
} else {
@ -550,7 +537,7 @@ class Application
$message = sprintf('Command "%s" is not defined.', $name);
if ($alternatives = $this->findAlternatives($name, $allCommands, array())) {
if ($alternatives = $this->findAlternatives($name, $allCommands)) {
if (1 == count($alternatives)) {
$message .= "\n\nDid you mean this?\n ";
} else {
@ -632,8 +619,8 @@ class Application
/**
* Returns a text representation of the Application.
*
* @param string $namespace An optional namespace name
* @param boolean $raw Whether to return raw command list
* @param string $namespace An optional namespace name
* @param bool $raw Whether to return raw command list
*
* @return string A string representing the Application
*
@ -651,8 +638,8 @@ class Application
/**
* Returns an XML representation of the Application.
*
* @param string $namespace An optional namespace name
* @param Boolean $asDom Whether to return a DOM or an XML string
* @param string $namespace An optional namespace name
* @param bool $asDom Whether to return a DOM or an XML string
*
* @return string|\DOMDocument An XML string representing the Application
*
@ -675,34 +662,27 @@ class Application
/**
* Renders a caught exception.
*
* @param \Exception $e An exception instance
* @param \Exception $e An exception instance
* @param OutputInterface $output An OutputInterface instance
*/
public function renderException($e, $output)
{
$strlen = function ($string) {
if (!function_exists('mb_strlen')) {
return strlen($string);
}
if (false === $encoding = mb_detect_encoding($string)) {
return strlen($string);
}
return mb_strlen($string, $encoding);
};
do {
$title = sprintf(' [%s] ', get_class($e));
$len = $strlen($title);
$len = $this->stringWidth($title);
$width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
// HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
$width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : (defined('HHVM_VERSION') ? 1 << 31 : PHP_INT_MAX);
if (defined('HHVM_VERSION') && $width > 1 << 31) {
$width = 1 << 31;
}
$formatter = $output->getFormatter();
$lines = array();
foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
foreach (str_split($line, $width - 4) as $line) {
foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
// pre-format lines to get the right string length
$lineLength = $strlen(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
$lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
$lines[] = array($line, $lineLength);
$len = max($lineLength, $len);
@ -711,7 +691,7 @@ class Application
$messages = array('', '');
$messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len)));
$messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $strlen($title)))));
$messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title)))));
foreach ($lines as $line) {
$messages[] = $formatter->format(sprintf('<error> %s %s</error>', $line[0], str_repeat(' ', $len - $line[1])));
}
@ -728,12 +708,12 @@ class Application
$trace = $e->getTrace();
array_unshift($trace, array(
'function' => '',
'file' => $e->getFile() != null ? $e->getFile() : 'n/a',
'line' => $e->getLine() != null ? $e->getLine() : 'n/a',
'args' => array(),
'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
'args' => array(),
));
for ($i = 0, $count = count($trace); $i < $count; $i++) {
for ($i = 0, $count = count($trace); $i < $count; ++$i) {
$class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
$type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
$function = $trace[$i]['function'];
@ -743,20 +723,20 @@ class Application
$output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
}
$output->writeln("");
$output->writeln("");
$output->writeln('');
$output->writeln('');
}
} while ($e = $e->getPrevious());
if (null !== $this->runningCommand) {
$output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
$output->writeln("");
$output->writeln("");
$output->writeln('');
$output->writeln('');
}
}
/**
* Tries to figure out the terminal width in which this application runs
* Tries to figure out the terminal width in which this application runs.
*
* @return int|null
*/
@ -768,7 +748,7 @@ class Application
}
/**
* Tries to figure out the terminal height in which this application runs
* Tries to figure out the terminal height in which this application runs.
*
* @return int|null
*/
@ -780,7 +760,7 @@ class Application
}
/**
* Tries to figure out the terminal dimensions based on the current environment
* Tries to figure out the terminal dimensions based on the current environment.
*
* @return array Array containing width and height
*/
@ -790,7 +770,7 @@ class Application
return $this->terminalDimensions;
}
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
if ('\\' === DIRECTORY_SEPARATOR) {
// extract [w, H] from "wxh (WxH)"
if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
return array((int) $matches[1], (int) $matches[2]);
@ -820,8 +800,8 @@ class Application
*
* Can be useful to force terminal dimensions for functional tests.
*
* @param integer $width The width
* @param integer $height The height
* @param int $width The width
* @param int $height The height
*
* @return Application The current application
*/
@ -848,9 +828,9 @@ class Application
if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
$input->setInteractive(false);
} elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) {
$inputStream = $this->getHelperSet()->get('dialog')->getInputStream();
if (!@posix_isatty($inputStream)) {
} elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
$inputStream = $this->getHelperSet()->get('question')->getInputStream();
if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
$input->setInteractive(false);
}
}
@ -878,7 +858,9 @@ class Application
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @return integer 0 if everything went fine, or an error code
* @return int 0 if everything went fine, or an error code
*
* @throws \Exception when the command being run threw an exception
*/
protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
{
@ -895,16 +877,20 @@ class Application
$event = new ConsoleCommandEvent($command, $input, $output);
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
try {
$exitCode = $command->run($input, $output);
} catch (\Exception $e) {
$event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
if ($event->commandShouldRun()) {
try {
$exitCode = $command->run($input, $output);
} catch (\Exception $e) {
$event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
throw $event->getException();
throw $event->getException();
}
} else {
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
}
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
@ -935,13 +921,13 @@ class Application
return new InputDefinition(array(
new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'),
new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message.'),
new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version.'),
new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output.'),
new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output.'),
new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'),
new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
));
}
@ -967,11 +953,14 @@ class Application
new DialogHelper(),
new ProgressHelper(),
new TableHelper(),
new DebugFormatterHelper(),
new ProcessHelper(),
new QuestionHelper(),
));
}
/**
* Runs and parses stty -a if it's available, suppressing any error output
* Runs and parses stty -a if it's available, suppressing any error output.
*
* @return string
*/
@ -994,7 +983,7 @@ class Application
}
/**
* Runs and parses mode CON if it's available, suppressing any error output
* Runs and parses mode CON if it's available, suppressing any error output.
*
* @return string <width>x<height> or null if it could not be parsed
*/
@ -1050,10 +1039,10 @@ class Application
/**
* Finds alternative of $name among $collection,
* if nothing is found in $collection, try in $abbrevs
* if nothing is found in $collection, try in $abbrevs.
*
* @param string $name The string
* @param array|\Traversable $collection The collection
* @param string $name The string
* @param array|\Traversable $collection The collection
*
* @return array A sorted array of similar string
*/
@ -1078,7 +1067,7 @@ class Application
}
$lev = levenshtein($subname, $parts[$i]);
if ($lev <= strlen($subname) / 3 || false !== strpos($parts[$i], $subname)) {
if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
$alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
} elseif ($exists) {
$alternatives[$collectionName] += $threshold;
@ -1093,9 +1082,92 @@ class Application
}
}
$alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2*$threshold; });
$alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
asort($alternatives);
return array_keys($alternatives);
}
/**
* Sets the default Command name.
*
* @param string $commandName The Command name
*/
public function setDefaultCommand($commandName)
{
$this->defaultCommand = $commandName;
}
private function stringWidth($string)
{
if (!function_exists('mb_strwidth')) {
return strlen($string);
}
if (false === $encoding = mb_detect_encoding($string)) {
return strlen($string);
}
return mb_strwidth($string, $encoding);
}
private function splitStringByWidth($string, $width)
{
// str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
// additionally, array_slice() is not enough as some character has doubled width.
// we need a function to split string not by character count but by string width
if (!function_exists('mb_strwidth')) {
return str_split($string, $width);
}
if (false === $encoding = mb_detect_encoding($string)) {
return str_split($string, $width);
}
$utf8String = mb_convert_encoding($string, 'utf8', $encoding);
$lines = array();
$line = '';
foreach (preg_split('//u', $utf8String) as $char) {
// test if $char could be appended to current line
if (mb_strwidth($line.$char, 'utf8') <= $width) {
$line .= $char;
continue;
}
// if not, push current line to array and make new line
$lines[] = str_pad($line, $width);
$line = $char;
}
if ('' !== $line) {
$lines[] = count($lines) ? str_pad($line, $width) : $line;
}
mb_convert_variables($encoding, 'utf8', $lines);
return $lines;
}
/**
* Returns all namespaces of the command name.
*
* @param string $name The full name of the command
*
* @return array The namespaces of the command
*/
private function extractAllNamespaces($name)
{
// -1 as third argument is needed to skip the command short name when exploding
$parts = explode(':', $name, -1);
$namespaces = array();
foreach ($parts as $part) {
if (count($namespaces)) {
$namespaces[] = end($namespaces).':'.$part;
} else {
$namespaces[] = $part;
}
}
return $namespaces;
}
}

View file

@ -1,6 +1,23 @@
CHANGELOG
=========
2.6.0
-----
* added a Process helper
* added a DebugFormatter helper
2.5.0
-----
* deprecated the dialog helper (use the question helper instead)
* deprecated TableHelper in favor of Table
* deprecated ProgressHelper in favor of ProgressBar
* added ConsoleLogger
* added a question helper
* added a way to set the process name of a command
* added a way to set a default command instead of `ListCommand`
2.4.0
-----

View file

@ -33,6 +33,7 @@ class Command
{
private $application;
private $name;
private $processTitle;
private $aliases = array();
private $definition;
private $help;
@ -64,7 +65,7 @@ class Command
$this->configure();
if (!$this->name) {
throw new \LogicException('The command name cannot be empty.');
throw new \LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
}
}
@ -128,12 +129,12 @@ class Command
}
/**
* Checks whether the command is enabled or not in the current environment
* Checks whether the command is enabled or not in the current environment.
*
* Override this to check for x or y and return false if the command can not
* run properly under the current conditions.
*
* @return Boolean
* @return bool
*/
public function isEnabled()
{
@ -158,10 +159,11 @@ class Command
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @return null|integer null or 0 if everything went fine, or an error code
* @return null|int null or 0 if everything went fine, or an error code
*
* @throws \LogicException When this abstract method is not implemented
* @see setCode()
*
* @see setCode()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
@ -171,6 +173,10 @@ class Command
/**
* Interacts with the user.
*
* This method is executed before the InputDefinition is validated.
* This means that this is the only place where the command can
* interactively ask for values of missing required arguments.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
@ -201,7 +207,7 @@ class Command
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @return integer The command exit code
* @return int The command exit code
*
* @throws \Exception
*
@ -229,6 +235,16 @@ class Command
$this->initialize($input, $output);
if (null !== $this->processTitle) {
if (function_exists('cli_set_process_title')) {
cli_set_process_title($this->processTitle);
} elseif (function_exists('setproctitle')) {
setproctitle($this->processTitle);
} elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
$output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
}
}
if ($input->isInteractive()) {
$this->interact($input, $output);
}
@ -276,7 +292,7 @@ class Command
*
* This method is not part of public API and should not be used directly.
*
* @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
* @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
*/
public function mergeApplicationDefinition($mergeArgs = true)
{
@ -350,10 +366,10 @@ class Command
/**
* 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)
* @param string $name The argument name
* @param int $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
*
@ -369,11 +385,11 @@ class Command
/**
* Adds an option.
*
* @param string $name The option name
* @param string $shortcut The shortcut (can be null)
* @param integer $mode The option mode: One of the InputOption::VALUE_* constants
* @param string $description A description text
* @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE)
* @param string $name The option name
* @param string $shortcut The shortcut (can be null)
* @param int $mode The option mode: One of the InputOption::VALUE_* constants
* @param string $description A description text
* @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE)
*
* @return Command The current instance
*
@ -411,6 +427,25 @@ class Command
return $this;
}
/**
* Sets the process title of the command.
*
* This feature should be used only when creating a long process command,
* like a daemon.
*
* PHP 5.5+ or the proctitle PECL library is required
*
* @param string $title The process title
*
* @return Command The current instance
*/
public function setProcessTitle($title)
{
$this->processTitle = $title;
return $this;
}
/**
* Returns the command name.
*
@ -483,7 +518,7 @@ class Command
* 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
* @return string The processed help for the command
*/
public function getProcessedHelp()
{
@ -491,11 +526,11 @@ class Command
$placeholders = array(
'%command.name%',
'%command.full_name%'
'%command.full_name%',
);
$replacements = array(
$name,
$_SERVER['PHP_SELF'].' '.$name
$_SERVER['PHP_SELF'].' '.$name,
);
return str_replace($placeholders, $replacements, $this->getHelp());
@ -504,7 +539,7 @@ class Command
/**
* Sets the aliases for the command.
*
* @param array $aliases An array of aliases for the command
* @param string[] $aliases An array of aliases for the command
*
* @return Command The current instance
*
@ -514,6 +549,10 @@ class Command
*/
public function setAliases($aliases)
{
if (!is_array($aliases) && !$aliases instanceof \Traversable) {
throw new \InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
}
foreach ($aliases as $alias) {
$this->validateName($alias);
}
@ -584,7 +623,7 @@ class Command
/**
* Returns an XML representation of the command.
*
* @param Boolean $asDom Whether to return a DOM or an XML string
* @param bool $asDom Whether to return a DOM or an XML string
*
* @return string|\DOMDocument An XML string representing the command
*

View file

@ -58,7 +58,7 @@ EOF
}
/**
* Sets the command
* Sets the command.
*
* @param Command $command The command to set
*/
@ -83,7 +83,7 @@ EOF
$helper = new DescriptorHelper();
$helper->describe($output, $this->command, array(
'format' => $input->getOption('format'),
'raw' => $input->getOption('raw'),
'raw_text' => $input->getOption('raw'),
));
$this->command = null;

View file

@ -74,8 +74,8 @@ EOF
$helper = new DescriptorHelper();
$helper->describe($output, $this->getApplication(), array(
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
'namespace' => $input->getArgument('namespace'),
));
}

View file

@ -26,6 +26,8 @@ final class ConsoleEvents
* The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent
* instance.
*
* @Event
*
* @var string
*/
const COMMAND = 'console.command';
@ -37,6 +39,8 @@ final class ConsoleEvents
* The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent
* instance.
*
* @Event
*
* @var string
*/
const TERMINATE = 'console.terminate';
@ -49,6 +53,8 @@ final class ConsoleEvents
* a Symfony\Component\Console\Event\ConsoleExceptionEvent
* instance.
*
* @Event
*
* @var string
*/
const EXCEPTION = 'console.exception';

View file

@ -16,6 +16,8 @@ use Symfony\Component\Console\Command\Command;
/**
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
*
* @internal
*/
class ApplicationDescription
{
@ -144,9 +146,11 @@ class ApplicationDescription
}
ksort($namespacedCommands);
foreach ($namespacedCommands as &$commands) {
ksort($commands);
foreach ($namespacedCommands as &$commandsSet) {
ksort($commandsSet);
}
// unset reference to keep scope clear
unset($commandsSet);
return $namespacedCommands;
}

View file

@ -20,6 +20,8 @@ use Symfony\Component\Console\Output\OutputInterface;
/**
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
*
* @internal
*/
abstract class Descriptor implements DescriptorInterface
{
@ -59,8 +61,8 @@ abstract class Descriptor implements DescriptorInterface
/**
* Writes content to output.
*
* @param string $content
* @param boolean $decorated
* @param string $content
* @param bool $decorated
*/
protected function write($content, $decorated = false)
{

View file

@ -21,6 +21,8 @@ use Symfony\Component\Console\Input\InputOption;
* JSON descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @internal
*/
class JsonDescriptor extends Descriptor
{
@ -97,11 +99,11 @@ class JsonDescriptor extends Descriptor
private function getInputArgumentData(InputArgument $argument)
{
return array(
'name' => $argument->getName(),
'name' => $argument->getName(),
'is_required' => $argument->isRequired(),
'is_array' => $argument->isArray(),
'is_array' => $argument->isArray(),
'description' => $argument->getDescription(),
'default' => $argument->getDefault(),
'default' => $argument->getDefault(),
);
}
@ -113,13 +115,13 @@ class JsonDescriptor extends Descriptor
private function getInputOptionData(InputOption $option)
{
return array(
'name' => '--'.$option->getName(),
'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
'accept_value' => $option->acceptValue(),
'name' => '--'.$option->getName(),
'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
'accept_value' => $option->acceptValue(),
'is_value_required' => $option->isValueRequired(),
'is_multiple' => $option->isArray(),
'description' => $option->getDescription(),
'default' => $option->getDefault(),
'is_multiple' => $option->isArray(),
'description' => $option->getDescription(),
'default' => $option->getDefault(),
);
}
@ -154,12 +156,12 @@ class JsonDescriptor extends Descriptor
$command->mergeApplicationDefinition(false);
return array(
'name' => $command->getName(),
'usage' => $command->getSynopsis(),
'name' => $command->getName(),
'usage' => $command->getSynopsis(),
'description' => $command->getDescription(),
'help' => $command->getProcessedHelp(),
'aliases' => $command->getAliases(),
'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
'help' => $command->getProcessedHelp(),
'aliases' => $command->getAliases(),
'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
);
}
}

View file

@ -21,6 +21,8 @@ use Symfony\Component\Console\Input\InputOption;
* Markdown descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @internal
*/
class MarkdownDescriptor extends Descriptor
{
@ -103,7 +105,7 @@ class MarkdownDescriptor extends Descriptor
$this->write($help);
}
if ($definition = $command->getNativeDefinition()) {
if ($command->getNativeDefinition()) {
$this->write("\n\n");
$this->describeInputDefinition($command->getNativeDefinition());
}
@ -128,7 +130,7 @@ class MarkdownDescriptor extends Descriptor
$this->write("\n\n");
$this->write(implode("\n", array_map(function ($commandName) {
return '* '.$commandName;
} , $namespace['commands'])));
}, $namespace['commands'])));
}
foreach ($description->getCommands() as $command) {

View file

@ -21,6 +21,8 @@ use Symfony\Component\Console\Input\InputOption;
* Text descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @internal
*/
class TextDescriptor extends Descriptor
{
@ -157,13 +159,37 @@ class TextDescriptor extends Descriptor
$this->writeText("\n");
}
} else {
if ('' != $help = $application->getHelp()) {
$this->writeText("$help\n\n", $options);
}
$this->writeText("<comment>Usage:</comment>\n", $options);
$this->writeText(" command [options] [arguments]\n\n", $options);
$this->writeText('<comment>Options:</comment>', $options);
$inputOptions = $application->getDefinition()->getOptions();
$width = 0;
foreach ($inputOptions as $option) {
$nameLength = strlen($option->getName()) + 2;
if ($option->getShortcut()) {
$nameLength += strlen($option->getShortcut()) + 3;
}
$width = max($width, $nameLength);
}
++$width;
foreach ($inputOptions as $option) {
$this->writeText("\n", $options);
$this->describeInputOption($option, array_merge($options, array('name_width' => $width)));
}
$this->writeText("\n\n", $options);
$width = $this->getColumnWidth($description->getCommands());
$this->writeText($application->getHelp(), $options);
$this->writeText("\n\n");
if ($describedNamespace) {
$this->writeText(sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $describedNamespace), $options);
$this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
} else {
$this->writeText('<comment>Available commands:</comment>', $options);
}
@ -177,7 +203,7 @@ class TextDescriptor extends Descriptor
foreach ($namespace['commands'] as $name) {
$this->writeText("\n");
$this->writeText(sprintf(" <info>%-${width}s</info> %s", $name, $description->getCommand($name)->getDescription()), $options);
$this->writeText(sprintf(" <info>%-${width}s</info> %s", $name, $description->getCommand($name)->getDescription()), $options);
}
}
@ -205,7 +231,7 @@ class TextDescriptor extends Descriptor
*/
private function formatDefaultValue($default)
{
if (version_compare(PHP_VERSION, '5.4', '<')) {
if (PHP_VERSION_ID < 50400) {
return str_replace('\/', '/', json_encode($default));
}

View file

@ -21,6 +21,8 @@ use Symfony\Component\Console\Input\InputOption;
* XML descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @internal
*/
class XmlDescriptor extends Descriptor
{

View file

@ -12,10 +12,51 @@
namespace Symfony\Component\Console\Event;
/**
* Allows to do things before the command is executed.
* Allows to do things before the command is executed, like skipping the command or changing the input.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ConsoleCommandEvent extends ConsoleEvent
{
/**
* The return code for skipped commands, this will also be passed into the terminate event
*/
const RETURN_CODE_DISABLED = 113;
/**
* Indicates if the command should be run or skipped
*
* @var bool
*/
private $commandShouldRun = true;
/**
* Disables the command, so it won't be run
*
* @return bool
*/
public function disableCommand()
{
return $this->commandShouldRun = false;
}
/**
* Enables the command
*
* @return bool
*/
public function enableCommand()
{
return $this->commandShouldRun = true;
}
/**
* Returns true if the command is runnable, false otherwise
*
* @return bool
*/
public function commandShouldRun()
{
return $this->commandShouldRun;
}
}

View file

@ -58,7 +58,7 @@ class ConsoleExceptionEvent extends ConsoleEvent
/**
* Gets the exit code.
*
* @return integer The command exit code
* @return int The command exit code
*/
public function getExitCode()
{

View file

@ -25,7 +25,7 @@ class ConsoleTerminateEvent extends ConsoleEvent
/**
* The exit code of the command.
*
* @var integer
* @var int
*/
private $exitCode;
@ -39,7 +39,7 @@ class ConsoleTerminateEvent extends ConsoleEvent
/**
* Sets the exit code.
*
* @param integer $exitCode The command exit code
* @param int $exitCode The command exit code
*/
public function setExitCode($exitCode)
{
@ -49,7 +49,7 @@ class ConsoleTerminateEvent extends ConsoleEvent
/**
* Gets the exit code.
*
* @return integer The command exit code
* @return int The command exit code
*/
public function getExitCode()
{

View file

@ -33,20 +33,20 @@ class OutputFormatter implements OutputFormatterInterface
*/
public static function escape($text)
{
return preg_replace('/([^\\\\]?)</is', '$1\\<', $text);
return preg_replace('/([^\\\\]?)</', '$1\\<', $text);
}
/**
* Initializes console output formatter.
*
* @param Boolean $decorated Whether this formatter should actually decorate strings
* @param bool $decorated Whether this formatter should actually decorate strings
* @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
*
* @api
*/
public function __construct($decorated = false, array $styles = array())
{
$this->decorated = (Boolean) $decorated;
$this->decorated = (bool) $decorated;
$this->setStyle('error', new OutputFormatterStyle('white', 'red'));
$this->setStyle('info', new OutputFormatterStyle('green'));
@ -63,19 +63,19 @@ class OutputFormatter implements OutputFormatterInterface
/**
* Sets the decorated flag.
*
* @param Boolean $decorated Whether to decorate the messages or not
* @param bool $decorated Whether to decorate the messages or not
*
* @api
*/
public function setDecorated($decorated)
{
$this->decorated = (Boolean) $decorated;
$this->decorated = (bool) $decorated;
}
/**
* Gets the decorated flag.
*
* @return Boolean true if the output will decorate messages, false otherwise
* @return bool true if the output will decorate messages, false otherwise
*
* @api
*/
@ -102,7 +102,7 @@ class OutputFormatter implements OutputFormatterInterface
*
* @param string $name
*
* @return Boolean
* @return bool
*
* @api
*/
@ -142,14 +142,19 @@ class OutputFormatter implements OutputFormatterInterface
*/
public function format($message)
{
$message = (string) $message;
$offset = 0;
$output = '';
$tagRegex = '[a-z][a-z0-9_=;-]*';
preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#isx", $message, $matches, PREG_OFFSET_CAPTURE);
preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[0] as $i => $match) {
$pos = $match[1];
$text = $match[0];
if (0 != $pos && '\\' == $message[$pos - 1]) {
continue;
}
// add the text up to the next tag
$output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
$offset = $pos + strlen($text);
@ -164,9 +169,6 @@ class OutputFormatter implements OutputFormatterInterface
if (!$open && !$tag) {
// </>
$this->styleStack->pop();
} elseif ($pos && '\\' == $message[$pos - 1]) {
// escaped tag
$output .= $this->applyCurrentStyle($text);
} elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
$output .= $this->applyCurrentStyle($text);
} elseif ($open) {
@ -194,7 +196,7 @@ class OutputFormatter implements OutputFormatterInterface
*
* @param string $string
*
* @return OutputFormatterStyle|Boolean false if string is not format string
* @return OutputFormatterStyle|bool false if string is not format string
*/
private function createStyleFromString($string)
{
@ -215,7 +217,11 @@ class OutputFormatter implements OutputFormatterInterface
} elseif ('bg' == $match[0]) {
$style->setBackground($match[1]);
} else {
$style->setOption($match[1]);
try {
$style->setOption($match[1]);
} catch (\InvalidArgumentException $e) {
return false;
}
}
}

View file

@ -23,7 +23,7 @@ interface OutputFormatterInterface
/**
* Sets the decorated flag.
*
* @param Boolean $decorated Whether to decorate the messages or not
* @param bool $decorated Whether to decorate the messages or not
*
* @api
*/
@ -32,7 +32,7 @@ interface OutputFormatterInterface
/**
* Gets the decorated flag.
*
* @return Boolean true if the output will decorate messages, false otherwise
* @return bool true if the output will decorate messages, false otherwise
*
* @api
*/
@ -53,7 +53,7 @@ interface OutputFormatterInterface
*
* @param string $name
*
* @return Boolean
* @return bool
*
* @api
*/

View file

@ -21,31 +21,33 @@ namespace Symfony\Component\Console\Formatter;
class OutputFormatterStyle implements OutputFormatterStyleInterface
{
private static $availableForegroundColors = array(
'black' => 30,
'red' => 31,
'green' => 32,
'yellow' => 33,
'blue' => 34,
'magenta' => 35,
'cyan' => 36,
'white' => 37
'black' => array('set' => 30, 'unset' => 39),
'red' => array('set' => 31, 'unset' => 39),
'green' => array('set' => 32, 'unset' => 39),
'yellow' => array('set' => 33, 'unset' => 39),
'blue' => array('set' => 34, 'unset' => 39),
'magenta' => array('set' => 35, 'unset' => 39),
'cyan' => array('set' => 36, 'unset' => 39),
'white' => array('set' => 37, 'unset' => 39),
'default' => array('set' => 39, 'unset' => 39),
);
private static $availableBackgroundColors = array(
'black' => 40,
'red' => 41,
'green' => 42,
'yellow' => 43,
'blue' => 44,
'magenta' => 45,
'cyan' => 46,
'white' => 47
'black' => array('set' => 40, 'unset' => 49),
'red' => array('set' => 41, 'unset' => 49),
'green' => array('set' => 42, 'unset' => 49),
'yellow' => array('set' => 43, 'unset' => 49),
'blue' => array('set' => 44, 'unset' => 49),
'magenta' => array('set' => 45, 'unset' => 49),
'cyan' => array('set' => 46, 'unset' => 49),
'white' => array('set' => 47, 'unset' => 49),
'default' => array('set' => 49, 'unset' => 49),
);
private static $availableOptions = array(
'bold' => 1,
'underscore' => 4,
'blink' => 5,
'reverse' => 7,
'conceal' => 8
'bold' => array('set' => 1, 'unset' => 22),
'underscore' => array('set' => 4, 'unset' => 24),
'blink' => array('set' => 5, 'unset' => 25),
'reverse' => array('set' => 7, 'unset' => 27),
'conceal' => array('set' => 8, 'unset' => 28),
);
private $foreground;
@ -149,7 +151,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
));
}
if (false === array_search(static::$availableOptions[$option], $this->options)) {
if (!in_array(static::$availableOptions[$option], $this->options)) {
$this->options[] = static::$availableOptions[$option];
}
}
@ -160,7 +162,6 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
* @param string $option The option name
*
* @throws \InvalidArgumentException When the option name isn't defined
*
*/
public function unsetOption($option)
{
@ -201,22 +202,28 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
*/
public function apply($text)
{
$codes = array();
$setCodes = array();
$unsetCodes = array();
if (null !== $this->foreground) {
$codes[] = $this->foreground;
$setCodes[] = $this->foreground['set'];
$unsetCodes[] = $this->foreground['unset'];
}
if (null !== $this->background) {
$codes[] = $this->background;
$setCodes[] = $this->background['set'];
$unsetCodes[] = $this->background['unset'];
}
if (count($this->options)) {
$codes = array_merge($codes, $this->options);
foreach ($this->options as $option) {
$setCodes[] = $option['set'];
$unsetCodes[] = $option['unset'];
}
}
if (0 === count($codes)) {
if (0 === count($setCodes)) {
return $text;
}
return sprintf("\033[%sm%s\033[0m", implode(';', $codes), $text);
return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
}
}

View file

@ -62,7 +62,7 @@ class OutputFormatterStyleStack
*
* @return OutputFormatterStyleInterface
*
* @throws \InvalidArgumentException When style tags incorrectly nested
* @throws \InvalidArgumentException When style tags incorrectly nested
*/
public function pop(OutputFormatterStyleInterface $style = null)
{
@ -96,7 +96,7 @@ class OutputFormatterStyleStack
return $this->emptyStyle;
}
return $this->styles[count($this->styles)-1];
return $this->styles[count($this->styles) - 1];
}
/**

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