composer update
This commit is contained in:
17
vendor/symfony/console/Application.php
vendored
17
vendor/symfony/console/Application.php
vendored
@@ -753,12 +753,20 @@ class Application
|
||||
do {
|
||||
$message = trim($e->getMessage());
|
||||
if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
|
||||
$title = sprintf(' [%s%s] ', \get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
|
||||
$class = \get_class($e);
|
||||
$class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
|
||||
$title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
|
||||
$len = Helper::strlen($title);
|
||||
} else {
|
||||
$len = 0;
|
||||
}
|
||||
|
||||
if (false !== strpos($message, "class@anonymous\0")) {
|
||||
$message = preg_replace_callback('/class@anonymous\x00.*?\.php0x?[0-9a-fA-F]++/', function ($m) {
|
||||
return \class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
|
||||
}, $message);
|
||||
}
|
||||
|
||||
$width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX;
|
||||
$lines = array();
|
||||
foreach ('' !== $message ? preg_split('/\r?\n/', $message) : array() as $line) {
|
||||
@@ -793,6 +801,13 @@ class Application
|
||||
// exception related properties
|
||||
$trace = $e->getTrace();
|
||||
|
||||
array_unshift($trace, array(
|
||||
'function' => '',
|
||||
'file' => $e->getFile() ?: 'n/a',
|
||||
'line' => $e->getLine() ?: 'n/a',
|
||||
'args' => array(),
|
||||
));
|
||||
|
||||
for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
|
||||
$class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
|
||||
$type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
|
||||
|
11
vendor/symfony/console/CHANGELOG.md
vendored
11
vendor/symfony/console/CHANGELOG.md
vendored
@@ -1,6 +1,17 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* allowed passing commands as `array($process, 'ENV_VAR' => 'value')` to
|
||||
`ProcessHelper::run()` to pass environment variables
|
||||
* deprecated passing a command as a string to `ProcessHelper::run()`,
|
||||
pass it the command as an array of its arguments instead
|
||||
* made the `ProcessHelper` class final
|
||||
* added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`)
|
||||
* added `capture_stderr_separately` option to `CommandTester::execute()`
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
||||
|
35
vendor/symfony/console/Command/Command.php
vendored
35
vendor/symfony/console/Command/Command.php
vendored
@@ -150,7 +150,7 @@ class Command
|
||||
* execute() method, you set the code to execute by passing
|
||||
* a Closure to the setCode() method.
|
||||
*
|
||||
* @return null|int null or 0 if everything went fine, or an error code
|
||||
* @return int|null null or 0 if everything went fine, or an error code
|
||||
*
|
||||
* @throws LogicException When this abstract method is not implemented
|
||||
*
|
||||
@@ -173,10 +173,14 @@ class Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the command just after the input has been validated.
|
||||
* Initializes the command after the input has been bound and before the input
|
||||
* is 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.
|
||||
*
|
||||
* @see InputInterface::bind()
|
||||
* @see InputInterface::validate()
|
||||
*/
|
||||
protected function initialize(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
@@ -297,14 +301,13 @@ class Command
|
||||
|
||||
$this->definition->addOptions($this->application->getDefinition()->getOptions());
|
||||
|
||||
$this->applicationDefinitionMerged = true;
|
||||
|
||||
if ($mergeArgs) {
|
||||
$currentArguments = $this->definition->getArguments();
|
||||
$this->definition->setArguments($this->application->getDefinition()->getArguments());
|
||||
$this->definition->addArguments($currentArguments);
|
||||
}
|
||||
|
||||
$this->applicationDefinitionMerged = true;
|
||||
if ($mergeArgs) {
|
||||
$this->applicationDefinitionMergedWithArgs = true;
|
||||
}
|
||||
}
|
||||
@@ -357,10 +360,12 @@ class Command
|
||||
/**
|
||||
* Adds an argument.
|
||||
*
|
||||
* @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)
|
||||
* @param string $name The argument name
|
||||
* @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL
|
||||
* @param string $description A description text
|
||||
* @param string|string[]|null $default The default value (for self::OPTIONAL mode only)
|
||||
*
|
||||
* @throws InvalidArgumentException When argument mode is not valid
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -374,11 +379,13 @@ class Command
|
||||
/**
|
||||
* Adds an option.
|
||||
*
|
||||
* @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_NONE)
|
||||
* @param string $name The option name
|
||||
* @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
|
||||
* @param int|null $mode The option mode: One of the VALUE_* constants
|
||||
* @param string $description A description text
|
||||
* @param string|string[]|int|bool|null $default The default value (must be null for self::VALUE_NONE)
|
||||
*
|
||||
* @throws InvalidArgumentException If option mode is invalid or incompatible
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
@@ -12,7 +12,6 @@
|
||||
namespace Symfony\Component\Console\Command;
|
||||
|
||||
use Symfony\Component\Console\Exception\LogicException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Lock\Factory;
|
||||
use Symfony\Component\Lock\Lock;
|
||||
use Symfony\Component\Lock\Store\FlockStore;
|
||||
@@ -36,7 +35,7 @@ trait LockableTrait
|
||||
private function lock($name = null, $blocking = false)
|
||||
{
|
||||
if (!class_exists(SemaphoreStore::class)) {
|
||||
throw new RuntimeException('To enable the locking feature you must install the symfony/lock component.');
|
||||
throw new LogicException('To enable the locking feature you must install the symfony/lock component.');
|
||||
}
|
||||
|
||||
if (null !== $this->lock) {
|
||||
|
@@ -16,6 +16,6 @@ namespace Symfony\Component\Console\Exception;
|
||||
*
|
||||
* @author Jérôme Tamarelle <jerome@tamarelle.net>
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
interface ExceptionInterface extends \Throwable
|
||||
{
|
||||
}
|
||||
|
@@ -17,8 +17,9 @@ use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
* Formatter class for console output.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
* @author Roland Franssen <franssen.roland@gmail.com>
|
||||
*/
|
||||
class OutputFormatter implements OutputFormatterInterface
|
||||
class OutputFormatter implements WrappableOutputFormatterInterface
|
||||
{
|
||||
private $decorated;
|
||||
private $styles = array();
|
||||
@@ -130,10 +131,18 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
*/
|
||||
public function format($message)
|
||||
{
|
||||
$message = (string) $message;
|
||||
return $this->formatAndWrap((string) $message, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function formatAndWrap(string $message, int $width)
|
||||
{
|
||||
$offset = 0;
|
||||
$output = '';
|
||||
$tagRegex = '[a-z][a-z0-9,_=;-]*+';
|
||||
$currentLineLength = 0;
|
||||
preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
|
||||
foreach ($matches[0] as $i => $match) {
|
||||
$pos = $match[1];
|
||||
@@ -144,7 +153,7 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
}
|
||||
|
||||
// add the text up to the next tag
|
||||
$output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
|
||||
$output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
|
||||
$offset = $pos + \strlen($text);
|
||||
|
||||
// opening tag?
|
||||
@@ -158,7 +167,7 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
// </>
|
||||
$this->styleStack->pop();
|
||||
} elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
|
||||
$output .= $this->applyCurrentStyle($text);
|
||||
$output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength);
|
||||
} elseif ($open) {
|
||||
$this->styleStack->push($style);
|
||||
} else {
|
||||
@@ -166,7 +175,7 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
}
|
||||
}
|
||||
|
||||
$output .= $this->applyCurrentStyle(substr($message, $offset));
|
||||
$output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength);
|
||||
|
||||
if (false !== strpos($output, "\0")) {
|
||||
return strtr($output, array("\0" => '\\', '\\<' => '<'));
|
||||
@@ -223,8 +232,46 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
/**
|
||||
* Applies current style from stack to text, if must be applied.
|
||||
*/
|
||||
private function applyCurrentStyle(string $text): string
|
||||
private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength): string
|
||||
{
|
||||
return $this->isDecorated() && \strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
|
||||
if ('' === $text) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$width) {
|
||||
return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text;
|
||||
}
|
||||
|
||||
if (!$currentLineLength && '' !== $current) {
|
||||
$text = ltrim($text);
|
||||
}
|
||||
|
||||
if ($currentLineLength) {
|
||||
$prefix = substr($text, 0, $i = $width - $currentLineLength)."\n";
|
||||
$text = substr($text, $i);
|
||||
} else {
|
||||
$prefix = '';
|
||||
}
|
||||
|
||||
preg_match('~(\\n)$~', $text, $matches);
|
||||
$text = $prefix.preg_replace('~([^\\n]{'.$width.'})\\ *~', "\$1\n", $text);
|
||||
$text = rtrim($text, "\n").($matches[1] ?? '');
|
||||
|
||||
if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) {
|
||||
$text = "\n".$text;
|
||||
}
|
||||
|
||||
$lines = explode("\n", $text);
|
||||
if ($width === $currentLineLength = \strlen(end($lines))) {
|
||||
$currentLineLength = 0;
|
||||
}
|
||||
|
||||
if ($this->isDecorated()) {
|
||||
foreach ($lines as $i => $line) {
|
||||
$lines[$i] = $this->styleStack->getCurrent()->apply($line);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $lines);
|
||||
}
|
||||
}
|
||||
|
@@ -90,11 +90,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
||||
}
|
||||
|
||||
if (!isset(static::$availableForegroundColors[$color])) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid foreground color specified: "%s". Expected one of (%s)',
|
||||
$color,
|
||||
implode(', ', array_keys(static::$availableForegroundColors))
|
||||
));
|
||||
throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors))));
|
||||
}
|
||||
|
||||
$this->foreground = static::$availableForegroundColors[$color];
|
||||
@@ -116,11 +112,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
||||
}
|
||||
|
||||
if (!isset(static::$availableBackgroundColors[$color])) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid background color specified: "%s". Expected one of (%s)',
|
||||
$color,
|
||||
implode(', ', array_keys(static::$availableBackgroundColors))
|
||||
));
|
||||
throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors))));
|
||||
}
|
||||
|
||||
$this->background = static::$availableBackgroundColors[$color];
|
||||
@@ -136,11 +128,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
||||
public function setOption($option)
|
||||
{
|
||||
if (!isset(static::$availableOptions[$option])) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid option specified: "%s". Expected one of (%s)',
|
||||
$option,
|
||||
implode(', ', array_keys(static::$availableOptions))
|
||||
));
|
||||
throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
|
||||
}
|
||||
|
||||
if (!\in_array(static::$availableOptions[$option], $this->options)) {
|
||||
@@ -158,11 +146,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
||||
public function unsetOption($option)
|
||||
{
|
||||
if (!isset(static::$availableOptions[$option])) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid option specified: "%s". Expected one of (%s)',
|
||||
$option,
|
||||
implode(', ', array_keys(static::$availableOptions))
|
||||
));
|
||||
throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
|
||||
}
|
||||
|
||||
$pos = array_search(static::$availableOptions[$option], $this->options);
|
||||
|
@@ -12,11 +12,12 @@
|
||||
namespace Symfony\Component\Console\Formatter;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Contracts\Service\ResetInterface;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <contact@jfsimon.fr>
|
||||
*/
|
||||
class OutputFormatterStyleStack
|
||||
class OutputFormatterStyleStack implements ResetInterface
|
||||
{
|
||||
/**
|
||||
* @var OutputFormatterStyleInterface[]
|
||||
|
25
vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php
vendored
Normal file
25
vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console\Formatter;
|
||||
|
||||
/**
|
||||
* Formatter interface for console output that supports word wrapping.
|
||||
*
|
||||
* @author Roland Franssen <franssen.roland@gmail.com>
|
||||
*/
|
||||
interface WrappableOutputFormatterInterface extends OutputFormatterInterface
|
||||
{
|
||||
/**
|
||||
* Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping).
|
||||
*/
|
||||
public function formatAndWrap(string $message, int $width);
|
||||
}
|
33
vendor/symfony/console/Helper/ProcessHelper.php
vendored
33
vendor/symfony/console/Helper/ProcessHelper.php
vendored
@@ -20,18 +20,20 @@ use Symfony\Component\Process\Process;
|
||||
* The ProcessHelper class provides helpers to run external processes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since Symfony 4.2
|
||||
*/
|
||||
class ProcessHelper extends Helper
|
||||
{
|
||||
/**
|
||||
* Runs an external process.
|
||||
*
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @param string|array|Process $cmd An instance of Process or an array of arguments to escape and run or a command to run
|
||||
* @param string|null $error An error message that must be displayed if something went wrong
|
||||
* @param callable|null $callback A PHP callback to run whenever there is some
|
||||
* output available on STDOUT or STDERR
|
||||
* @param int $verbosity The threshold for verbosity
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @param array|Process $cmd An instance of Process or an array of the command and arguments
|
||||
* @param string|null $error An error message that must be displayed if something went wrong
|
||||
* @param callable|null $callback A PHP callback to run whenever there is some
|
||||
* output available on STDOUT or STDERR
|
||||
* @param int $verbosity The threshold for verbosity
|
||||
*
|
||||
* @return Process The process that ran
|
||||
*/
|
||||
@@ -44,9 +46,22 @@ class ProcessHelper extends Helper
|
||||
$formatter = $this->getHelperSet()->get('debug_formatter');
|
||||
|
||||
if ($cmd instanceof Process) {
|
||||
$process = $cmd;
|
||||
} else {
|
||||
$cmd = array($cmd);
|
||||
}
|
||||
|
||||
if (!\is_array($cmd)) {
|
||||
@trigger_error(sprintf('Passing a command as a string to "%s()" is deprecated since Symfony 4.2, pass it the command as an array of arguments instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
$cmd = array(\method_exists(Process::class, 'fromShellCommandline') ? Process::fromShellCommandline($cmd) : new Process($cmd));
|
||||
}
|
||||
|
||||
if (\is_string($cmd[0] ?? null)) {
|
||||
$process = new Process($cmd);
|
||||
$cmd = array();
|
||||
} elseif (($cmd[0] ?? null) instanceof Process) {
|
||||
$process = $cmd[0];
|
||||
unset($cmd[0]);
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid command provided to "%s()": the command should an array whose first is element is either the path to the binary to run of a "Process" object.', __METHOD__));
|
||||
}
|
||||
|
||||
if ($verbosity <= $output->getVerbosity()) {
|
||||
@@ -57,7 +72,7 @@ class ProcessHelper extends Helper
|
||||
$callback = $this->wrapCallback($output, $process, $callback);
|
||||
}
|
||||
|
||||
$process->run($callback);
|
||||
$process->run($callback, $cmd);
|
||||
|
||||
if ($verbosity <= $output->getVerbosity()) {
|
||||
$message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
|
||||
|
23
vendor/symfony/console/Helper/QuestionHelper.php
vendored
23
vendor/symfony/console/Helper/QuestionHelper.php
vendored
@@ -17,6 +17,7 @@ use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\StreamableInputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
@@ -46,13 +47,23 @@ class QuestionHelper extends Helper
|
||||
}
|
||||
|
||||
if (!$input->isInteractive()) {
|
||||
if ($question instanceof ChoiceQuestion) {
|
||||
$default = $question->getDefault();
|
||||
|
||||
if (null !== $default && $question instanceof ChoiceQuestion) {
|
||||
$choices = $question->getChoices();
|
||||
|
||||
return $choices[$question->getDefault()];
|
||||
if (!$question->isMultiselect()) {
|
||||
return isset($choices[$default]) ? $choices[$default] : $default;
|
||||
}
|
||||
|
||||
$default = explode(',', $default);
|
||||
foreach ($default as $k => $v) {
|
||||
$v = trim($v);
|
||||
$default[$k] = isset($choices[$v]) ? $choices[$v] : $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $question->getDefault();
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) {
|
||||
@@ -89,7 +100,7 @@ class QuestionHelper extends Helper
|
||||
/**
|
||||
* Asks the question to the user.
|
||||
*
|
||||
* @return bool|mixed|null|string
|
||||
* @return bool|mixed|string|null
|
||||
*
|
||||
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
|
||||
*/
|
||||
@@ -123,6 +134,10 @@ class QuestionHelper extends Helper
|
||||
$ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
|
||||
}
|
||||
|
||||
if ($output instanceof ConsoleSectionOutput) {
|
||||
$output->addContent($ret);
|
||||
}
|
||||
|
||||
$ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
|
||||
|
||||
if ($normalizer = $question->getNormalizer()) {
|
||||
|
@@ -58,7 +58,7 @@ class SymfonyQuestionHelper extends QuestionHelper
|
||||
|
||||
case $question instanceof ChoiceQuestion:
|
||||
$choices = $question->getChoices();
|
||||
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default]));
|
||||
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default));
|
||||
|
||||
break;
|
||||
|
||||
|
106
vendor/symfony/console/Helper/Table.php
vendored
106
vendor/symfony/console/Helper/Table.php
vendored
@@ -13,6 +13,7 @@ namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
@@ -34,6 +35,9 @@ class Table
|
||||
private const BORDER_OUTSIDE = 0;
|
||||
private const BORDER_INSIDE = 1;
|
||||
|
||||
private $headerTitle;
|
||||
private $footerTitle;
|
||||
|
||||
/**
|
||||
* Table headers.
|
||||
*/
|
||||
@@ -77,6 +81,7 @@ class Table
|
||||
* @var array
|
||||
*/
|
||||
private $columnWidths = array();
|
||||
private $columnMaxWidths = array();
|
||||
|
||||
private static $styles;
|
||||
|
||||
@@ -180,11 +185,7 @@ class Table
|
||||
*/
|
||||
public function getColumnStyle($columnIndex)
|
||||
{
|
||||
if (isset($this->columnStyles[$columnIndex])) {
|
||||
return $this->columnStyles[$columnIndex];
|
||||
}
|
||||
|
||||
return $this->getStyle();
|
||||
return $this->columnStyles[$columnIndex] ?? $this->getStyle();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,6 +220,25 @@ class Table
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum width of a column.
|
||||
*
|
||||
* Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while
|
||||
* formatted strings are preserved.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnMaxWidth(int $columnIndex, int $width): self
|
||||
{
|
||||
if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) {
|
||||
throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, \get_class($this->output->getFormatter())));
|
||||
}
|
||||
|
||||
$this->columnMaxWidths[$columnIndex] = $width;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
$headers = array_values($headers);
|
||||
@@ -290,19 +310,32 @@ class Table
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHeaderTitle(?string $title): self
|
||||
{
|
||||
$this->headerTitle = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setFooterTitle(?string $title): self
|
||||
{
|
||||
$this->footerTitle = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders table to output.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* +---------------+-----------------------+------------------+
|
||||
* | ISBN | Title | Author |
|
||||
* +---------------+-----------------------+------------------+
|
||||
* | 99921-58-10-7 | Divine Comedy | Dante Alighieri |
|
||||
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
|
||||
* | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
|
||||
* +---------------+-----------------------+------------------+
|
||||
* </code>
|
||||
*
|
||||
* +---------------+-----------------------+------------------+
|
||||
* | ISBN | Title | Author |
|
||||
* +---------------+-----------------------+------------------+
|
||||
* | 99921-58-10-7 | Divine Comedy | Dante Alighieri |
|
||||
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
|
||||
* | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
|
||||
* +---------------+-----------------------+------------------+
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
@@ -331,15 +364,17 @@ class Table
|
||||
}
|
||||
|
||||
if ($isHeader || $isFirstRow) {
|
||||
$this->renderRowSeparator($isFirstRow ? self::SEPARATOR_TOP_BOTTOM : self::SEPARATOR_TOP);
|
||||
if ($isFirstRow) {
|
||||
$this->renderRowSeparator(self::SEPARATOR_TOP_BOTTOM);
|
||||
$isFirstRow = false;
|
||||
} else {
|
||||
$this->renderRowSeparator(self::SEPARATOR_TOP, $this->headerTitle, $this->style->getHeaderTitleFormat());
|
||||
}
|
||||
}
|
||||
|
||||
$this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat());
|
||||
}
|
||||
$this->renderRowSeparator(self::SEPARATOR_BOTTOM);
|
||||
$this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat());
|
||||
|
||||
$this->cleanup();
|
||||
$this->rendered = true;
|
||||
@@ -348,9 +383,11 @@ class Table
|
||||
/**
|
||||
* Renders horizontal header separator.
|
||||
*
|
||||
* Example: <code>+-----+-----------+-------+</code>
|
||||
* Example:
|
||||
*
|
||||
* +-----+-----------+-------+
|
||||
*/
|
||||
private function renderRowSeparator(int $type = self::SEPARATOR_MID)
|
||||
private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null)
|
||||
{
|
||||
if (0 === $count = $this->numberOfColumns) {
|
||||
return;
|
||||
@@ -378,6 +415,23 @@ class Table
|
||||
$markup .= $column === $count - 1 ? $rightChar : $midChar;
|
||||
}
|
||||
|
||||
if (null !== $title) {
|
||||
$titleLength = Helper::strlenWithoutDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title));
|
||||
$markupLength = Helper::strlen($markup);
|
||||
if ($titleLength > $limit = $markupLength - 4) {
|
||||
$titleLength = $limit;
|
||||
$formatLength = Helper::strlenWithoutDecoration($formatter, sprintf($titleFormat, ''));
|
||||
$formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...');
|
||||
}
|
||||
|
||||
$titleStart = ($markupLength - $titleLength) / 2;
|
||||
if (false === mb_detect_encoding($markup, null, true)) {
|
||||
$markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength);
|
||||
} else {
|
||||
$markup = mb_substr($markup, 0, $titleStart).$formattedTitle.mb_substr($markup, $titleStart + $titleLength);
|
||||
}
|
||||
}
|
||||
|
||||
$this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
|
||||
}
|
||||
|
||||
@@ -394,7 +448,9 @@ class Table
|
||||
/**
|
||||
* Renders table row.
|
||||
*
|
||||
* Example: <code>| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |</code>
|
||||
* Example:
|
||||
*
|
||||
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
|
||||
*/
|
||||
private function renderRow(array $row, string $cellFormat)
|
||||
{
|
||||
@@ -458,12 +514,17 @@ class Table
|
||||
|
||||
private function buildTableRows($rows)
|
||||
{
|
||||
/** @var WrappableOutputFormatterInterface $formatter */
|
||||
$formatter = $this->output->getFormatter();
|
||||
$unmergedRows = array();
|
||||
for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
|
||||
$rows = $this->fillNextRows($rows, $rowKey);
|
||||
|
||||
// Remove any new line breaks and replace it with a new line
|
||||
foreach ($rows[$rowKey] as $column => $cell) {
|
||||
if (isset($this->columnMaxWidths[$column]) && Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) {
|
||||
$cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column]);
|
||||
}
|
||||
if (!strstr($cell, "\n")) {
|
||||
continue;
|
||||
}
|
||||
@@ -652,13 +713,13 @@ class Table
|
||||
$lengths[] = $this->getCellWidth($row, $column);
|
||||
}
|
||||
|
||||
$this->effectiveColumnWidths[$column] = max($lengths) + \strlen($this->style->getCellRowContentFormat()) - 2;
|
||||
$this->effectiveColumnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2;
|
||||
}
|
||||
}
|
||||
|
||||
private function getColumnSeparatorWidth(): int
|
||||
{
|
||||
return \strlen(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3]));
|
||||
return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3]));
|
||||
}
|
||||
|
||||
private function getCellWidth(array $row, int $column): int
|
||||
@@ -671,8 +732,9 @@ class Table
|
||||
}
|
||||
|
||||
$columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0;
|
||||
$cellWidth = max($cellWidth, $columnWidth);
|
||||
|
||||
return max($cellWidth, $columnWidth);
|
||||
return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
|
28
vendor/symfony/console/Helper/TableStyle.php
vendored
28
vendor/symfony/console/Helper/TableStyle.php
vendored
@@ -40,6 +40,8 @@ class TableStyle
|
||||
private $crossingTopLeftBottomChar = '+';
|
||||
private $crossingTopMidBottomChar = '+';
|
||||
private $crossingTopRightBottomChar = '+';
|
||||
private $headerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
|
||||
private $footerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
|
||||
private $cellHeaderFormat = '<info>%s</info>';
|
||||
private $cellRowFormat = '%s';
|
||||
private $cellRowContentFormat = ' %s ';
|
||||
@@ -276,7 +278,7 @@ class TableStyle
|
||||
/**
|
||||
* Gets crossing character.
|
||||
*
|
||||
* @return string $crossingChar
|
||||
* @return string
|
||||
*/
|
||||
public function getCrossingChar()
|
||||
{
|
||||
@@ -429,4 +431,28 @@ class TableStyle
|
||||
{
|
||||
return $this->padType;
|
||||
}
|
||||
|
||||
public function getHeaderTitleFormat(): string
|
||||
{
|
||||
return $this->headerTitleFormat;
|
||||
}
|
||||
|
||||
public function setHeaderTitleFormat(string $format): self
|
||||
{
|
||||
$this->headerTitleFormat = $format;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFooterTitleFormat(): string
|
||||
{
|
||||
return $this->footerTitleFormat;
|
||||
}
|
||||
|
||||
public function setFooterTitleFormat(string $format): self
|
||||
{
|
||||
$this->footerTitleFormat = $format;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
3
vendor/symfony/console/Input/ArgvInput.php
vendored
3
vendor/symfony/console/Input/ArgvInput.php
vendored
@@ -121,7 +121,8 @@ class ArgvInput extends Input
|
||||
$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]));
|
||||
$encoding = mb_detect_encoding($name, null, true);
|
||||
throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding)));
|
||||
}
|
||||
|
||||
$option = $this->definition->getOptionForShortcut($name[$i]);
|
||||
|
12
vendor/symfony/console/Input/InputArgument.php
vendored
12
vendor/symfony/console/Input/InputArgument.php
vendored
@@ -31,10 +31,10 @@ class InputArgument
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @param string $name The argument name
|
||||
* @param int $mode The argument mode: self::REQUIRED or self::OPTIONAL
|
||||
* @param string $description A description text
|
||||
* @param mixed $default The default value (for self::OPTIONAL mode only)
|
||||
* @param string $name The argument name
|
||||
* @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL
|
||||
* @param string $description A description text
|
||||
* @param string|string[]|null $default The default value (for self::OPTIONAL mode only)
|
||||
*
|
||||
* @throws InvalidArgumentException When argument mode is not valid
|
||||
*/
|
||||
@@ -86,7 +86,7 @@ class InputArgument
|
||||
/**
|
||||
* Sets the default value.
|
||||
*
|
||||
* @param mixed $default The default value
|
||||
* @param string|string[]|null $default The default value
|
||||
*
|
||||
* @throws LogicException When incorrect default value is given
|
||||
*/
|
||||
@@ -110,7 +110,7 @@ class InputArgument
|
||||
/**
|
||||
* Returns the default value.
|
||||
*
|
||||
* @return mixed The default value
|
||||
* @return string|string[]|null The default value
|
||||
*/
|
||||
public function getDefault()
|
||||
{
|
||||
|
@@ -21,8 +21,6 @@ interface InputAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the Console Input.
|
||||
*
|
||||
* @param InputInterface
|
||||
*/
|
||||
public function setInput(InputInterface $input);
|
||||
}
|
||||
|
@@ -20,8 +20,8 @@ use Symfony\Component\Console\Exception\LogicException;
|
||||
* Usage:
|
||||
*
|
||||
* $definition = new InputDefinition(array(
|
||||
* new InputArgument('name', InputArgument::REQUIRED),
|
||||
* new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
|
||||
* new InputArgument('name', InputArgument::REQUIRED),
|
||||
* new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
|
||||
* ));
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
|
14
vendor/symfony/console/Input/InputInterface.php
vendored
14
vendor/symfony/console/Input/InputInterface.php
vendored
@@ -61,6 +61,8 @@ interface InputInterface
|
||||
|
||||
/**
|
||||
* Binds the current Input instance with the given arguments and options.
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function bind(InputDefinition $definition);
|
||||
|
||||
@@ -83,7 +85,7 @@ interface InputInterface
|
||||
*
|
||||
* @param string $name The argument name
|
||||
*
|
||||
* @return mixed The argument value
|
||||
* @return string|string[]|null The argument value
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
*/
|
||||
@@ -92,8 +94,8 @@ interface InputInterface
|
||||
/**
|
||||
* Sets an argument value by name.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
* @param string $value The argument value
|
||||
* @param string $name The argument name
|
||||
* @param string|string[]|null $value The argument value
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
*/
|
||||
@@ -120,7 +122,7 @@ interface InputInterface
|
||||
*
|
||||
* @param string $name The option name
|
||||
*
|
||||
* @return mixed The option value
|
||||
* @return string|string[]|bool|null The option value
|
||||
*
|
||||
* @throws InvalidArgumentException When option given doesn't exist
|
||||
*/
|
||||
@@ -129,8 +131,8 @@ interface InputInterface
|
||||
/**
|
||||
* Sets an option value by name.
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @param string|bool $value The option value
|
||||
* @param string $name The option name
|
||||
* @param string|string[]|bool|null $value The option value
|
||||
*
|
||||
* @throws InvalidArgumentException When option given doesn't exist
|
||||
*/
|
||||
|
14
vendor/symfony/console/Input/InputOption.php
vendored
14
vendor/symfony/console/Input/InputOption.php
vendored
@@ -33,11 +33,11 @@ class InputOption
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @param string $name The option name
|
||||
* @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
|
||||
* @param int $mode The option mode: One of the VALUE_* constants
|
||||
* @param string $description A description text
|
||||
* @param mixed $default The default value (must be null for self::VALUE_NONE)
|
||||
* @param string $name The option name
|
||||
* @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
|
||||
* @param int|null $mode The option mode: One of the VALUE_* constants
|
||||
* @param string $description A description text
|
||||
* @param string|string[]|int|bool|null $default The default value (must be null for self::VALUE_NONE)
|
||||
*
|
||||
* @throws InvalidArgumentException If option mode is invalid or incompatible
|
||||
*/
|
||||
@@ -149,7 +149,7 @@ class InputOption
|
||||
/**
|
||||
* Sets the default value.
|
||||
*
|
||||
* @param mixed $default The default value
|
||||
* @param string|string[]|int|bool|null $default The default value
|
||||
*
|
||||
* @throws LogicException When incorrect default value is given
|
||||
*/
|
||||
@@ -173,7 +173,7 @@ class InputOption
|
||||
/**
|
||||
* Returns the default value.
|
||||
*
|
||||
* @return mixed The default value
|
||||
* @return string|string[]|int|bool|null The default value
|
||||
*/
|
||||
public function getDefault()
|
||||
{
|
||||
|
@@ -77,6 +77,18 @@ class ConsoleSectionOutput extends StreamOutput
|
||||
return implode('', $this->content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function addContent(string $input)
|
||||
{
|
||||
foreach (explode(PHP_EOL, $input) as $lineContent) {
|
||||
$this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1;
|
||||
$this->content[] = $lineContent;
|
||||
$this->content[] = PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -88,11 +100,7 @@ class ConsoleSectionOutput extends StreamOutput
|
||||
|
||||
$erasedContent = $this->popStreamContentUntilCurrentSection();
|
||||
|
||||
foreach (explode(PHP_EOL, $message) as $lineContent) {
|
||||
$this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1;
|
||||
$this->content[] = $lineContent;
|
||||
$this->content[] = PHP_EOL;
|
||||
}
|
||||
$this->addContent($message);
|
||||
|
||||
parent::doWrite($message, true);
|
||||
parent::doWrite($erasedContent, false);
|
||||
|
10
vendor/symfony/console/Output/StreamOutput.php
vendored
10
vendor/symfony/console/Output/StreamOutput.php
vendored
@@ -20,11 +20,11 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $output = new StreamOutput(fopen('php://stdout', 'w'));
|
||||
* $output = new StreamOutput(fopen('php://stdout', 'w'));
|
||||
*
|
||||
* As `StreamOutput` can use any stream, you can also use a file:
|
||||
*
|
||||
* $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
|
||||
* $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
@@ -70,7 +70,11 @@ class StreamOutput extends Output
|
||||
*/
|
||||
protected function doWrite($message, $newline)
|
||||
{
|
||||
if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
|
||||
if ($newline) {
|
||||
$message .= PHP_EOL;
|
||||
}
|
||||
|
||||
if (false === @fwrite($this->stream, $message)) {
|
||||
// should never happen
|
||||
throw new RuntimeException('Unable to write output.');
|
||||
}
|
||||
|
14
vendor/symfony/console/Question/Question.php
vendored
14
vendor/symfony/console/Question/Question.php
vendored
@@ -117,7 +117,7 @@ class Question
|
||||
/**
|
||||
* Gets values for the autocompleter.
|
||||
*
|
||||
* @return null|iterable
|
||||
* @return iterable|null
|
||||
*/
|
||||
public function getAutocompleterValues()
|
||||
{
|
||||
@@ -127,7 +127,7 @@ class Question
|
||||
/**
|
||||
* Sets values for the autocompleter.
|
||||
*
|
||||
* @param null|iterable $values
|
||||
* @param iterable|null $values
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
@@ -141,7 +141,7 @@ class Question
|
||||
}
|
||||
|
||||
if (null !== $values && !\is_array($values) && !$values instanceof \Traversable) {
|
||||
throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
|
||||
throw new InvalidArgumentException('Autocompleter values can be either an array, "null" or a "Traversable" object.');
|
||||
}
|
||||
|
||||
if ($this->hidden) {
|
||||
@@ -156,7 +156,7 @@ class Question
|
||||
/**
|
||||
* Sets a validator for the question.
|
||||
*
|
||||
* @param null|callable $validator
|
||||
* @param callable|null $validator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -170,7 +170,7 @@ class Question
|
||||
/**
|
||||
* Gets the validator for the question.
|
||||
*
|
||||
* @return null|callable
|
||||
* @return callable|null
|
||||
*/
|
||||
public function getValidator()
|
||||
{
|
||||
@@ -182,7 +182,7 @@ class Question
|
||||
*
|
||||
* Null means an unlimited number of attempts.
|
||||
*
|
||||
* @param null|int $attempts
|
||||
* @param int|null $attempts
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
@@ -204,7 +204,7 @@ class Question
|
||||
*
|
||||
* Null means an unlimited number of attempts.
|
||||
*
|
||||
* @return null|int
|
||||
* @return int|null
|
||||
*/
|
||||
public function getMaxAttempts()
|
||||
{
|
||||
|
@@ -13,8 +13,6 @@ namespace Symfony\Component\Console\Tester;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Output\StreamOutput;
|
||||
|
||||
/**
|
||||
* Eases the testing of console applications.
|
||||
@@ -33,7 +31,6 @@ class ApplicationTester
|
||||
private $application;
|
||||
private $input;
|
||||
private $statusCode;
|
||||
private $captureStreamsIndependently = false;
|
||||
|
||||
public function __construct(Application $application)
|
||||
{
|
||||
@@ -69,36 +66,7 @@ class ApplicationTester
|
||||
putenv('SHELL_INTERACTIVE=1');
|
||||
}
|
||||
|
||||
$this->captureStreamsIndependently = array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately'];
|
||||
if (!$this->captureStreamsIndependently) {
|
||||
$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']);
|
||||
}
|
||||
} else {
|
||||
$this->output = new ConsoleOutput(
|
||||
isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL,
|
||||
isset($options['decorated']) ? $options['decorated'] : null
|
||||
);
|
||||
|
||||
$errorOutput = new StreamOutput(fopen('php://memory', 'w', false));
|
||||
$errorOutput->setFormatter($this->output->getFormatter());
|
||||
$errorOutput->setVerbosity($this->output->getVerbosity());
|
||||
$errorOutput->setDecorated($this->output->isDecorated());
|
||||
|
||||
$reflectedOutput = new \ReflectionObject($this->output);
|
||||
$strErrProperty = $reflectedOutput->getProperty('stderr');
|
||||
$strErrProperty->setAccessible(true);
|
||||
$strErrProperty->setValue($this->output, $errorOutput);
|
||||
|
||||
$reflectedParent = $reflectedOutput->getParentClass();
|
||||
$streamProperty = $reflectedParent->getProperty('stream');
|
||||
$streamProperty->setAccessible(true);
|
||||
$streamProperty->setValue($this->output, fopen('php://memory', 'w', false));
|
||||
}
|
||||
$this->initOutput($options);
|
||||
|
||||
$this->statusCode = $this->application->run($this->input, $this->output);
|
||||
|
||||
@@ -106,28 +74,4 @@ class ApplicationTester
|
||||
|
||||
return $this->statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output written to STDERR by the application.
|
||||
*
|
||||
* @param bool $normalize Whether to normalize end of lines to \n or not
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorOutput($normalize = false)
|
||||
{
|
||||
if (!$this->captureStreamsIndependently) {
|
||||
throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
|
||||
}
|
||||
|
||||
rewind($this->output->getErrorOutput()->getStream());
|
||||
|
||||
$display = stream_get_contents($this->output->getErrorOutput()->getStream());
|
||||
|
||||
if ($normalize) {
|
||||
$display = str_replace(PHP_EOL, "\n", $display);
|
||||
}
|
||||
|
||||
return $display;
|
||||
}
|
||||
}
|
||||
|
16
vendor/symfony/console/Tester/CommandTester.php
vendored
16
vendor/symfony/console/Tester/CommandTester.php
vendored
@@ -13,7 +13,6 @@ namespace Symfony\Component\Console\Tester;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Output\StreamOutput;
|
||||
|
||||
/**
|
||||
* Eases the testing of console commands.
|
||||
@@ -39,9 +38,10 @@ class CommandTester
|
||||
*
|
||||
* Available execution options:
|
||||
*
|
||||
* * interactive: Sets the input interactive flag
|
||||
* * decorated: Sets the output decorated flag
|
||||
* * verbosity: Sets the output verbosity flag
|
||||
* * interactive: Sets the input interactive flag
|
||||
* * decorated: Sets the output decorated flag
|
||||
* * verbosity: Sets the output verbosity flag
|
||||
* * capture_stderr_separately: Make output of stdOut and stdErr separately available
|
||||
*
|
||||
* @param array $input An array of command arguments and options
|
||||
* @param array $options An array of execution options
|
||||
@@ -68,12 +68,12 @@ class CommandTester
|
||||
$this->input->setInteractive($options['interactive']);
|
||||
}
|
||||
|
||||
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
|
||||
$this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
|
||||
if (isset($options['verbosity'])) {
|
||||
$this->output->setVerbosity($options['verbosity']);
|
||||
if (!isset($options['decorated'])) {
|
||||
$options['decorated'] = false;
|
||||
}
|
||||
|
||||
$this->initOutput($options);
|
||||
|
||||
return $this->statusCode = $this->command->run($this->input, $this->output);
|
||||
}
|
||||
}
|
||||
|
75
vendor/symfony/console/Tester/TesterTrait.php
vendored
75
vendor/symfony/console/Tester/TesterTrait.php
vendored
@@ -12,19 +12,19 @@
|
||||
namespace Symfony\Component\Console\Tester;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\StreamOutput;
|
||||
|
||||
/**
|
||||
* @author Amrouche Hamza <hamza.simperfit@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
trait TesterTrait
|
||||
{
|
||||
/** @var StreamOutput */
|
||||
private $output;
|
||||
private $inputs = array();
|
||||
private $captureStreamsIndependently = false;
|
||||
|
||||
/**
|
||||
* Gets the display returned by the last execution of the command or application.
|
||||
@@ -46,6 +46,30 @@ trait TesterTrait
|
||||
return $display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output written to STDERR by the application.
|
||||
*
|
||||
* @param bool $normalize Whether to normalize end of lines to \n or not
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorOutput($normalize = false)
|
||||
{
|
||||
if (!$this->captureStreamsIndependently) {
|
||||
throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
|
||||
}
|
||||
|
||||
rewind($this->output->getErrorOutput()->getStream());
|
||||
|
||||
$display = stream_get_contents($this->output->getErrorOutput()->getStream());
|
||||
|
||||
if ($normalize) {
|
||||
$display = str_replace(PHP_EOL, "\n", $display);
|
||||
}
|
||||
|
||||
return $display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input instance used by the last execution of the command or application.
|
||||
*
|
||||
@@ -79,8 +103,8 @@ trait TesterTrait
|
||||
/**
|
||||
* Sets the user inputs.
|
||||
*
|
||||
* @param $inputs array An array of strings representing each input
|
||||
* passed to the command input stream
|
||||
* @param array $inputs An array of strings representing each input
|
||||
* passed to the command input stream
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
@@ -91,6 +115,49 @@ trait TesterTrait
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the output property.
|
||||
*
|
||||
* Available options:
|
||||
*
|
||||
* * decorated: Sets the output decorated flag
|
||||
* * verbosity: Sets the output verbosity flag
|
||||
* * capture_stderr_separately: Make output of stdOut and stdErr separately available
|
||||
*/
|
||||
private function initOutput(array $options)
|
||||
{
|
||||
$this->captureStreamsIndependently = array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately'];
|
||||
if (!$this->captureStreamsIndependently) {
|
||||
$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']);
|
||||
}
|
||||
} else {
|
||||
$this->output = new ConsoleOutput(
|
||||
isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL,
|
||||
isset($options['decorated']) ? $options['decorated'] : null
|
||||
);
|
||||
|
||||
$errorOutput = new StreamOutput(fopen('php://memory', 'w', false));
|
||||
$errorOutput->setFormatter($this->output->getFormatter());
|
||||
$errorOutput->setVerbosity($this->output->getVerbosity());
|
||||
$errorOutput->setDecorated($this->output->isDecorated());
|
||||
|
||||
$reflectedOutput = new \ReflectionObject($this->output);
|
||||
$strErrProperty = $reflectedOutput->getProperty('stderr');
|
||||
$strErrProperty->setAccessible(true);
|
||||
$strErrProperty->setValue($this->output, $errorOutput);
|
||||
|
||||
$reflectedParent = $reflectedOutput->getParentClass();
|
||||
$streamProperty = $reflectedParent->getProperty('stream');
|
||||
$streamProperty->setAccessible(true);
|
||||
$streamProperty->setValue($this->output, fopen('php://memory', 'w', false));
|
||||
}
|
||||
}
|
||||
|
||||
private static function createStream(array $inputs)
|
||||
{
|
||||
$stream = fopen('php://memory', 'r+', false);
|
||||
|
98
vendor/symfony/console/Tests/ApplicationTest.php
vendored
98
vendor/symfony/console/Tests/ApplicationTest.php
vendored
@@ -824,6 +824,56 @@ class ApplicationTest extends TestCase
|
||||
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_linebreaks.txt', $tester->getDisplay(true), '->renderException() keep multiple line breaks');
|
||||
}
|
||||
|
||||
public function testRenderAnonymousException()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->register('foo')->setCode(function () {
|
||||
throw new class('') extends \InvalidArgumentException {
|
||||
};
|
||||
});
|
||||
$tester = new ApplicationTester($application);
|
||||
|
||||
$tester->run(array('command' => 'foo'), array('decorated' => false));
|
||||
$this->assertContains('[InvalidArgumentException@anonymous]', $tester->getDisplay(true));
|
||||
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->register('foo')->setCode(function () {
|
||||
throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', \get_class(new class() {
|
||||
})));
|
||||
});
|
||||
$tester = new ApplicationTester($application);
|
||||
|
||||
$tester->run(array('command' => 'foo'), array('decorated' => false));
|
||||
$this->assertContains('Dummy type "@anonymous" is invalid.', $tester->getDisplay(true));
|
||||
}
|
||||
|
||||
public function testRenderExceptionStackTraceContainsRootException()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->register('foo')->setCode(function () {
|
||||
throw new class('') extends \InvalidArgumentException {
|
||||
};
|
||||
});
|
||||
$tester = new ApplicationTester($application);
|
||||
|
||||
$tester->run(array('command' => 'foo'), array('decorated' => false));
|
||||
$this->assertContains('[InvalidArgumentException@anonymous]', $tester->getDisplay(true));
|
||||
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->register('foo')->setCode(function () {
|
||||
throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', \get_class(new class() {
|
||||
})));
|
||||
});
|
||||
$tester = new ApplicationTester($application);
|
||||
|
||||
$tester->run(array('command' => 'foo'), array('decorated' => false));
|
||||
$this->assertContains('Dummy type "@anonymous" is invalid.', $tester->getDisplay(true));
|
||||
}
|
||||
|
||||
public function testRun()
|
||||
{
|
||||
$application = new Application();
|
||||
@@ -960,6 +1010,30 @@ class ApplicationTest extends TestCase
|
||||
$this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception');
|
||||
}
|
||||
|
||||
public function testRunDispatchesIntegerExitCode()
|
||||
{
|
||||
$passedRightValue = false;
|
||||
|
||||
// We can assume here that some other test asserts that the event is dispatched at all
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use (&$passedRightValue) {
|
||||
$passedRightValue = (4 === $event->getExitCode());
|
||||
});
|
||||
|
||||
$application = new Application();
|
||||
$application->setDispatcher($dispatcher);
|
||||
$application->setAutoExit(false);
|
||||
|
||||
$application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) {
|
||||
throw new \Exception('', 4);
|
||||
});
|
||||
|
||||
$tester = new ApplicationTester($application);
|
||||
$tester->run(array('command' => 'test'));
|
||||
|
||||
$this->assertTrue($passedRightValue, '-> exit code 4 was passed in the console.terminate event');
|
||||
}
|
||||
|
||||
public function testRunReturnsExitCodeOneForExceptionCodeZero()
|
||||
{
|
||||
$exception = new \Exception('', 0);
|
||||
@@ -975,6 +1049,30 @@ class ApplicationTest extends TestCase
|
||||
$this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0');
|
||||
}
|
||||
|
||||
public function testRunDispatchesExitCodeOneForExceptionCodeZero()
|
||||
{
|
||||
$passedRightValue = false;
|
||||
|
||||
// We can assume here that some other test asserts that the event is dispatched at all
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use (&$passedRightValue) {
|
||||
$passedRightValue = (1 === $event->getExitCode());
|
||||
});
|
||||
|
||||
$application = new Application();
|
||||
$application->setDispatcher($dispatcher);
|
||||
$application->setAutoExit(false);
|
||||
|
||||
$application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) {
|
||||
throw new \Exception();
|
||||
});
|
||||
|
||||
$tester = new ApplicationTester($application);
|
||||
$tester->run(array('command' => 'test'));
|
||||
|
||||
$this->assertTrue($passedRightValue, '-> exit code 1 was passed in the console.terminate event');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage An option with shortcut "e" already exists.
|
||||
|
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
class Foo6Command extends Command
|
||||
|
@@ -322,6 +322,25 @@ more text
|
||||
EOF
|
||||
));
|
||||
}
|
||||
|
||||
public function testFormatAndWrap()
|
||||
{
|
||||
$formatter = new OutputFormatter(true);
|
||||
|
||||
$this->assertSame("fo\no\e[37;41mb\e[39;49m\n\e[37;41mar\e[39;49m\nba\nz", $formatter->formatAndWrap('foo<error>bar</error> baz', 2));
|
||||
$this->assertSame("pr\ne \e[37;41m\e[39;49m\n\e[37;41mfo\e[39;49m\n\e[37;41mo \e[39;49m\n\e[37;41mba\e[39;49m\n\e[37;41mr \e[39;49m\n\e[37;41mba\e[39;49m\n\e[37;41mz\e[39;49m \npo\nst", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 2));
|
||||
$this->assertSame("pre\e[37;41m\e[39;49m\n\e[37;41mfoo\e[39;49m\n\e[37;41mbar\e[39;49m\n\e[37;41mbaz\e[39;49m\npos\nt", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 3));
|
||||
$this->assertSame("pre \e[37;41m\e[39;49m\n\e[37;41mfoo \e[39;49m\n\e[37;41mbar \e[39;49m\n\e[37;41mbaz\e[39;49m \npost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 4));
|
||||
$this->assertSame("pre \e[37;41mf\e[39;49m\n\e[37;41moo ba\e[39;49m\n\e[37;41mr baz\e[39;49m\npost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 5));
|
||||
|
||||
$formatter = new OutputFormatter();
|
||||
|
||||
$this->assertSame("fo\nob\nar\nba\nz", $formatter->formatAndWrap('foo<error>bar</error> baz', 2));
|
||||
$this->assertSame("pr\ne \nfo\no \nba\nr \nba\nz \npo\nst", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 2));
|
||||
$this->assertSame("pre\nfoo\nbar\nbaz\npos\nt", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 3));
|
||||
$this->assertSame("pre \nfoo \nbar \nbaz \npost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 4));
|
||||
$this->assertSame("pre f\noo ba\nr baz\npost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 5));
|
||||
}
|
||||
}
|
||||
|
||||
class TableCell
|
||||
|
@@ -25,6 +25,10 @@ class ProcessHelperTest extends TestCase
|
||||
*/
|
||||
public function testVariousProcessRuns($expected, $cmd, $verbosity, $error)
|
||||
{
|
||||
if (\is_string($cmd)) {
|
||||
$cmd = \method_exists(Process::class, 'fromShellCommandline') ? Process::fromShellCommandline($cmd) : new Process($cmd);
|
||||
}
|
||||
|
||||
$helper = new ProcessHelper();
|
||||
$helper->setHelperSet(new HelperSet(array(new DebugFormatterHelper())));
|
||||
$output = $this->getOutputStream($verbosity);
|
||||
@@ -41,7 +45,7 @@ class ProcessHelperTest extends TestCase
|
||||
$executed = false;
|
||||
$callback = function () use (&$executed) { $executed = true; };
|
||||
|
||||
$helper->run($output, 'php -r "echo 42;"', null, $callback);
|
||||
$helper->run($output, array('php', '-r', 'echo 42;'), null, $callback);
|
||||
$this->assertTrue($executed);
|
||||
}
|
||||
|
||||
@@ -81,12 +85,21 @@ EOT;
|
||||
OUT out message
|
||||
RES 252 Command did not run successfully
|
||||
|
||||
EOT;
|
||||
|
||||
$PHP = '\\' === \DIRECTORY_SEPARATOR ? '"!PHP!"' : '"$PHP"';
|
||||
$successOutputPhp = <<<EOT
|
||||
RUN php -r $PHP
|
||||
OUT 42
|
||||
RES Command ran successfully
|
||||
|
||||
EOT;
|
||||
|
||||
$errorMessage = 'An error occurred';
|
||||
$args = new Process(array('php', '-r', 'echo 42;'));
|
||||
$args = $args->getCommandLine();
|
||||
$successOutputProcessDebug = str_replace("'php' '-r' 'echo 42;'", $args, $successOutputProcessDebug);
|
||||
$fromShellCommandline = \method_exists(Process::class, 'fromShellCommandline') ? array(Process::class, 'fromShellCommandline') : function ($cmd) { return new Process($cmd); };
|
||||
|
||||
return array(
|
||||
array('', 'php -r "echo 42;"', StreamOutput::VERBOSITY_VERBOSE, null),
|
||||
@@ -100,7 +113,9 @@ EOT;
|
||||
array($syntaxErrorOutputVerbose.$errorMessage.PHP_EOL, 'php -r "fwrite(STDERR, \'error message\');usleep(50000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_VERY_VERBOSE, $errorMessage),
|
||||
array($syntaxErrorOutputDebug.$errorMessage.PHP_EOL, 'php -r "fwrite(STDERR, \'error message\');usleep(500000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_DEBUG, $errorMessage),
|
||||
array($successOutputProcessDebug, array('php', '-r', 'echo 42;'), StreamOutput::VERBOSITY_DEBUG, null),
|
||||
array($successOutputDebug, new Process('php -r "echo 42;"'), StreamOutput::VERBOSITY_DEBUG, null),
|
||||
array($successOutputDebug, $fromShellCommandline('php -r "echo 42;"'), StreamOutput::VERBOSITY_DEBUG, null),
|
||||
array($successOutputProcessDebug, array(new Process(array('php', '-r', 'echo 42;'))), StreamOutput::VERBOSITY_DEBUG, null),
|
||||
array($successOutputPhp, array($fromShellCommandline('php -r '.$PHP), 'PHP' => 'echo 42;'), StreamOutput::VERBOSITY_DEBUG, null),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -89,6 +89,63 @@ class QuestionHelperTest extends AbstractQuestionHelperTest
|
||||
$this->assertEquals('Superman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, true), $this->createOutputInterface(), $question));
|
||||
}
|
||||
|
||||
public function testAskChoiceNonInteractive()
|
||||
{
|
||||
$questionHelper = new QuestionHelper();
|
||||
|
||||
$helperSet = new HelperSet(array(new FormatterHelper()));
|
||||
$questionHelper->setHelperSet($helperSet);
|
||||
$inputStream = $this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n");
|
||||
|
||||
$heroes = array('Superman', 'Batman', 'Spiderman');
|
||||
|
||||
$question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0');
|
||||
|
||||
$this->assertSame('Superman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question));
|
||||
|
||||
$question = new ChoiceQuestion('What is your favorite superhero?', $heroes, 'Batman');
|
||||
$this->assertSame('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question));
|
||||
|
||||
$question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null);
|
||||
$this->assertNull($questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question));
|
||||
|
||||
$question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0');
|
||||
$question->setValidator(null);
|
||||
$this->assertSame('Superman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question));
|
||||
|
||||
try {
|
||||
$question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null);
|
||||
$questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$this->assertSame('Value "" is invalid', $e->getMessage());
|
||||
}
|
||||
|
||||
$question = new ChoiceQuestion('Who are your favorite superheros?', $heroes, '0, 1');
|
||||
$question->setMultiselect(true);
|
||||
$this->assertSame(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question));
|
||||
|
||||
$question = new ChoiceQuestion('Who are your favorite superheros?', $heroes, '0, 1');
|
||||
$question->setMultiselect(true);
|
||||
$question->setValidator(null);
|
||||
$this->assertSame(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question));
|
||||
|
||||
$question = new ChoiceQuestion('Who are your favorite superheros?', $heroes, '0, Batman');
|
||||
$question->setMultiselect(true);
|
||||
$this->assertSame(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question));
|
||||
|
||||
$question = new ChoiceQuestion('Who are your favorite superheros?', $heroes, null);
|
||||
$question->setMultiselect(true);
|
||||
$this->assertNull($questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question));
|
||||
|
||||
try {
|
||||
$question = new ChoiceQuestion('Who are your favorite superheros?', $heroes, '');
|
||||
$question->setMultiselect(true);
|
||||
$questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, false), $this->createOutputInterface(), $question);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$this->assertSame('Value "" is invalid', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testAsk()
|
||||
{
|
||||
$dialog = new QuestionHelper();
|
||||
|
@@ -74,6 +74,18 @@ class SymfonyQuestionHelperTest extends AbstractQuestionHelperTest
|
||||
$this->assertOutputContains('What is your favorite superhero? [Superman, Batman]', $output);
|
||||
}
|
||||
|
||||
public function testAskChoiceWithChoiceValueAsDefault()
|
||||
{
|
||||
$questionHelper = new SymfonyQuestionHelper();
|
||||
$helperSet = new HelperSet(array(new FormatterHelper()));
|
||||
$questionHelper->setHelperSet($helperSet);
|
||||
$question = new ChoiceQuestion('What is your favorite superhero?', array('Superman', 'Batman', 'Spiderman'), 'Batman');
|
||||
$question->setMaxAttempts(1);
|
||||
|
||||
$this->assertSame('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($this->getInputStream("Batman\n")), $output = $this->createOutputInterface(), $question));
|
||||
$this->assertOutputContains('What is your favorite superhero? [Batman]', $output);
|
||||
}
|
||||
|
||||
public function testAskReturnsNullIfValidatorAllowsIt()
|
||||
{
|
||||
$questionHelper = new SymfonyQuestionHelper();
|
||||
|
143
vendor/symfony/console/Tests/Helper/TableTest.php
vendored
143
vendor/symfony/console/Tests/Helper/TableTest.php
vendored
@@ -783,7 +783,7 @@ TABLE;
|
||||
$table->render();
|
||||
}
|
||||
|
||||
public function testColumnWith()
|
||||
public function testColumnWidth()
|
||||
{
|
||||
$table = new Table($output = $this->getOutputStream());
|
||||
$table
|
||||
@@ -815,7 +815,7 @@ TABLE;
|
||||
$this->assertEquals($expected, $this->getOutputContent($output));
|
||||
}
|
||||
|
||||
public function testColumnWiths()
|
||||
public function testColumnWidths()
|
||||
{
|
||||
$table = new Table($output = $this->getOutputStream());
|
||||
$table
|
||||
@@ -974,6 +974,145 @@ TABLE;
|
||||
Table::getStyleDefinition('absent');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider renderSetTitle
|
||||
*/
|
||||
public function testSetTitle($headerTitle, $footerTitle, $style, $expected)
|
||||
{
|
||||
(new Table($output = $this->getOutputStream()))
|
||||
->setHeaderTitle($headerTitle)
|
||||
->setFooterTitle($footerTitle)
|
||||
->setHeaders(array('ISBN', 'Title', 'Author'))
|
||||
->setRows(array(
|
||||
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
|
||||
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
|
||||
array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
|
||||
array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
|
||||
))
|
||||
->setStyle($style)
|
||||
->render()
|
||||
;
|
||||
|
||||
$this->assertEquals($expected, $this->getOutputContent($output));
|
||||
}
|
||||
|
||||
public function renderSetTitle()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'Books',
|
||||
'Page 1/2',
|
||||
'default',
|
||||
<<<'TABLE'
|
||||
+---------------+----------- Books --------+------------------+
|
||||
| ISBN | Title | Author |
|
||||
+---------------+--------------------------+------------------+
|
||||
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
|
||||
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
|
||||
| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
|
||||
| 80-902734-1-6 | And Then There Were None | Agatha Christie |
|
||||
+---------------+--------- Page 1/2 -------+------------------+
|
||||
|
||||
TABLE
|
||||
),
|
||||
array(
|
||||
'Books',
|
||||
'Page 1/2',
|
||||
'box',
|
||||
<<<'TABLE'
|
||||
┌───────────────┬─────────── Books ────────┬──────────────────┐
|
||||
│ ISBN │ Title │ Author │
|
||||
├───────────────┼──────────────────────────┼──────────────────┤
|
||||
│ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri │
|
||||
│ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens │
|
||||
│ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien │
|
||||
│ 80-902734-1-6 │ And Then There Were None │ Agatha Christie │
|
||||
└───────────────┴───────── Page 1/2 ───────┴──────────────────┘
|
||||
|
||||
TABLE
|
||||
),
|
||||
array(
|
||||
'Boooooooooooooooooooooooooooooooooooooooooooooooooooooooks',
|
||||
'Page 1/999999999999999999999999999999999999999999999999999',
|
||||
'default',
|
||||
<<<'TABLE'
|
||||
+- Booooooooooooooooooooooooooooooooooooooooooooooooooooo... -+
|
||||
| ISBN | Title | Author |
|
||||
+---------------+--------------------------+------------------+
|
||||
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
|
||||
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
|
||||
| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
|
||||
| 80-902734-1-6 | And Then There Were None | Agatha Christie |
|
||||
+- Page 1/99999999999999999999999999999999999999999999999... -+
|
||||
|
||||
TABLE
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function testColumnMaxWidths()
|
||||
{
|
||||
$table = new Table($output = $this->getOutputStream());
|
||||
$table
|
||||
->setRows(array(
|
||||
array('Divine Comedy', 'A Tale of Two Cities', 'The Lord of the Rings', 'And Then There Were None'),
|
||||
))
|
||||
->setColumnMaxWidth(1, 5)
|
||||
->setColumnMaxWidth(2, 10)
|
||||
->setColumnMaxWidth(3, 15);
|
||||
|
||||
$table->render();
|
||||
|
||||
$expected =
|
||||
<<<TABLE
|
||||
+---------------+-------+------------+-----------------+
|
||||
| Divine Comedy | A Tal | The Lord o | And Then There |
|
||||
| | e of | f the Ring | Were None |
|
||||
| | Two C | s | |
|
||||
| | ities | | |
|
||||
+---------------+-------+------------+-----------------+
|
||||
|
||||
TABLE;
|
||||
|
||||
$this->assertEquals($expected, $this->getOutputContent($output));
|
||||
}
|
||||
|
||||
public function testBoxedStyleWithColspan()
|
||||
{
|
||||
$boxed = new TableStyle();
|
||||
$boxed
|
||||
->setHorizontalBorderChars('─')
|
||||
->setVerticalBorderChars('│')
|
||||
->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├')
|
||||
;
|
||||
|
||||
$table = new Table($output = $this->getOutputStream());
|
||||
$table->setStyle($boxed);
|
||||
$table
|
||||
->setHeaders(array('ISBN', 'Title', 'Author'))
|
||||
->setRows(array(
|
||||
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
|
||||
new TableSeparator(),
|
||||
array(new TableCell('This value spans 3 columns.', array('colspan' => 3))),
|
||||
))
|
||||
;
|
||||
$table->render();
|
||||
|
||||
$expected =
|
||||
<<<TABLE
|
||||
┌───────────────┬───────────────┬─────────────────┐
|
||||
│ ISBN │ Title │ Author │
|
||||
├───────────────┼───────────────┼─────────────────┤
|
||||
│ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri │
|
||||
├───────────────┼───────────────┼─────────────────┤
|
||||
│ This value spans 3 columns. │
|
||||
└───────────────┴───────────────┴─────────────────┘
|
||||
|
||||
TABLE;
|
||||
|
||||
$this->assertSame($expected, $this->getOutputContent($output));
|
||||
}
|
||||
|
||||
protected function getOutputStream($decorated = false)
|
||||
{
|
||||
return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, $decorated);
|
||||
|
@@ -246,6 +246,11 @@ class ArgvInputTest extends TestCase
|
||||
new InputDefinition(array(new InputArgument('number'))),
|
||||
'The "-1" option does not exist.',
|
||||
),
|
||||
array(
|
||||
array('cli.php', '-fЩ'),
|
||||
new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_NONE))),
|
||||
'The "-Щ" option does not exist.',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -13,9 +13,12 @@ namespace Symfony\Component\Console\Tests\Output;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\StreamableInputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\StreamOutput;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
|
||||
class ConsoleSectionOutputTest extends TestCase
|
||||
{
|
||||
@@ -23,7 +26,7 @@ class ConsoleSectionOutputTest extends TestCase
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->stream = fopen('php://memory', 'r+', false);
|
||||
$this->stream = fopen('php://memory', 'r+b', false);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
@@ -137,4 +140,24 @@ class ConsoleSectionOutputTest extends TestCase
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals('Foo'.PHP_EOL.'Bar'.PHP_EOL."\x1b[2A\x1b[0JBar".PHP_EOL."\x1b[1A\x1b[0JBaz".PHP_EOL.'Bar'.PHP_EOL."\x1b[1A\x1b[0JFoobar".PHP_EOL, stream_get_contents($output->getStream()));
|
||||
}
|
||||
|
||||
public function testClearSectionContainingQuestion()
|
||||
{
|
||||
$inputStream = fopen('php://memory', 'r+b', false);
|
||||
fwrite($inputStream, "Batman & Robin\n");
|
||||
rewind($inputStream);
|
||||
|
||||
$input = $this->getMockBuilder(StreamableInputInterface::class)->getMock();
|
||||
$input->expects($this->once())->method('isInteractive')->willReturn(true);
|
||||
$input->expects($this->once())->method('getStream')->willReturn($inputStream);
|
||||
|
||||
$sections = array();
|
||||
$output = new ConsoleSectionOutput($this->stream, $sections, OutputInterface::VERBOSITY_NORMAL, true, new OutputFormatter());
|
||||
|
||||
(new QuestionHelper())->ask($input, $output, new Question('What\'s your favorite super hero?'));
|
||||
$output->clear();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertSame('What\'s your favorite super hero?'.PHP_EOL."\x1b[2A\x1b[0J", stream_get_contents($output->getStream()));
|
||||
}
|
||||
}
|
||||
|
@@ -90,4 +90,24 @@ class ApplicationTesterTest extends TestCase
|
||||
{
|
||||
$this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code');
|
||||
}
|
||||
|
||||
public function testErrorOutput()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->register('foo')
|
||||
->addArgument('foo')
|
||||
->setCode(function ($input, $output) {
|
||||
$output->getErrorOutput()->write('foo');
|
||||
})
|
||||
;
|
||||
|
||||
$tester = new ApplicationTester($application);
|
||||
$tester->run(
|
||||
array('command' => 'foo', 'foo' => 'bar'),
|
||||
array('capture_stderr_separately' => true)
|
||||
);
|
||||
|
||||
$this->assertSame('foo', $tester->getErrorOutput());
|
||||
}
|
||||
}
|
||||
|
@@ -160,4 +160,23 @@ class CommandTesterTest extends TestCase
|
||||
|
||||
$this->assertEquals(0, $tester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testErrorOutput()
|
||||
{
|
||||
$command = new Command('foo');
|
||||
$command->addArgument('command');
|
||||
$command->addArgument('foo');
|
||||
$command->setCode(function ($input, $output) {
|
||||
$output->getErrorOutput()->write('foo');
|
||||
}
|
||||
);
|
||||
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute(
|
||||
array('foo' => 'bar'),
|
||||
array('capture_stderr_separately' => true)
|
||||
);
|
||||
|
||||
$this->assertSame('foo', $tester->getErrorOutput());
|
||||
}
|
||||
}
|
||||
|
3
vendor/symfony/console/composer.json
vendored
3
vendor/symfony/console/composer.json
vendored
@@ -17,6 +17,7 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"symfony/contracts": "^1.0",
|
||||
"symfony/polyfill-mbstring": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -46,7 +47,7 @@
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.1-dev"
|
||||
"dev-master": "4.2-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
vendor/symfony/console/phpunit.xml.dist
vendored
2
vendor/symfony/console/phpunit.xml.dist
vendored
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
|
Reference in New Issue
Block a user