upgraded dependencies

This commit is contained in:
RafficMohammed
2023-01-08 01:59:16 +05:30
parent 51056e3aad
commit f9ae387337
6895 changed files with 133617 additions and 178680 deletions

View File

@@ -20,22 +20,18 @@ namespace Symfony\Component\Console\Helper;
*/
class DebugFormatterHelper extends Helper
{
private $colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'];
private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'];
private $started = [];
private $count = -1;
/**
* Starts a debug formatting session.
*
* @param string $id The id of the formatting session
* @param string $message The message to display
* @param string $prefix The prefix to use
*
* @return string
*/
public function start($id, $message, $prefix = 'RUN')
public function start(string $id, string $message, string $prefix = 'RUN')
{
$this->started[$id] = ['border' => ++$this->count % \count($this->colors)];
$this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)];
return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
}
@@ -43,15 +39,9 @@ class DebugFormatterHelper extends Helper
/**
* Adds progress to a formatting session.
*
* @param string $id The id of the formatting session
* @param string $buffer The message to display
* @param bool $error Whether to consider the buffer as error
* @param string $prefix The prefix for output
* @param string $errorPrefix The prefix for error output
*
* @return string
*/
public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
public function progress(string $id, string $buffer, bool $error = false, string $prefix = 'OUT', string $errorPrefix = 'ERR')
{
$message = '';
@@ -85,14 +75,9 @@ class DebugFormatterHelper extends Helper
/**
* Stops a formatting session.
*
* @param string $id The id of the formatting session
* @param string $message The message to display
* @param bool $successful Whether to consider the result as success
* @param string $prefix The prefix for the end output
*
* @return string
*/
public function stop($id, $message, $successful, $prefix = 'RES')
public function stop(string $id, string $message, bool $successful, string $prefix = 'RES')
{
$trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
@@ -109,7 +94,7 @@ class DebugFormatterHelper extends Helper
private function getBorder(string $id): string
{
return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
return sprintf('<bg=%s> </>', self::COLORS[$this->started[$id]['border']]);
}
/**

View File

@@ -48,11 +48,9 @@ class DescriptorHelper extends Helper
* * format: string, the output format name
* * raw_text: boolean, sets output type as raw
*
* @param object $object
*
* @throws InvalidArgumentException when the given format is not supported
*/
public function describe(OutputInterface $output, $object, array $options = [])
public function describe(OutputInterface $output, ?object $object, array $options = [])
{
$options = array_merge([
'raw_text' => false,
@@ -70,11 +68,9 @@ class DescriptorHelper extends Helper
/**
* Registers a descriptor.
*
* @param string $format
*
* @return $this
*/
public function register($format, DescriptorInterface $descriptor)
public function register(string $format, DescriptorInterface $descriptor)
{
$this->descriptors[$format] = $descriptor;
@@ -88,4 +84,9 @@ class DescriptorHelper extends Helper
{
return 'descriptor';
}
public function getFormats(): array
{
return array_keys($this->descriptors);
}
}

View File

@@ -23,13 +23,9 @@ class FormatterHelper extends Helper
/**
* Formats a message within a section.
*
* @param string $section The section name
* @param string $message The message
* @param string $style The style to apply to the section
*
* @return string The format section
* @return string
*/
public function formatSection($section, $message, $style = 'info')
public function formatSection(string $section, string $message, string $style = 'info')
{
return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
}
@@ -38,12 +34,10 @@ class FormatterHelper extends Helper
* Formats a message as a block of text.
*
* @param string|array $messages The message to write in the block
* @param string $style The style to apply to the whole block
* @param bool $large Whether to return a large block
*
* @return string The formatter message
* @return string
*/
public function formatBlock($messages, $style, $large = false)
public function formatBlock($messages, string $style, bool $large = false)
{
if (!\is_array($messages)) {
$messages = [$messages];
@@ -54,12 +48,12 @@ class FormatterHelper extends Helper
foreach ($messages as $message) {
$message = OutputFormatter::escape($message);
$lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
$len = max(self::strlen($message) + ($large ? 4 : 2), $len);
$len = max(self::width($message) + ($large ? 4 : 2), $len);
}
$messages = $large ? [str_repeat(' ', $len)] : [];
for ($i = 0; isset($lines[$i]); ++$i) {
$messages[] = $lines[$i].str_repeat(' ', $len - self::strlen($lines[$i]));
$messages[] = $lines[$i].str_repeat(' ', $len - self::width($lines[$i]));
}
if ($large) {
$messages[] = str_repeat(' ', $len);
@@ -75,17 +69,13 @@ class FormatterHelper extends Helper
/**
* Truncates a message to the given length.
*
* @param string $message
* @param int $length
* @param string $suffix
*
* @return string
*/
public function truncate($message, $length, $suffix = '...')
public function truncate(string $message, int $length, string $suffix = '...')
{
$computedLength = $length - self::strlen($suffix);
$computedLength = $length - self::width($suffix);
if ($computedLength > self::strlen($message)) {
if ($computedLength > self::width($message)) {
return $message;
}

View File

@@ -12,6 +12,7 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\String\UnicodeString;
/**
* Helper is the base class for all helper classes.
@@ -41,13 +42,28 @@ abstract class Helper implements HelperInterface
/**
* Returns the length of a string, using mb_strwidth if it is available.
*
* @param string $string The string to check its length
* @deprecated since Symfony 5.3
*
* @return int The length of the string
* @return int
*/
public static function strlen($string)
public static function strlen(?string $string)
{
$string = (string) $string;
trigger_deprecation('symfony/console', '5.3', 'Method "%s()" is deprecated and will be removed in Symfony 6.0. Use Helper::width() or Helper::length() instead.', __METHOD__);
return self::width($string);
}
/**
* Returns the width of a string, using mb_strwidth if it is available.
* The width is how many characters positions the string will use.
*/
public static function width(?string $string): int
{
$string ?? $string = '';
if (preg_match('//u', $string)) {
return (new UnicodeString($string))->width(false);
}
if (false === $encoding = mb_detect_encoding($string, null, true)) {
return \strlen($string);
@@ -56,18 +72,33 @@ abstract class Helper implements HelperInterface
return mb_strwidth($string, $encoding);
}
/**
* Returns the length of a string, using mb_strlen if it is available.
* The length is related to how many bytes the string will use.
*/
public static function length(?string $string): int
{
$string ?? $string = '';
if (preg_match('//u', $string)) {
return (new UnicodeString($string))->length();
}
if (false === $encoding = mb_detect_encoding($string, null, true)) {
return \strlen($string);
}
return mb_strlen($string, $encoding);
}
/**
* Returns the subset of a string, using mb_substr if it is available.
*
* @param string $string String to subset
* @param int $from Start offset
* @param int|null $length Length to read
*
* @return string The string subset
* @return string
*/
public static function substr($string, $from, $length = null)
public static function substr(?string $string, int $from, int $length = null)
{
$string = (string) $string;
$string ?? $string = '';
if (false === $encoding = mb_detect_encoding($string, null, true)) {
return substr($string, $from, $length);
@@ -105,7 +136,7 @@ abstract class Helper implements HelperInterface
}
}
public static function formatMemory($memory)
public static function formatMemory(int $memory)
{
if ($memory >= 1024 * 1024 * 1024) {
return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
@@ -122,21 +153,26 @@ abstract class Helper implements HelperInterface
return sprintf('%d B', $memory);
}
public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
/**
* @deprecated since Symfony 5.3
*/
public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, ?string $string)
{
return self::strlen(self::removeDecoration($formatter, $string));
trigger_deprecation('symfony/console', '5.3', 'Method "%s()" is deprecated and will be removed in Symfony 6.0. Use Helper::removeDecoration() instead.', __METHOD__);
return self::width(self::removeDecoration($formatter, $string));
}
public static function removeDecoration(OutputFormatterInterface $formatter, $string)
public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string)
{
$isDecorated = $formatter->isDecorated();
$formatter->setDecorated(false);
// remove <...> formatting
$string = $formatter->format($string);
$string = $formatter->format($string ?? '');
// remove already formatted characters
$string = preg_replace("/\033\[[^m]*m/", '', $string);
$string = preg_replace("/\033\[[^m]*m/", '', $string ?? '');
// remove terminal hyperlinks
$string = preg_replace('/\\033]8;[^;]*;[^\\033]*\\033\\\\/', '', $string);
$string = preg_replace('/\\033]8;[^;]*;[^\\033]*\\033\\\\/', '', $string ?? '');
$formatter->setDecorated($isDecorated);
return $string;

View File

@@ -26,14 +26,14 @@ interface HelperInterface
/**
* Gets the helper set associated with this helper.
*
* @return HelperSet A HelperSet instance
* @return HelperSet|null
*/
public function getHelperSet();
/**
* Returns the canonical name of this helper.
*
* @return string The canonical name
* @return string
*/
public function getName();
}

View File

@@ -18,12 +18,12 @@ use Symfony\Component\Console\Exception\InvalidArgumentException;
* HelperSet represents a set of helpers to be used with a command.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @implements \IteratorAggregate<string, Helper>
*/
class HelperSet implements \IteratorAggregate
{
/**
* @var Helper[]
*/
/** @var array<string, Helper> */
private $helpers = [];
private $command;
@@ -37,12 +37,7 @@ class HelperSet implements \IteratorAggregate
}
}
/**
* Sets a helper.
*
* @param string $alias An alias
*/
public function set(HelperInterface $helper, $alias = null)
public function set(HelperInterface $helper, string $alias = null)
{
$this->helpers[$helper->getName()] = $helper;
if (null !== $alias) {
@@ -55,11 +50,9 @@ class HelperSet implements \IteratorAggregate
/**
* Returns true if the helper if defined.
*
* @param string $name The helper name
*
* @return bool true if the helper is defined, false otherwise
* @return bool
*/
public function has($name)
public function has(string $name)
{
return isset($this->helpers[$name]);
}
@@ -67,13 +60,11 @@ class HelperSet implements \IteratorAggregate
/**
* Gets a helper value.
*
* @param string $name The helper name
*
* @return HelperInterface The helper instance
* @return HelperInterface
*
* @throws InvalidArgumentException if the helper is not defined
*/
public function get($name)
public function get(string $name)
{
if (!$this->has($name)) {
throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
@@ -82,23 +73,32 @@ class HelperSet implements \IteratorAggregate
return $this->helpers[$name];
}
/**
* @deprecated since Symfony 5.4
*/
public function setCommand(Command $command = null)
{
trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__);
$this->command = $command;
}
/**
* Gets the command associated with this helper set.
*
* @return Command A Command instance
* @return Command
*
* @deprecated since Symfony 5.4
*/
public function getCommand()
{
trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__);
return $this->command;
}
/**
* @return \Traversable<Helper>
* @return \Traversable<string, Helper>
*/
#[\ReturnTypeWillChange]
public function getIterator()

View File

@@ -21,22 +21,18 @@ use Symfony\Component\Process\Process;
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.2
* @final
*/
class ProcessHelper extends Helper
{
/**
* Runs an external process.
*
* @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
* @param array|Process $cmd An instance of Process or an array of the command and arguments
* @param callable|null $callback A PHP callback to run whenever there is some
* output available on STDOUT or STDERR
*/
public function run(OutputInterface $output, $cmd, $error = null, callable $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
public function run(OutputInterface $output, $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process
{
if (!class_exists(Process::class)) {
throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".');
@@ -53,8 +49,7 @@ class ProcessHelper extends Helper
}
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 = [method_exists(Process::class, 'fromShellCommandline') ? Process::fromShellCommandline($cmd) : new Process($cmd)];
throw new \TypeError(sprintf('The "command" argument of "%s()" must be an array or a "%s" instance, "%s" given.', __METHOD__, Process::class, get_debug_type($cmd)));
}
if (\is_string($cmd[0] ?? null)) {
@@ -96,17 +91,14 @@ class ProcessHelper extends Helper
* exits with a non-zero exit code.
*
* @param array|Process $cmd An instance of Process 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
*
* @return Process The process that ran
*
* @throws ProcessFailedException
*
* @see run()
*/
public function mustRun(OutputInterface $output, $cmd, $error = null, callable $callback = null)
public function mustRun(OutputInterface $output, $cmd, string $error = null, callable $callback = null): Process
{
$process = $this->run($output, $cmd, $error, $callback);
@@ -119,10 +111,8 @@ class ProcessHelper extends Helper
/**
* Wraps a Process callback to add debugging output.
*
* @return callable
*/
public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null)
public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null): callable
{
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
@@ -147,7 +137,7 @@ class ProcessHelper extends Helper
/**
* {@inheritdoc}
*/
public function getName()
public function getName(): string
{
return 'process';
}

View File

@@ -11,6 +11,7 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Cursor;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\ConsoleSectionOutput;
@@ -25,6 +26,16 @@ use Symfony\Component\Console\Terminal;
*/
final class ProgressBar
{
public const FORMAT_VERBOSE = 'verbose';
public const FORMAT_VERY_VERBOSE = 'very_verbose';
public const FORMAT_DEBUG = 'debug';
public const FORMAT_NORMAL = 'normal';
private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax';
private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax';
private const FORMAT_DEBUG_NOMAX = 'debug_nomax';
private const FORMAT_NORMAL_NOMAX = 'normal_nomax';
private $barWidth = 28;
private $barChar;
private $emptyBarChar = '-';
@@ -42,11 +53,11 @@ final class ProgressBar
private $startTime;
private $stepWidth;
private $percent = 0.0;
private $formatLineCount;
private $messages = [];
private $overwrite = true;
private $terminal;
private $previousMessage;
private $cursor;
private static $formatters;
private static $formats;
@@ -54,7 +65,7 @@ final class ProgressBar
/**
* @param int $max Maximum steps (0 if unknown)
*/
public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 0.1)
public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25)
{
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
@@ -78,6 +89,7 @@ final class ProgressBar
}
$this->startTime = time();
$this->cursor = new Cursor($output);
}
/**
@@ -101,8 +113,6 @@ final class ProgressBar
* Gets the placeholder formatter for a given name.
*
* @param string $name The placeholder name (including the delimiter char like %)
*
* @return callable|null A PHP callable
*/
public static function getPlaceholderFormatterDefinition(string $name): ?callable
{
@@ -134,8 +144,6 @@ final class ProgressBar
* Gets the format for a given name.
*
* @param string $name The format name
*
* @return string|null A format string
*/
public static function getFormatDefinition(string $name): ?string
{
@@ -191,11 +199,29 @@ final class ProgressBar
return $this->percent;
}
public function getBarOffset(): int
public function getBarOffset(): float
{
return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth);
}
public function getEstimated(): float
{
if (!$this->step) {
return 0;
}
return round((time() - $this->startTime) / $this->step * $this->max);
}
public function getRemaining(): float
{
if (!$this->step) {
return 0;
}
return round((time() - $this->startTime) / $this->step * ($this->max - $this->step));
}
public function setBarWidth(int $size)
{
$this->barWidth = max(1, $size);
@@ -213,11 +239,7 @@ final class ProgressBar
public function getBarCharacter(): string
{
if (null === $this->barChar) {
return $this->max ? '=' : $this->emptyBarChar;
}
return $this->barChar;
return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar);
}
public function setEmptyBarCharacter(string $char)
@@ -357,7 +379,7 @@ final class ProgressBar
{
$this->format = null;
$this->max = max(0, $max);
$this->stepWidth = $this->max ? Helper::strlen((string) $this->max) : 4;
$this->stepWidth = $this->max ? Helper::width((string) $this->max) : 4;
}
/**
@@ -423,8 +445,6 @@ final class ProgressBar
} else {
$this->format = $format;
}
$this->formatLineCount = substr_count($this->format, "\n");
}
/**
@@ -441,23 +461,25 @@ final class ProgressBar
if ($this->overwrite) {
if (null !== $this->previousMessage) {
if ($this->output instanceof ConsoleSectionOutput) {
$messageLines = explode("\n", $message);
$messageLines = explode("\n", $this->previousMessage);
$lineCount = \count($messageLines);
foreach ($messageLines as $messageLine) {
$messageLineLength = Helper::strlenWithoutDecoration($this->output->getFormatter(), $messageLine);
$messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine));
if ($messageLineLength > $this->terminal->getWidth()) {
$lineCount += floor($messageLineLength / $this->terminal->getWidth());
}
}
$this->output->clear($lineCount);
} else {
// Erase previous lines
if ($this->formatLineCount > 0) {
$message = str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount).$message;
$lineCount = substr_count($this->previousMessage, "\n");
for ($i = 0; $i < $lineCount; ++$i) {
$this->cursor->moveToColumn(1);
$this->cursor->clearLine();
$this->cursor->moveUp();
}
// Move the cursor to the beginning of the line and erase the line
$message = "\x0D\x1B[2K$message";
$this->cursor->moveToColumn(1);
$this->cursor->clearLine();
}
}
} elseif ($this->step > 0) {
@@ -476,13 +498,13 @@ final class ProgressBar
switch ($this->output->getVerbosity()) {
// OutputInterface::VERBOSITY_QUIET: display is disabled anyway
case OutputInterface::VERBOSITY_VERBOSE:
return $this->max ? 'verbose' : 'verbose_nomax';
return $this->max ? self::FORMAT_VERBOSE : self::FORMAT_VERBOSE_NOMAX;
case OutputInterface::VERBOSITY_VERY_VERBOSE:
return $this->max ? 'very_verbose' : 'very_verbose_nomax';
return $this->max ? self::FORMAT_VERY_VERBOSE : self::FORMAT_VERY_VERBOSE_NOMAX;
case OutputInterface::VERBOSITY_DEBUG:
return $this->max ? 'debug' : 'debug_nomax';
return $this->max ? self::FORMAT_DEBUG : self::FORMAT_DEBUG_NOMAX;
default:
return $this->max ? 'normal' : 'normal_nomax';
return $this->max ? self::FORMAT_NORMAL : self::FORMAT_NORMAL_NOMAX;
}
}
@@ -493,7 +515,7 @@ final class ProgressBar
$completeBars = $bar->getBarOffset();
$display = str_repeat($bar->getBarCharacter(), $completeBars);
if ($completeBars < $bar->getBarWidth()) {
$emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
$emptyBars = $bar->getBarWidth() - $completeBars - Helper::length(Helper::removeDecoration($output->getFormatter(), $bar->getProgressCharacter()));
$display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
}
@@ -507,26 +529,14 @@ final class ProgressBar
throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
}
if (!$bar->getProgress()) {
$remaining = 0;
} else {
$remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
}
return Helper::formatTime($remaining);
return Helper::formatTime($bar->getRemaining());
},
'estimated' => function (self $bar) {
if (!$bar->getMaxSteps()) {
throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
}
if (!$bar->getProgress()) {
$estimated = 0;
} else {
$estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
}
return Helper::formatTime($estimated);
return Helper::formatTime($bar->getEstimated());
},
'memory' => function (self $bar) {
return Helper::formatMemory(memory_get_usage(true));
@@ -546,17 +556,17 @@ final class ProgressBar
private static function initFormats(): array
{
return [
'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
'normal_nomax' => ' %current% [%bar%]',
self::FORMAT_NORMAL => ' %current%/%max% [%bar%] %percent:3s%%',
self::FORMAT_NORMAL_NOMAX => ' %current% [%bar%]',
'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
self::FORMAT_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
self::FORMAT_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%',
'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
self::FORMAT_VERY_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
self::FORMAT_VERY_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%',
'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
self::FORMAT_DEBUG => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
self::FORMAT_DEBUG_NOMAX => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
];
}
@@ -582,7 +592,7 @@ final class ProgressBar
// gets string length for each sub line with multiline format
$linesLength = array_map(function ($subLine) {
return Helper::strlenWithoutDecoration($this->output->getFormatter(), rtrim($subLine, "\r"));
return Helper::width(Helper::removeDecoration($this->output->getFormatter(), rtrim($subLine, "\r")));
}, explode("\n", $line));
$linesWidth = max($linesLength);

View File

@@ -20,6 +20,17 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
class ProgressIndicator
{
private const FORMATS = [
'normal' => ' %indicator% %message%',
'normal_no_ansi' => ' %message%',
'verbose' => ' %indicator% %message% (%elapsed:6s%)',
'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
];
private $output;
private $startTime;
private $format;
@@ -30,13 +41,14 @@ class ProgressIndicator
private $indicatorUpdateTime;
private $started = false;
/**
* @var array<string, callable>
*/
private static $formatters;
private static $formats;
/**
* @param string|null $format Indicator format
* @param int $indicatorChangeInterval Change interval in milliseconds
* @param array|null $indicatorValues Animated indicator characters
* @param int $indicatorChangeInterval Change interval in milliseconds
* @param array|null $indicatorValues Animated indicator characters
*/
public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null)
{
@@ -64,10 +76,8 @@ class ProgressIndicator
/**
* Sets the current indicator message.
*
* @param string|null $message
*/
public function setMessage($message)
public function setMessage(?string $message)
{
$this->message = $message;
@@ -76,10 +86,8 @@ class ProgressIndicator
/**
* Starts the indicator output.
*
* @param $message
*/
public function start($message)
public function start(string $message)
{
if ($this->started) {
throw new LogicException('Progress indicator already started.');
@@ -124,7 +132,7 @@ class ProgressIndicator
*
* @param $message
*/
public function finish($message)
public function finish(string $message)
{
if (!$this->started) {
throw new LogicException('Progress indicator has not yet been started.');
@@ -139,28 +147,19 @@ class ProgressIndicator
/**
* Gets the format for a given name.
*
* @param string $name The format name
*
* @return string|null A format string
* @return string|null
*/
public static function getFormatDefinition($name)
public static function getFormatDefinition(string $name)
{
if (!self::$formats) {
self::$formats = self::initFormats();
}
return self::$formats[$name] ?? null;
return self::FORMATS[$name] ?? null;
}
/**
* Sets a placeholder formatter for a given name.
*
* This method also allow you to override an existing placeholder.
*
* @param string $name The placeholder name (including the delimiter char like %)
* @param callable $callable A PHP callable
*/
public static function setPlaceholderFormatterDefinition($name, $callable)
public static function setPlaceholderFormatterDefinition(string $name, callable $callable)
{
if (!self::$formatters) {
self::$formatters = self::initPlaceholderFormatters();
@@ -170,13 +169,11 @@ class ProgressIndicator
}
/**
* Gets the placeholder formatter for a given name.
* Gets the placeholder formatter for a given name (including the delimiter char like %).
*
* @param string $name The placeholder name (including the delimiter char like %)
*
* @return callable|null A PHP callable
* @return callable|null
*/
public static function getPlaceholderFormatterDefinition($name)
public static function getPlaceholderFormatterDefinition(string $name)
{
if (!self::$formatters) {
self::$formatters = self::initPlaceholderFormatters();
@@ -249,18 +246,4 @@ class ProgressIndicator
},
];
}
private static function initFormats(): array
{
return [
'normal' => ' %indicator% %message%',
'normal_no_ansi' => ' %message%',
'verbose' => ' %indicator% %message% (%elapsed:6s%)',
'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
];
}
}

View File

@@ -11,6 +11,7 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Cursor;
use Symfony\Component\Console\Exception\MissingInputException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Formatter\OutputFormatter;
@@ -24,6 +25,8 @@ use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Terminal;
use function Symfony\Component\String\s;
/**
* The QuestionHelper class provides helpers to interact with the user.
*
@@ -31,8 +34,11 @@ use Symfony\Component\Console\Terminal;
*/
class QuestionHelper extends Helper
{
/**
* @var resource|null
*/
private $inputStream;
private static $shell;
private static $stty = true;
private static $stdinIsInteractive;
@@ -122,9 +128,7 @@ class QuestionHelper extends Helper
}
if (false === $ret) {
$cp = $this->setIOCodepage();
$ret = fgets($inputStream, 4096);
$ret = $this->resetIOCodepage($cp, $ret);
$ret = $this->readInput($inputStream, $question);
if (false === $ret) {
throw new MissingInputException('Aborted.');
}
@@ -199,18 +203,16 @@ class QuestionHelper extends Helper
}
/**
* @param string $tag
*
* @return string[]
*/
protected function formatChoiceQuestionChoices(ChoiceQuestion $question, $tag)
protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag)
{
$messages = [];
$maxWidth = max(array_map([__CLASS__, 'strlen'], array_keys($choices = $question->getChoices())));
$maxWidth = max(array_map([__CLASS__, 'width'], array_keys($choices = $question->getChoices())));
foreach ($choices as $key => $value) {
$padding = str_repeat(' ', $maxWidth - self::strlen($key));
$padding = str_repeat(' ', $maxWidth - self::width($key));
$messages[] = sprintf(" [<$tag>%s$padding</$tag>] %s", $key, $value);
}
@@ -239,6 +241,8 @@ class QuestionHelper extends Helper
*/
private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string
{
$cursor = new Cursor($output, $inputStream);
$fullChoice = '';
$ret = '';
@@ -248,6 +252,9 @@ class QuestionHelper extends Helper
$numMatches = \count($matches);
$sttyMode = shell_exec('stty -g');
$isStdin = 'php://stdin' === (stream_get_meta_data($inputStream)['uri'] ?? null);
$r = [$inputStream];
$w = [];
// Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
shell_exec('stty -icanon -echo');
@@ -257,18 +264,22 @@ class QuestionHelper extends Helper
// Read a keypress
while (!feof($inputStream)) {
while ($isStdin && 0 === @stream_select($r, $w, $w, 0, 100)) {
// Give signal handlers a chance to run
$r = [$inputStream];
}
$c = fread($inputStream, 1);
// as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false.
if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) {
shell_exec(sprintf('stty %s', $sttyMode));
shell_exec('stty '.$sttyMode);
throw new MissingInputException('Aborted.');
} elseif ("\177" === $c) { // Backspace Character
if (0 === $numMatches && 0 !== $i) {
--$i;
$cursor->moveLeft(s($fullChoice)->slice(-1)->width(false));
$fullChoice = self::substr($fullChoice, 0, $i);
// Move cursor backwards
$output->write("\033[1D");
}
if (0 === $i) {
@@ -354,22 +365,19 @@ class QuestionHelper extends Helper
}
}
// Erase characters from cursor to end of line
$output->write("\033[K");
$cursor->clearLineAfter();
if ($numMatches > 0 && -1 !== $ofs) {
// Save cursor position
$output->write("\0337");
$cursor->savePosition();
// Write highlighted text, complete the partially entered response
$charactersEntered = \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)));
$output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).'</hl>');
// Restore cursor position
$output->write("\0338");
$cursor->restorePosition();
}
}
// Reset stty so it behaves normally again
shell_exec(sprintf('stty %s', $sttyMode));
shell_exec('stty '.$sttyMode);
return $fullChoice;
}
@@ -430,7 +438,7 @@ class QuestionHelper extends Helper
$value = fgets($inputStream, 4096);
if (self::$stty && Terminal::hasSttyAvailable()) {
shell_exec(sprintf('stty %s', $sttyMode));
shell_exec('stty '.$sttyMode);
}
if (false === $value) {
@@ -501,6 +509,40 @@ class QuestionHelper extends Helper
return self::$stdinIsInteractive = 1 !== $status;
}
/**
* Reads one or more lines of input and returns what is read.
*
* @param resource $inputStream The handler resource
* @param Question $question The question being asked
*
* @return string|false The input received, false in case input could not be read
*/
private function readInput($inputStream, Question $question)
{
if (!$question->isMultiline()) {
$cp = $this->setIOCodepage();
$ret = fgets($inputStream, 4096);
return $this->resetIOCodepage($cp, $ret);
}
$multiLineStreamReader = $this->cloneInputStream($inputStream);
if (null === $multiLineStreamReader) {
return false;
}
$ret = '';
$cp = $this->setIOCodepage();
while (false !== ($char = fgetc($multiLineStreamReader))) {
if (\PHP_EOL === "{$ret}{$char}") {
break;
}
$ret .= $char;
}
return $this->resetIOCodepage($cp, $ret);
}
/**
* Sets console I/O to the host code page.
*
@@ -537,4 +579,38 @@ class QuestionHelper extends Helper
return $input;
}
/**
* Clones an input stream in order to act on one instance of the same
* stream without affecting the other instance.
*
* @param resource $inputStream The handler resource
*
* @return resource|null The cloned resource, null in case it could not be cloned
*/
private function cloneInputStream($inputStream)
{
$streamMetaData = stream_get_meta_data($inputStream);
$seekable = $streamMetaData['seekable'] ?? false;
$mode = $streamMetaData['mode'] ?? 'rb';
$uri = $streamMetaData['uri'] ?? null;
if (null === $uri) {
return null;
}
$cloneStream = fopen($uri, $mode);
// For seekable and writable streams, add all the same data to the
// cloned stream and then seek to the same offset.
if (true === $seekable && !\in_array($mode, ['r', 'rb', 'rt'])) {
$offset = ftell($inputStream);
rewind($inputStream);
stream_copy_to_stream($inputStream, $cloneStream);
fseek($inputStream, $offset);
fseek($cloneStream, $offset);
}
return $cloneStream;
}
}

View File

@@ -33,6 +33,10 @@ class SymfonyQuestionHelper extends QuestionHelper
$text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
$default = $question->getDefault();
if ($question->isMultiline()) {
$text .= sprintf(' (press %s to continue)', $this->getEofShortcut());
}
switch (true) {
case null === $default:
$text = sprintf(' <info>%s</info>:', $text);
@@ -93,4 +97,13 @@ class SymfonyQuestionHelper extends QuestionHelper
parent::writeError($output, $error);
}
private function getEofShortcut(): string
{
if ('Windows' === \PHP_OS_FAMILY) {
return '<comment>Ctrl+Z</comment> then <comment>Enter</comment>';
}
return '<comment>Ctrl+D</comment>';
}
}

View File

@@ -85,6 +85,9 @@ class Table
private $columnWidths = [];
private $columnMaxWidths = [];
/**
* @var array<string, TableStyle>|null
*/
private static $styles;
private $rendered = false;
@@ -102,10 +105,8 @@ class Table
/**
* Sets a style definition.
*
* @param string $name The style name
*/
public static function setStyleDefinition($name, TableStyle $style)
public static function setStyleDefinition(string $name, TableStyle $style)
{
if (!self::$styles) {
self::$styles = self::initStyles();
@@ -117,11 +118,9 @@ class Table
/**
* Gets a style definition by name.
*
* @param string $name The style name
*
* @return TableStyle
*/
public static function getStyleDefinition($name)
public static function getStyleDefinition(string $name)
{
if (!self::$styles) {
self::$styles = self::initStyles();
@@ -161,15 +160,12 @@ class Table
/**
* Sets table column style.
*
* @param int $columnIndex Column index
* @param TableStyle|string $name The style name or a TableStyle instance
* @param TableStyle|string $name The style name or a TableStyle instance
*
* @return $this
*/
public function setColumnStyle($columnIndex, $name)
public function setColumnStyle(int $columnIndex, $name)
{
$columnIndex = (int) $columnIndex;
$this->columnStyles[$columnIndex] = $this->resolveStyle($name);
return $this;
@@ -180,11 +176,9 @@ class Table
*
* If style was not set, it returns the global table style.
*
* @param int $columnIndex Column index
*
* @return TableStyle
*/
public function getColumnStyle($columnIndex)
public function getColumnStyle(int $columnIndex)
{
return $this->columnStyles[$columnIndex] ?? $this->getStyle();
}
@@ -192,14 +186,11 @@ class Table
/**
* Sets the minimum width of a column.
*
* @param int $columnIndex Column index
* @param int $width Minimum column width in characters
*
* @return $this
*/
public function setColumnWidth($columnIndex, $width)
public function setColumnWidth(int $columnIndex, int $width)
{
$this->columnWidths[(int) $columnIndex] = (int) $width;
$this->columnWidths[$columnIndex] = $width;
return $this;
}
@@ -230,7 +221,7 @@ class Table
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())));
throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter())));
}
$this->columnMaxWidths[$columnIndex] = $width;
@@ -238,6 +229,9 @@ class Table
return $this;
}
/**
* @return $this
*/
public function setHeaders(array $headers)
{
$headers = array_values($headers);
@@ -257,6 +251,9 @@ class Table
return $this->addRows($rows);
}
/**
* @return $this
*/
public function addRows(array $rows)
{
foreach ($rows as $row) {
@@ -266,6 +263,9 @@ class Table
return $this;
}
/**
* @return $this
*/
public function addRow($row)
{
if ($row instanceof TableSeparator) {
@@ -285,6 +285,8 @@ class Table
/**
* Adds a row to the table, and re-renders the table.
*
* @return $this
*/
public function appendRow($row): self
{
@@ -302,6 +304,9 @@ class Table
return $this;
}
/**
* @return $this
*/
public function setRow($column, array $row)
{
$this->rows[$column] = $row;
@@ -309,6 +314,9 @@ class Table
return $this;
}
/**
* @return $this
*/
public function setHeaderTitle(?string $title): self
{
$this->headerTitle = $title;
@@ -316,6 +324,9 @@ class Table
return $this;
}
/**
* @return $this
*/
public function setFooterTitle(?string $title): self
{
$this->footerTitle = $title;
@@ -323,6 +334,9 @@ class Table
return $this;
}
/**
* @return $this
*/
public function setHorizontal(bool $horizontal = true): self
{
$this->horizontal = $horizontal;
@@ -466,11 +480,11 @@ class Table
}
if (null !== $title) {
$titleLength = Helper::strlenWithoutDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title));
$markupLength = Helper::strlen($markup);
$titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title)));
$markupLength = Helper::width($markup);
if ($titleLength > $limit = $markupLength - 4) {
$titleLength = $limit;
$formatLength = Helper::strlenWithoutDecoration($formatter, sprintf($titleFormat, ''));
$formatLength = Helper::width(Helper::removeDecoration($formatter, sprintf($titleFormat, '')));
$formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...');
}
@@ -543,10 +557,33 @@ class Table
return sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width));
}
$width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
$width += Helper::length($cell) - Helper::length(Helper::removeDecoration($this->output->getFormatter(), $cell));
$content = sprintf($style->getCellRowContentFormat(), $cell);
return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
$padType = $style->getPadType();
if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) {
$isNotStyledByTag = !preg_match('/^<(\w+|(\w+=[\w,]+;?)*)>.+<\/(\w+|(\w+=\w+;?)*)?>$/', $cell);
if ($isNotStyledByTag) {
$cellFormat = $cell->getStyle()->getCellFormat();
if (!\is_string($cellFormat)) {
$tag = http_build_query($cell->getStyle()->getTagOptions(), '', ';');
$cellFormat = '<'.$tag.'>%s</>';
}
if (strstr($content, '</>')) {
$content = str_replace('</>', '', $content);
$width -= 3;
}
if (strstr($content, '<fg=default;bg=default>')) {
$content = str_replace('<fg=default;bg=default>', '', $content);
$width -= \strlen('<fg=default;bg=default>');
}
}
$padType = $cell->getStyle()->getPadByAlign();
}
return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType));
}
/**
@@ -578,7 +615,7 @@ class Table
foreach ($rows[$rowKey] as $column => $cell) {
$colspan = $cell instanceof TableCell ? $cell->getColspan() : 1;
if (isset($this->columnMaxWidths[$column]) && Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) {
if (isset($this->columnMaxWidths[$column]) && Helper::width(Helper::removeDecoration($formatter, $cell)) > $this->columnMaxWidths[$column]) {
$cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan);
}
if (!strstr($cell ?? '', "\n")) {
@@ -642,7 +679,7 @@ class Table
$unmergedRows = [];
foreach ($rows[$line] as $column => $cell) {
if (null !== $cell && !$cell instanceof TableCell && !\is_scalar($cell) && !(\is_object($cell) && method_exists($cell, '__toString'))) {
throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', \gettype($cell)));
throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell)));
}
if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
$nbLines = $cell->getRowspan() - 1;
@@ -651,7 +688,7 @@ class Table
$lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
$nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
$rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan()]);
$rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
unset($lines[0]);
}
@@ -659,7 +696,7 @@ class Table
$unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows);
foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
$value = $lines[$unmergedRowKey - $line] ?? '';
$unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan()]);
$unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
if ($nbLines === $unmergedRowKey - $line) {
break;
}
@@ -766,7 +803,7 @@ class Table
foreach ($row as $i => $cell) {
if ($cell instanceof TableCell) {
$textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
$textLength = Helper::strlen($textContent);
$textLength = Helper::width($textContent);
if ($textLength > 0) {
$contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
foreach ($contentColumns as $position => $content) {
@@ -780,13 +817,13 @@ class Table
}
}
$this->effectiveColumnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2;
$this->effectiveColumnWidths[$column] = max($lengths) + Helper::width($this->style->getCellRowContentFormat()) - 2;
}
}
private function getColumnSeparatorWidth(): int
{
return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3]));
return Helper::width(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3]));
}
private function getCellWidth(array $row, int $column): int
@@ -795,7 +832,7 @@ class Table
if (isset($row[$column])) {
$cell = $row[$column];
$cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
$cellWidth = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $cell));
}
$columnWidth = $this->columnWidths[$column] ?? 0;
@@ -813,6 +850,9 @@ class Table
$this->numberOfColumns = null;
}
/**
* @return array<string, TableStyle>
*/
private static function initStyles(): array
{
$borderless = new TableStyle();

View File

@@ -22,6 +22,7 @@ class TableCell
private $options = [
'rowspan' => 1,
'colspan' => 1,
'style' => null,
];
public function __construct(string $value = '', array $options = [])
@@ -33,6 +34,10 @@ class TableCell
throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
}
if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) {
throw new InvalidArgumentException('The style option must be an instance of "TableCellStyle".');
}
$this->options = array_merge($this->options, $options);
}
@@ -65,4 +70,9 @@ class TableCell
{
return (int) $this->options['rowspan'];
}
public function getStyle(): ?TableCellStyle
{
return $this->options['style'];
}
}

View File

@@ -0,0 +1,89 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* @author Yewhen Khoptynskyi <khoptynskyi@gmail.com>
*/
class TableCellStyle
{
public const DEFAULT_ALIGN = 'left';
private const TAG_OPTIONS = [
'fg',
'bg',
'options',
];
private const ALIGN_MAP = [
'left' => \STR_PAD_RIGHT,
'center' => \STR_PAD_BOTH,
'right' => \STR_PAD_LEFT,
];
private $options = [
'fg' => 'default',
'bg' => 'default',
'options' => null,
'align' => self::DEFAULT_ALIGN,
'cellFormat' => null,
];
public function __construct(array $options = [])
{
if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
throw new InvalidArgumentException(sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff)));
}
if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) {
throw new InvalidArgumentException(sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys(self::ALIGN_MAP))));
}
$this->options = array_merge($this->options, $options);
}
public function getOptions(): array
{
return $this->options;
}
/**
* Gets options we need for tag for example fg, bg.
*
* @return string[]
*/
public function getTagOptions()
{
return array_filter(
$this->getOptions(),
function ($key) {
return \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]);
},
\ARRAY_FILTER_USE_KEY
);
}
/**
* @return int
*/
public function getPadByAlign()
{
return self::ALIGN_MAP[$this->getOptions()['align']];
}
public function getCellFormat(): ?string
{
return $this->getOptions()['cellFormat'];
}
}

View File

@@ -18,15 +18,13 @@ class TableRows implements \IteratorAggregate
{
private $generator;
public function __construct(callable $generator)
public function __construct(\Closure $generator)
{
$this->generator = $generator;
}
public function getIterator(): \Traversable
{
$g = $this->generator;
return $g();
return ($this->generator)();
}
}

View File

@@ -51,11 +51,9 @@ class TableStyle
/**
* Sets padding character, used for cell padding.
*
* @param string $paddingChar
*
* @return $this
*/
public function setPaddingChar($paddingChar)
public function setPaddingChar(string $paddingChar)
{
if (!$paddingChar) {
throw new LogicException('The padding char must not be empty.');
@@ -90,8 +88,7 @@ class TableStyle
* ╚═══════════════╧══════════════════════════╧══════════════════╝
* </code>
*
* @param string $outside Outside border char (see #1 of example)
* @param string|null $inside Inside border char (see #2 of example), equals $outside if null
* @return $this
*/
public function setHorizontalBorderChars(string $outside, string $inside = null): self
{
@@ -101,36 +98,6 @@ class TableStyle
return $this;
}
/**
* Sets horizontal border character.
*
* @param string $horizontalBorderChar
*
* @return $this
*
* @deprecated since Symfony 4.1, use {@link setHorizontalBorderChars()} instead.
*/
public function setHorizontalBorderChar($horizontalBorderChar)
{
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use setHorizontalBorderChars() instead.', __METHOD__), \E_USER_DEPRECATED);
return $this->setHorizontalBorderChars($horizontalBorderChar, $horizontalBorderChar);
}
/**
* Gets horizontal border character.
*
* @return string
*
* @deprecated since Symfony 4.1, use {@link getBorderChars()} instead.
*/
public function getHorizontalBorderChar()
{
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use getBorderChars() instead.', __METHOD__), \E_USER_DEPRECATED);
return $this->horizontalOutsideBorderChar;
}
/**
* Sets vertical border characters.
*
@@ -146,8 +113,7 @@ class TableStyle
* ╚═══════════════╧══════════════════════════╧══════════════════╝
* </code>
*
* @param string $outside Outside border char (see #1 of example)
* @param string|null $inside Inside border char (see #2 of example), equals $outside if null
* @return $this
*/
public function setVerticalBorderChars(string $outside, string $inside = null): self
{
@@ -157,36 +123,6 @@ class TableStyle
return $this;
}
/**
* Sets vertical border character.
*
* @param string $verticalBorderChar
*
* @return $this
*
* @deprecated since Symfony 4.1, use {@link setVerticalBorderChars()} instead.
*/
public function setVerticalBorderChar($verticalBorderChar)
{
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use setVerticalBorderChars() instead.', __METHOD__), \E_USER_DEPRECATED);
return $this->setVerticalBorderChars($verticalBorderChar, $verticalBorderChar);
}
/**
* Gets vertical border character.
*
* @return string
*
* @deprecated since Symfony 4.1, use {@link getBorderChars()} instead.
*/
public function getVerticalBorderChar()
{
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use getBorderChars() instead.', __METHOD__), \E_USER_DEPRECATED);
return $this->verticalOutsideBorderChar;
}
/**
* Gets border characters.
*
@@ -230,6 +166,8 @@ class TableStyle
* @param string|null $topLeftBottom Top left bottom char (see #8' of example), equals to $midLeft if null
* @param string|null $topMidBottom Top mid bottom char (see #0' of example), equals to $cross if null
* @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null
*
* @return $this
*/
public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null): self
{
@@ -259,22 +197,6 @@ class TableStyle
return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char);
}
/**
* Sets crossing character.
*
* @param string $crossingChar
*
* @return $this
*
* @deprecated since Symfony 4.1. Use {@link setDefaultCrossingChar()} instead.
*/
public function setCrossingChar($crossingChar)
{
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1. Use setDefaultCrossingChar() instead.', __METHOD__), \E_USER_DEPRECATED);
return $this->setDefaultCrossingChar($crossingChar);
}
/**
* Gets crossing character.
*
@@ -311,11 +233,9 @@ class TableStyle
/**
* Sets header cell format.
*
* @param string $cellHeaderFormat
*
* @return $this
*/
public function setCellHeaderFormat($cellHeaderFormat)
public function setCellHeaderFormat(string $cellHeaderFormat)
{
$this->cellHeaderFormat = $cellHeaderFormat;
@@ -335,11 +255,9 @@ class TableStyle
/**
* Sets row cell format.
*
* @param string $cellRowFormat
*
* @return $this
*/
public function setCellRowFormat($cellRowFormat)
public function setCellRowFormat(string $cellRowFormat)
{
$this->cellRowFormat = $cellRowFormat;
@@ -359,11 +277,9 @@ class TableStyle
/**
* Sets row cell content format.
*
* @param string $cellRowContentFormat
*
* @return $this
*/
public function setCellRowContentFormat($cellRowContentFormat)
public function setCellRowContentFormat(string $cellRowContentFormat)
{
$this->cellRowContentFormat = $cellRowContentFormat;
@@ -383,11 +299,9 @@ class TableStyle
/**
* Sets table border format.
*
* @param string $borderFormat
*
* @return $this
*/
public function setBorderFormat($borderFormat)
public function setBorderFormat(string $borderFormat)
{
$this->borderFormat = $borderFormat;
@@ -407,11 +321,9 @@ class TableStyle
/**
* Sets cell padding type.
*
* @param int $padType STR_PAD_*
*
* @return $this
*/
public function setPadType($padType)
public function setPadType(int $padType)
{
if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], true)) {
throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
@@ -437,6 +349,9 @@ class TableStyle
return $this->headerTitleFormat;
}
/**
* @return $this
*/
public function setHeaderTitleFormat(string $format): self
{
$this->headerTitleFormat = $format;
@@ -449,6 +364,9 @@ class TableStyle
return $this->footerTitleFormat;
}
/**
* @return $this
*/
public function setFooterTitleFormat(string $format): self
{
$this->footerTitleFormat = $format;