Upgrade framework
This commit is contained in:
992
vendor/symfony/console/Application.php
vendored
992
vendor/symfony/console/Application.php
vendored
File diff suppressed because it is too large
Load Diff
39
vendor/symfony/console/Attribute/AsCommand.php
vendored
Normal file
39
vendor/symfony/console/Attribute/AsCommand.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?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\Attribute;
|
||||
|
||||
/**
|
||||
* Service tag to autoconfigure commands.
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)]
|
||||
class AsCommand
|
||||
{
|
||||
public function __construct(
|
||||
public string $name,
|
||||
public ?string $description = null,
|
||||
array $aliases = [],
|
||||
bool $hidden = false,
|
||||
) {
|
||||
if (!$hidden && !$aliases) {
|
||||
return;
|
||||
}
|
||||
|
||||
$name = explode('|', $name);
|
||||
$name = array_merge($name, $aliases);
|
||||
|
||||
if ($hidden && '' !== $name[0]) {
|
||||
array_unshift($name, '');
|
||||
}
|
||||
|
||||
$this->name = implode('|', $name);
|
||||
}
|
||||
}
|
||||
153
vendor/symfony/console/CHANGELOG.md
vendored
153
vendor/symfony/console/CHANGELOG.md
vendored
@@ -1,31 +1,158 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
6.0
|
||||
---
|
||||
|
||||
* `Command::setHidden()` has a default value (`true`) for `$hidden` parameter and is final
|
||||
* Remove `Helper::strlen()`, use `Helper::width()` instead
|
||||
* Remove `Helper::strlenWithoutDecoration()`, use `Helper::removeDecoration()` instead
|
||||
* `AddConsoleCommandPass` can not be configured anymore
|
||||
* Remove `HelperSet::setCommand()` and `getCommand()` without replacement
|
||||
|
||||
5.4
|
||||
---
|
||||
|
||||
* Add `TesterTrait::assertCommandIsSuccessful()` to test command
|
||||
* Deprecate `HelperSet::setCommand()` and `getCommand()` without replacement
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
* Add `GithubActionReporter` to render annotations in a Github Action
|
||||
* Add `InputOption::VALUE_NEGATABLE` flag to handle `--foo`/`--no-foo` options
|
||||
* Add the `Command::$defaultDescription` static property and the `description` attribute
|
||||
on the `console.command` tag to allow the `list` command to instantiate commands lazily
|
||||
* Add option `--short` to the `list` command
|
||||
* Add support for bright colors
|
||||
* Add `#[AsCommand]` attribute for declaring commands on PHP 8
|
||||
* Add `Helper::width()` and `Helper::length()`
|
||||
* The `--ansi` and `--no-ansi` options now default to `null`.
|
||||
|
||||
5.2.0
|
||||
-----
|
||||
|
||||
* Added `SingleCommandApplication::setAutoExit()` to allow testing via `CommandTester`
|
||||
* added support for multiline responses to questions through `Question::setMultiline()`
|
||||
and `Question::isMultiline()`
|
||||
* Added `SignalRegistry` class to stack signals handlers
|
||||
* Added support for signals:
|
||||
* Added `Application::getSignalRegistry()` and `Application::setSignalsToDispatchEvent()` methods
|
||||
* Added `SignalableCommandInterface` interface
|
||||
* Added `TableCellStyle` class to customize table cell
|
||||
* Removed `php ` prefix invocation from help messages.
|
||||
|
||||
5.1.0
|
||||
-----
|
||||
|
||||
* `Command::setHidden()` is final since Symfony 5.1
|
||||
* Add `SingleCommandApplication`
|
||||
* Add `Cursor` class
|
||||
|
||||
5.0.0
|
||||
-----
|
||||
|
||||
* removed support for finding hidden commands using an abbreviation, use the full name instead
|
||||
* removed `TableStyle::setCrossingChar()` method in favor of `TableStyle::setDefaultCrossingChar()`
|
||||
* removed `TableStyle::setHorizontalBorderChar()` method in favor of `TableStyle::setDefaultCrossingChars()`
|
||||
* removed `TableStyle::getHorizontalBorderChar()` method in favor of `TableStyle::getBorderChars()`
|
||||
* removed `TableStyle::setVerticalBorderChar()` method in favor of `TableStyle::setVerticalBorderChars()`
|
||||
* removed `TableStyle::getVerticalBorderChar()` method in favor of `TableStyle::getBorderChars()`
|
||||
* removed support for returning `null` from `Command::execute()`, return `0` instead
|
||||
* `ProcessHelper::run()` accepts only `array|Symfony\Component\Process\Process` for its `command` argument
|
||||
* `Application::setDispatcher` accepts only `Symfony\Contracts\EventDispatcher\EventDispatcherInterface`
|
||||
for its `dispatcher` argument
|
||||
* renamed `Application::renderException()` and `Application::doRenderException()`
|
||||
to `renderThrowable()` and `doRenderThrowable()` respectively.
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* deprecated finding hidden commands using an abbreviation, use the full name instead
|
||||
* added `Question::setTrimmable` default to true to allow the answer to be trimmed
|
||||
* added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar`
|
||||
* `Application` implements `ResetInterface`
|
||||
* marked all dispatched event classes as `@final`
|
||||
* added support for displaying table horizontally
|
||||
* deprecated returning `null` from `Command::execute()`, return `0` instead
|
||||
* Deprecated the `Application::renderException()` and `Application::doRenderException()` methods,
|
||||
use `renderThrowable()` and `doRenderThrowable()` instead.
|
||||
* added support for the `NO_COLOR` env var (https://no-color.org/)
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* added support for hyperlinks
|
||||
* added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating
|
||||
* added `Question::setAutocompleterCallback()` to provide a callback function
|
||||
that dynamically generates suggestions as the user types
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* allowed passing commands as `[$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
|
||||
-----
|
||||
|
||||
* added option to run suggested command if command is not found and only 1 alternative is available
|
||||
* added option to modify console output and print multiple modifiable sections
|
||||
* added support for iterable messages in output `write` and `writeln` methods
|
||||
|
||||
4.0.0
|
||||
-----
|
||||
|
||||
* `OutputFormatter` throws an exception when unknown options are used
|
||||
* removed `QuestionHelper::setInputStream()/getInputStream()`
|
||||
* removed `Application::getTerminalWidth()/getTerminalHeight()` and
|
||||
`Application::setTerminalDimensions()/getTerminalDimensions()`
|
||||
* removed `ConsoleExceptionEvent`
|
||||
* removed `ConsoleEvents::EXCEPTION`
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
* added `SHELL_VERBOSITY` env var to control verbosity
|
||||
* added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11
|
||||
`ContainerCommandLoader` for commands lazy-loading
|
||||
* added a case-insensitive command name matching fallback
|
||||
* added static `Command::$defaultName/getDefaultName()`, allowing for
|
||||
commands to be registered at compile time in the application command loader.
|
||||
Setting the `$defaultName` property avoids the need for filling the `command`
|
||||
attribute on the `console.command` tag when using `AddConsoleCommandPass`.
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
* added `ExceptionListener`
|
||||
* added `AddConsoleCommandPass` (originally in FrameworkBundle)
|
||||
* [BC BREAK] `Input::getOption()` no longer returns the default value for options
|
||||
with value optional explicitly passed empty
|
||||
* added console.error event to catch exceptions thrown by other listeners
|
||||
* deprecated console.exception event in favor of console.error
|
||||
* added ability to handle `CommandNotFoundException` through the
|
||||
`console.error` event
|
||||
* added `ExceptionListener`
|
||||
* added `AddConsoleCommandPass` (originally in FrameworkBundle)
|
||||
* [BC BREAK] `Input::getOption()` no longer returns the default value for options
|
||||
with value optional explicitly passed empty
|
||||
* added console.error event to catch exceptions thrown by other listeners
|
||||
* deprecated console.exception event in favor of console.error
|
||||
* added ability to handle `CommandNotFoundException` through the
|
||||
`console.error` event
|
||||
* deprecated default validation in `SymfonyQuestionHelper::ask`
|
||||
|
||||
3.2.0
|
||||
------
|
||||
|
||||
* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs
|
||||
* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface)
|
||||
* added StreamableInputInterface
|
||||
* added LockableTrait
|
||||
* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs
|
||||
* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface)
|
||||
* added StreamableInputInterface
|
||||
* added LockableTrait
|
||||
|
||||
3.1.0
|
||||
-----
|
||||
|
||||
* added truncate method to FormatterHelper
|
||||
* added setColumnWidth(s) method to Table
|
||||
* added setColumnWidth(s) method to Table
|
||||
|
||||
2.8.3
|
||||
-----
|
||||
|
||||
99
vendor/symfony/console/CI/GithubActionReporter.php
vendored
Normal file
99
vendor/symfony/console/CI/GithubActionReporter.php
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
<?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\CI;
|
||||
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Utility class for Github actions.
|
||||
*
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class GithubActionReporter
|
||||
{
|
||||
private $output;
|
||||
|
||||
/**
|
||||
* @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85
|
||||
*/
|
||||
private const ESCAPED_DATA = [
|
||||
'%' => '%25',
|
||||
"\r" => '%0D',
|
||||
"\n" => '%0A',
|
||||
];
|
||||
|
||||
/**
|
||||
* @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94
|
||||
*/
|
||||
private const ESCAPED_PROPERTIES = [
|
||||
'%' => '%25',
|
||||
"\r" => '%0D',
|
||||
"\n" => '%0A',
|
||||
':' => '%3A',
|
||||
',' => '%2C',
|
||||
];
|
||||
|
||||
public function __construct(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
public static function isGithubActionEnvironment(): bool
|
||||
{
|
||||
return false !== getenv('GITHUB_ACTIONS');
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an error using the Github annotations format.
|
||||
*
|
||||
* @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
|
||||
*/
|
||||
public function error(string $message, string $file = null, int $line = null, int $col = null): void
|
||||
{
|
||||
$this->log('error', $message, $file, $line, $col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output a warning using the Github annotations format.
|
||||
*
|
||||
* @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message
|
||||
*/
|
||||
public function warning(string $message, string $file = null, int $line = null, int $col = null): void
|
||||
{
|
||||
$this->log('warning', $message, $file, $line, $col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output a debug log using the Github annotations format.
|
||||
*
|
||||
* @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message
|
||||
*/
|
||||
public function debug(string $message, string $file = null, int $line = null, int $col = null): void
|
||||
{
|
||||
$this->log('debug', $message, $file, $line, $col);
|
||||
}
|
||||
|
||||
private function log(string $type, string $message, string $file = null, int $line = null, int $col = null): void
|
||||
{
|
||||
// Some values must be encoded.
|
||||
$message = strtr($message, self::ESCAPED_DATA);
|
||||
|
||||
if (!$file) {
|
||||
// No file provided, output the message solely:
|
||||
$this->output->writeln(sprintf('::%s::%s', $type, $message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->output->writeln(sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message));
|
||||
}
|
||||
}
|
||||
180
vendor/symfony/console/Color.php
vendored
Normal file
180
vendor/symfony/console/Color.php
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class Color
|
||||
{
|
||||
private const COLORS = [
|
||||
'black' => 0,
|
||||
'red' => 1,
|
||||
'green' => 2,
|
||||
'yellow' => 3,
|
||||
'blue' => 4,
|
||||
'magenta' => 5,
|
||||
'cyan' => 6,
|
||||
'white' => 7,
|
||||
'default' => 9,
|
||||
];
|
||||
|
||||
private const BRIGHT_COLORS = [
|
||||
'gray' => 0,
|
||||
'bright-red' => 1,
|
||||
'bright-green' => 2,
|
||||
'bright-yellow' => 3,
|
||||
'bright-blue' => 4,
|
||||
'bright-magenta' => 5,
|
||||
'bright-cyan' => 6,
|
||||
'bright-white' => 7,
|
||||
];
|
||||
|
||||
private const AVAILABLE_OPTIONS = [
|
||||
'bold' => ['set' => 1, 'unset' => 22],
|
||||
'underscore' => ['set' => 4, 'unset' => 24],
|
||||
'blink' => ['set' => 5, 'unset' => 25],
|
||||
'reverse' => ['set' => 7, 'unset' => 27],
|
||||
'conceal' => ['set' => 8, 'unset' => 28],
|
||||
];
|
||||
|
||||
private string $foreground;
|
||||
private string $background;
|
||||
private array $options = [];
|
||||
|
||||
public function __construct(string $foreground = '', string $background = '', array $options = [])
|
||||
{
|
||||
$this->foreground = $this->parseColor($foreground);
|
||||
$this->background = $this->parseColor($background, true);
|
||||
|
||||
foreach ($options as $option) {
|
||||
if (!isset(self::AVAILABLE_OPTIONS[$option])) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS))));
|
||||
}
|
||||
|
||||
$this->options[$option] = self::AVAILABLE_OPTIONS[$option];
|
||||
}
|
||||
}
|
||||
|
||||
public function apply(string $text): string
|
||||
{
|
||||
return $this->set().$text.$this->unset();
|
||||
}
|
||||
|
||||
public function set(): string
|
||||
{
|
||||
$setCodes = [];
|
||||
if ('' !== $this->foreground) {
|
||||
$setCodes[] = $this->foreground;
|
||||
}
|
||||
if ('' !== $this->background) {
|
||||
$setCodes[] = $this->background;
|
||||
}
|
||||
foreach ($this->options as $option) {
|
||||
$setCodes[] = $option['set'];
|
||||
}
|
||||
if (0 === \count($setCodes)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return sprintf("\033[%sm", implode(';', $setCodes));
|
||||
}
|
||||
|
||||
public function unset(): string
|
||||
{
|
||||
$unsetCodes = [];
|
||||
if ('' !== $this->foreground) {
|
||||
$unsetCodes[] = 39;
|
||||
}
|
||||
if ('' !== $this->background) {
|
||||
$unsetCodes[] = 49;
|
||||
}
|
||||
foreach ($this->options as $option) {
|
||||
$unsetCodes[] = $option['unset'];
|
||||
}
|
||||
if (0 === \count($unsetCodes)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return sprintf("\033[%sm", implode(';', $unsetCodes));
|
||||
}
|
||||
|
||||
private function parseColor(string $color, bool $background = false): string
|
||||
{
|
||||
if ('' === $color) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ('#' === $color[0]) {
|
||||
$color = substr($color, 1);
|
||||
|
||||
if (3 === \strlen($color)) {
|
||||
$color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2];
|
||||
}
|
||||
|
||||
if (6 !== \strlen($color)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid "%s" color.', $color));
|
||||
}
|
||||
|
||||
return ($background ? '4' : '3').$this->convertHexColorToAnsi(hexdec($color));
|
||||
}
|
||||
|
||||
if (isset(self::COLORS[$color])) {
|
||||
return ($background ? '4' : '3').self::COLORS[$color];
|
||||
}
|
||||
|
||||
if (isset(self::BRIGHT_COLORS[$color])) {
|
||||
return ($background ? '10' : '9').self::BRIGHT_COLORS[$color];
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS)))));
|
||||
}
|
||||
|
||||
private function convertHexColorToAnsi(int $color): string
|
||||
{
|
||||
$r = ($color >> 16) & 255;
|
||||
$g = ($color >> 8) & 255;
|
||||
$b = $color & 255;
|
||||
|
||||
// see https://github.com/termstandard/colors/ for more information about true color support
|
||||
if ('truecolor' !== getenv('COLORTERM')) {
|
||||
return (string) $this->degradeHexColorToAnsi($r, $g, $b);
|
||||
}
|
||||
|
||||
return sprintf('8;2;%d;%d;%d', $r, $g, $b);
|
||||
}
|
||||
|
||||
private function degradeHexColorToAnsi(int $r, int $g, int $b): int
|
||||
{
|
||||
if (0 === round($this->getSaturation($r, $g, $b) / 50)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255);
|
||||
}
|
||||
|
||||
private function getSaturation(int $r, int $g, int $b): int
|
||||
{
|
||||
$r = $r / 255;
|
||||
$g = $g / 255;
|
||||
$b = $b / 255;
|
||||
$v = max($r, $g, $b);
|
||||
|
||||
if (0 === $diff = $v - min($r, $g, $b)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) $diff * 100 / $v;
|
||||
}
|
||||
}
|
||||
367
vendor/symfony/console/Command/Command.php
vendored
367
vendor/symfony/console/Command/Command.php
vendored
@@ -11,16 +11,19 @@
|
||||
|
||||
namespace Symfony\Component\Console\Command;
|
||||
|
||||
use Symfony\Component\Console\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Exception\LogicException;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Base class for all commands.
|
||||
@@ -29,42 +32,91 @@ use Symfony\Component\Console\Exception\LogicException;
|
||||
*/
|
||||
class Command
|
||||
{
|
||||
private $application;
|
||||
private $name;
|
||||
private $processTitle;
|
||||
private $aliases = array();
|
||||
private $definition;
|
||||
private $hidden = false;
|
||||
private $help;
|
||||
private $description;
|
||||
private $ignoreValidationErrors = false;
|
||||
private $applicationDefinitionMerged = false;
|
||||
private $applicationDefinitionMergedWithArgs = false;
|
||||
private $code;
|
||||
private $synopsis = array();
|
||||
private $usages = array();
|
||||
private $helperSet;
|
||||
// see https://tldp.org/LDP/abs/html/exitcodes.html
|
||||
public const SUCCESS = 0;
|
||||
public const FAILURE = 1;
|
||||
public const INVALID = 2;
|
||||
|
||||
/**
|
||||
* @var string|null The default command name
|
||||
*/
|
||||
protected static $defaultName;
|
||||
|
||||
/**
|
||||
* @var string|null The default command description
|
||||
*/
|
||||
protected static $defaultDescription;
|
||||
|
||||
private $application = null;
|
||||
private ?string $name = null;
|
||||
private ?string $processTitle = null;
|
||||
private array $aliases = [];
|
||||
private $definition;
|
||||
private bool $hidden = false;
|
||||
private string $help = '';
|
||||
private string $description = '';
|
||||
private $fullDefinition = null;
|
||||
private bool $ignoreValidationErrors = false;
|
||||
private ?\Closure $code = null;
|
||||
private array $synopsis = [];
|
||||
private array $usages = [];
|
||||
private $helperSet = null;
|
||||
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
$class = static::class;
|
||||
|
||||
if ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) {
|
||||
return $attribute[0]->newInstance()->name;
|
||||
}
|
||||
|
||||
$r = new \ReflectionProperty($class, 'defaultName');
|
||||
|
||||
return $class === $r->class ? static::$defaultName : null;
|
||||
}
|
||||
|
||||
public static function getDefaultDescription(): ?string
|
||||
{
|
||||
$class = static::class;
|
||||
|
||||
if ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) {
|
||||
return $attribute[0]->newInstance()->description;
|
||||
}
|
||||
|
||||
$r = new \ReflectionProperty($class, 'defaultDescription');
|
||||
|
||||
return $class === $r->class ? static::$defaultDescription : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|null $name The name of the command; passing null means it must be set in configure()
|
||||
*
|
||||
* @throws LogicException When the command name is empty
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
public function __construct(string $name = null)
|
||||
{
|
||||
$this->definition = new InputDefinition();
|
||||
|
||||
if (null === $name && null !== $name = static::getDefaultName()) {
|
||||
$aliases = explode('|', $name);
|
||||
|
||||
if ('' === $name = array_shift($aliases)) {
|
||||
$this->setHidden(true);
|
||||
$name = array_shift($aliases);
|
||||
}
|
||||
|
||||
$this->setAliases($aliases);
|
||||
}
|
||||
|
||||
if (null !== $name) {
|
||||
$this->setName($name);
|
||||
}
|
||||
|
||||
$this->configure();
|
||||
|
||||
if (!$this->name) {
|
||||
throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
|
||||
if ('' === $this->description) {
|
||||
$this->setDescription(static::getDefaultDescription() ?? '');
|
||||
}
|
||||
|
||||
$this->configure();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,11 +129,6 @@ class Command
|
||||
$this->ignoreValidationErrors = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application instance for this command.
|
||||
*
|
||||
* @param Application $application An Application instance
|
||||
*/
|
||||
public function setApplication(Application $application = null)
|
||||
{
|
||||
$this->application = $application;
|
||||
@@ -90,13 +137,10 @@ class Command
|
||||
} else {
|
||||
$this->helperSet = null;
|
||||
}
|
||||
|
||||
$this->fullDefinition = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the helper set.
|
||||
*
|
||||
* @param HelperSet $helperSet A HelperSet instance
|
||||
*/
|
||||
public function setHelperSet(HelperSet $helperSet)
|
||||
{
|
||||
$this->helperSet = $helperSet;
|
||||
@@ -104,20 +148,16 @@ class Command
|
||||
|
||||
/**
|
||||
* Gets the helper set.
|
||||
*
|
||||
* @return HelperSet A HelperSet instance
|
||||
*/
|
||||
public function getHelperSet()
|
||||
public function getHelperSet(): ?HelperSet
|
||||
{
|
||||
return $this->helperSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the application instance for this command.
|
||||
*
|
||||
* @return Application An Application instance
|
||||
*/
|
||||
public function getApplication()
|
||||
public function getApplication(): ?Application
|
||||
{
|
||||
return $this->application;
|
||||
}
|
||||
@@ -125,7 +165,7 @@ class Command
|
||||
/**
|
||||
* Checks whether the command is enabled or not in the current environment.
|
||||
*
|
||||
* Override this to check for x or y and return false if the command can not
|
||||
* Override this to check for x or y and return false if the command cannot
|
||||
* run properly under the current conditions.
|
||||
*
|
||||
* @return bool
|
||||
@@ -150,10 +190,7 @@ class Command
|
||||
* execute() method, you set the code to execute by passing
|
||||
* a Closure to the setCode() method.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*
|
||||
* @return null|int null or 0 if everything went fine, or an error code
|
||||
* @return int 0 if everything went fine, or an exit code
|
||||
*
|
||||
* @throws LogicException When this abstract method is not implemented
|
||||
*
|
||||
@@ -170,22 +207,20 @@ class Command
|
||||
* This method is executed before the InputDefinition is validated.
|
||||
* This means that this is the only place where the command can
|
||||
* interactively ask for values of missing required arguments.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*/
|
||||
protected function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @see InputInterface::bind()
|
||||
* @see InputInterface::validate()
|
||||
*/
|
||||
protected function initialize(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
@@ -198,28 +233,21 @@ class Command
|
||||
* setCode() method or by overriding the execute() method
|
||||
* in a sub-class.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*
|
||||
* @return int The command exit code
|
||||
*
|
||||
* @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}.
|
||||
* @throws ExceptionInterface When input binding fails. Bypass this by calling {@link ignoreValidationErrors()}.
|
||||
*
|
||||
* @see setCode()
|
||||
* @see execute()
|
||||
*/
|
||||
public function run(InputInterface $input, OutputInterface $output)
|
||||
public function run(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
// force the creation of the synopsis before the merge with the app definition
|
||||
$this->getSynopsis(true);
|
||||
$this->getSynopsis(false);
|
||||
|
||||
// add the application arguments and options
|
||||
$this->mergeApplicationDefinition();
|
||||
|
||||
// bind the input against the command specific arguments/options
|
||||
try {
|
||||
$input->bind($this->definition);
|
||||
$input->bind($this->getDefinition());
|
||||
} catch (ExceptionInterface $e) {
|
||||
if (!$this->ignoreValidationErrors) {
|
||||
throw $e;
|
||||
@@ -229,16 +257,15 @@ class Command
|
||||
$this->initialize($input, $output);
|
||||
|
||||
if (null !== $this->processTitle) {
|
||||
if (function_exists('cli_set_process_title')) {
|
||||
if (false === @cli_set_process_title($this->processTitle)) {
|
||||
if ('Darwin' === PHP_OS) {
|
||||
$output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
|
||||
if (\function_exists('cli_set_process_title')) {
|
||||
if (!@cli_set_process_title($this->processTitle)) {
|
||||
if ('Darwin' === \PHP_OS) {
|
||||
$output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
|
||||
} else {
|
||||
$error = error_get_last();
|
||||
trigger_error($error['message'], E_USER_WARNING);
|
||||
cli_set_process_title($this->processTitle);
|
||||
}
|
||||
}
|
||||
} elseif (function_exists('setproctitle')) {
|
||||
} elseif (\function_exists('setproctitle')) {
|
||||
setproctitle($this->processTitle);
|
||||
} elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
|
||||
$output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
|
||||
@@ -259,14 +286,25 @@ class Command
|
||||
$input->validate();
|
||||
|
||||
if ($this->code) {
|
||||
$statusCode = call_user_func($this->code, $input, $output);
|
||||
$statusCode = ($this->code)($input, $output);
|
||||
} else {
|
||||
$statusCode = $this->execute($input, $output);
|
||||
|
||||
if (!\is_int($statusCode)) {
|
||||
throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode)));
|
||||
}
|
||||
}
|
||||
|
||||
return is_numeric($statusCode) ? (int) $statusCode : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds suggestions to $suggestions for the current completion input (e.g. option or argument).
|
||||
*/
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the code to execute when running this command.
|
||||
*
|
||||
@@ -281,21 +319,22 @@ class Command
|
||||
*
|
||||
* @see execute()
|
||||
*/
|
||||
public function setCode(callable $code)
|
||||
public function setCode(callable $code): static
|
||||
{
|
||||
if ($code instanceof \Closure) {
|
||||
$r = new \ReflectionFunction($code);
|
||||
if (null === $r->getClosureThis()) {
|
||||
if (\PHP_VERSION_ID < 70000) {
|
||||
// Bug in PHP5: https://bugs.php.net/bug.php?id=64761
|
||||
// This means that we cannot bind static closures and therefore we must
|
||||
// ignore any errors here. There is no way to test if the closure is
|
||||
// bindable.
|
||||
$code = @\Closure::bind($code, $this);
|
||||
} else {
|
||||
$code = \Closure::bind($code, $this);
|
||||
set_error_handler(static function () {});
|
||||
try {
|
||||
if ($c = \Closure::bind($code, $this)) {
|
||||
$code = $c;
|
||||
}
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$code = \Closure::fromCallable($code);
|
||||
}
|
||||
|
||||
$this->code = $code;
|
||||
@@ -309,35 +348,33 @@ class Command
|
||||
* This method is not part of public API and should not be used directly.
|
||||
*
|
||||
* @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function mergeApplicationDefinition($mergeArgs = true)
|
||||
public function mergeApplicationDefinition(bool $mergeArgs = true)
|
||||
{
|
||||
if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
|
||||
if (null === $this->application) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->definition->addOptions($this->application->getDefinition()->getOptions());
|
||||
$this->fullDefinition = new InputDefinition();
|
||||
$this->fullDefinition->setOptions($this->definition->getOptions());
|
||||
$this->fullDefinition->addOptions($this->application->getDefinition()->getOptions());
|
||||
|
||||
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;
|
||||
$this->fullDefinition->setArguments($this->application->getDefinition()->getArguments());
|
||||
$this->fullDefinition->addArguments($this->definition->getArguments());
|
||||
} else {
|
||||
$this->fullDefinition->setArguments($this->definition->getArguments());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an array of argument and option instances.
|
||||
*
|
||||
* @param array|InputDefinition $definition An array of argument and option instances or a definition instance
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefinition($definition)
|
||||
public function setDefinition(array|InputDefinition $definition): static
|
||||
{
|
||||
if ($definition instanceof InputDefinition) {
|
||||
$this->definition = $definition;
|
||||
@@ -345,19 +382,17 @@ class Command
|
||||
$this->definition->setDefinition($definition);
|
||||
}
|
||||
|
||||
$this->applicationDefinitionMerged = false;
|
||||
$this->fullDefinition = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the InputDefinition attached to this Command.
|
||||
*
|
||||
* @return InputDefinition An InputDefinition instance
|
||||
*/
|
||||
public function getDefinition()
|
||||
public function getDefinition(): InputDefinition
|
||||
{
|
||||
return $this->definition;
|
||||
return $this->fullDefinition ?? $this->getNativeDefinition();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,27 +402,28 @@ class Command
|
||||
* be changed by merging with the application InputDefinition.
|
||||
*
|
||||
* This method is not part of public API and should not be used directly.
|
||||
*
|
||||
* @return InputDefinition An InputDefinition instance
|
||||
*/
|
||||
public function getNativeDefinition()
|
||||
public function getNativeDefinition(): InputDefinition
|
||||
{
|
||||
return $this->getDefinition();
|
||||
return $this->definition ?? throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
|
||||
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
|
||||
*
|
||||
* @throws InvalidArgumentException When argument mode is not valid
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addArgument($name, $mode = null, $description = '', $default = null)
|
||||
public function addArgument(string $name, int $mode = null, string $description = '', mixed $default = null): static
|
||||
{
|
||||
$this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
|
||||
if (null !== $this->fullDefinition) {
|
||||
$this->fullDefinition->addArgument(new InputArgument($name, $mode, $description, $default));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -395,17 +431,20 @@ 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 $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
|
||||
* @param $mode The option mode: One of the InputOption::VALUE_* constants
|
||||
* @param $default The default value (must be null for InputOption::VALUE_NONE)
|
||||
*
|
||||
* @throws InvalidArgumentException If option mode is invalid or incompatible
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
|
||||
public function addOption(string $name, string|array $shortcut = null, int $mode = null, string $description = '', mixed $default = null): static
|
||||
{
|
||||
$this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
|
||||
if (null !== $this->fullDefinition) {
|
||||
$this->fullDefinition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -418,13 +457,11 @@ class Command
|
||||
*
|
||||
* $command->setName('foo:bar');
|
||||
*
|
||||
* @param string $name The command name
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException When the name is invalid
|
||||
*/
|
||||
public function setName($name)
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->validateName($name);
|
||||
|
||||
@@ -439,13 +476,9 @@ class Command
|
||||
* This feature should be used only when creating a long process command,
|
||||
* like a daemon.
|
||||
*
|
||||
* PHP 5.5+ or the proctitle PECL library is required
|
||||
*
|
||||
* @param string $title The process title
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setProcessTitle($title)
|
||||
public function setProcessTitle(string $title): static
|
||||
{
|
||||
$this->processTitle = $title;
|
||||
|
||||
@@ -454,10 +487,8 @@ class Command
|
||||
|
||||
/**
|
||||
* Returns the command name.
|
||||
*
|
||||
* @return string The command name
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
@@ -465,19 +496,19 @@ class Command
|
||||
/**
|
||||
* @param bool $hidden Whether or not the command should be hidden from the list of commands
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setHidden($hidden)
|
||||
public function setHidden(bool $hidden = true): static
|
||||
{
|
||||
$this->hidden = (bool) $hidden;
|
||||
$this->hidden = $hidden;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool Whether the command should be publicly shown or not.
|
||||
* @return bool whether the command should be publicly shown or not
|
||||
*/
|
||||
public function isHidden()
|
||||
public function isHidden(): bool
|
||||
{
|
||||
return $this->hidden;
|
||||
}
|
||||
@@ -485,11 +516,9 @@ class Command
|
||||
/**
|
||||
* Sets the description for the command.
|
||||
*
|
||||
* @param string $description The description for the command
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDescription($description)
|
||||
public function setDescription(string $description): static
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
@@ -498,10 +527,8 @@ class Command
|
||||
|
||||
/**
|
||||
* Returns the description for the command.
|
||||
*
|
||||
* @return string The description for the command
|
||||
*/
|
||||
public function getDescription()
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
@@ -509,11 +536,9 @@ class Command
|
||||
/**
|
||||
* Sets the help for the command.
|
||||
*
|
||||
* @param string $help The help for the command
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHelp($help)
|
||||
public function setHelp(string $help): static
|
||||
{
|
||||
$this->help = $help;
|
||||
|
||||
@@ -522,10 +547,8 @@ class Command
|
||||
|
||||
/**
|
||||
* Returns the help for the command.
|
||||
*
|
||||
* @return string The help for the command
|
||||
*/
|
||||
public function getHelp()
|
||||
public function getHelp(): string
|
||||
{
|
||||
return $this->help;
|
||||
}
|
||||
@@ -533,21 +556,20 @@ class Command
|
||||
/**
|
||||
* Returns the processed help for the command replacing the %command.name% and
|
||||
* %command.full_name% patterns with the real values dynamically.
|
||||
*
|
||||
* @return string The processed help for the command
|
||||
*/
|
||||
public function getProcessedHelp()
|
||||
public function getProcessedHelp(): string
|
||||
{
|
||||
$name = $this->name;
|
||||
$isSingleCommand = $this->application && $this->application->isSingleCommand();
|
||||
|
||||
$placeholders = array(
|
||||
$placeholders = [
|
||||
'%command.name%',
|
||||
'%command.full_name%',
|
||||
);
|
||||
$replacements = array(
|
||||
];
|
||||
$replacements = [
|
||||
$name,
|
||||
$_SERVER['PHP_SELF'].' '.$name,
|
||||
);
|
||||
$isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name,
|
||||
];
|
||||
|
||||
return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
|
||||
}
|
||||
@@ -561,27 +583,24 @@ class Command
|
||||
*
|
||||
* @throws InvalidArgumentException When an alias is invalid
|
||||
*/
|
||||
public function setAliases($aliases)
|
||||
public function setAliases(iterable $aliases): static
|
||||
{
|
||||
if (!is_array($aliases) && !$aliases instanceof \Traversable) {
|
||||
throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
|
||||
}
|
||||
$list = [];
|
||||
|
||||
foreach ($aliases as $alias) {
|
||||
$this->validateName($alias);
|
||||
$list[] = $alias;
|
||||
}
|
||||
|
||||
$this->aliases = $aliases;
|
||||
$this->aliases = \is_array($aliases) ? $aliases : $list;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the aliases for the command.
|
||||
*
|
||||
* @return array An array of aliases for the command
|
||||
*/
|
||||
public function getAliases()
|
||||
public function getAliases(): array
|
||||
{
|
||||
return $this->aliases;
|
||||
}
|
||||
@@ -590,10 +609,8 @@ class Command
|
||||
* Returns the synopsis for the command.
|
||||
*
|
||||
* @param bool $short Whether to show the short version of the synopsis (with options folded) or not
|
||||
*
|
||||
* @return string The synopsis
|
||||
*/
|
||||
public function getSynopsis($short = false)
|
||||
public function getSynopsis(bool $short = false): string
|
||||
{
|
||||
$key = $short ? 'short' : 'long';
|
||||
|
||||
@@ -605,15 +622,13 @@ class Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a command usage example.
|
||||
*
|
||||
* @param string $usage The usage, it'll be prefixed with the command name
|
||||
* Add a command usage example, it'll be prefixed with the command name.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addUsage($usage)
|
||||
public function addUsage(string $usage): static
|
||||
{
|
||||
if (0 !== strpos($usage, $this->name)) {
|
||||
if (!str_starts_with($usage, $this->name)) {
|
||||
$usage = sprintf('%s %s', $this->name, $usage);
|
||||
}
|
||||
|
||||
@@ -624,10 +639,8 @@ class Command
|
||||
|
||||
/**
|
||||
* Returns alternative usages of the command.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUsages()
|
||||
public function getUsages(): array
|
||||
{
|
||||
return $this->usages;
|
||||
}
|
||||
@@ -635,14 +648,10 @@ class Command
|
||||
/**
|
||||
* Gets a helper instance by name.
|
||||
*
|
||||
* @param string $name The helper name
|
||||
*
|
||||
* @return mixed The helper value
|
||||
*
|
||||
* @throws LogicException if no HelperSet is defined
|
||||
* @throws InvalidArgumentException if the helper is not defined
|
||||
*/
|
||||
public function getHelper($name)
|
||||
public function getHelper(string $name): mixed
|
||||
{
|
||||
if (null === $this->helperSet) {
|
||||
throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
|
||||
@@ -656,11 +665,9 @@ class Command
|
||||
*
|
||||
* It must be non-empty and parts can optionally be separated by ":".
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @throws InvalidArgumentException When the name is invalid
|
||||
*/
|
||||
private function validateName($name)
|
||||
private function validateName(string $name)
|
||||
{
|
||||
if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
|
||||
throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
|
||||
|
||||
205
vendor/symfony/console/Command/CompleteCommand.php
vendored
Normal file
205
vendor/symfony/console/Command/CompleteCommand.php
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Completion\Output\BashCompletionOutput;
|
||||
use Symfony\Component\Console\Completion\Output\CompletionOutputInterface;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
use Symfony\Component\Console\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Responsible for providing the values to the shell completion.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
final class CompleteCommand extends Command
|
||||
{
|
||||
protected static $defaultName = '|_complete';
|
||||
protected static $defaultDescription = 'Internal command to provide shell completion suggestions';
|
||||
|
||||
private $completionOutputs;
|
||||
|
||||
private $isDebug = false;
|
||||
|
||||
/**
|
||||
* @param array<string, class-string<CompletionOutputInterface>> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value
|
||||
*/
|
||||
public function __construct(array $completionOutputs = [])
|
||||
{
|
||||
// must be set before the parent constructor, as the property value is used in configure()
|
||||
$this->completionOutputs = $completionOutputs + ['bash' => BashCompletionOutput::class];
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("'.implode('", "', array_keys($this->completionOutputs)).'")')
|
||||
->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)')
|
||||
->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)')
|
||||
->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'The version of the completion script')
|
||||
;
|
||||
}
|
||||
|
||||
protected function initialize(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
try {
|
||||
// uncomment when a bugfix or BC break has been introduced in the shell completion scripts
|
||||
// $version = $input->getOption('symfony');
|
||||
// if ($version && version_compare($version, 'x.y', '>=')) {
|
||||
// $message = sprintf('Completion script version is not supported ("%s" given, ">=x.y" required).', $version);
|
||||
// $this->log($message);
|
||||
|
||||
// $output->writeln($message.' Install the Symfony completion script again by using the "completion" command.');
|
||||
|
||||
// return 126;
|
||||
// }
|
||||
|
||||
$shell = $input->getOption('shell');
|
||||
if (!$shell) {
|
||||
throw new \RuntimeException('The "--shell" option must be set.');
|
||||
}
|
||||
|
||||
if (!$completionOutput = $this->completionOutputs[$shell] ?? false) {
|
||||
throw new \RuntimeException(sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs))));
|
||||
}
|
||||
|
||||
$completionInput = $this->createCompletionInput($input);
|
||||
$suggestions = new CompletionSuggestions();
|
||||
|
||||
$this->log([
|
||||
'',
|
||||
'<comment>'.date('Y-m-d H:i:s').'</>',
|
||||
'<info>Input:</> <comment>("|" indicates the cursor position)</>',
|
||||
' '.(string) $completionInput,
|
||||
'<info>Command:</>',
|
||||
' '.(string) implode(' ', $_SERVER['argv']),
|
||||
'<info>Messages:</>',
|
||||
]);
|
||||
|
||||
$command = $this->findCommand($completionInput, $output);
|
||||
if (null === $command) {
|
||||
$this->log(' No command found, completing using the Application class.');
|
||||
|
||||
$this->getApplication()->complete($completionInput, $suggestions);
|
||||
} elseif (
|
||||
$completionInput->mustSuggestArgumentValuesFor('command')
|
||||
&& $command->getName() !== $completionInput->getCompletionValue()
|
||||
&& !\in_array($completionInput->getCompletionValue(), $command->getAliases(), true)
|
||||
) {
|
||||
$this->log(' No command found, completing using the Application class.');
|
||||
|
||||
// expand shortcut names ("cache:cl<TAB>") into their full name ("cache:clear")
|
||||
$suggestions->suggestValues(array_filter(array_merge([$command->getName()], $command->getAliases())));
|
||||
} else {
|
||||
$command->mergeApplicationDefinition();
|
||||
$completionInput->bind($command->getDefinition());
|
||||
|
||||
if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) {
|
||||
$this->log(' Completing option names for the <comment>'.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).'</> command.');
|
||||
|
||||
$suggestions->suggestOptions($command->getDefinition()->getOptions());
|
||||
} else {
|
||||
$this->log([
|
||||
' Completing using the <comment>'.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).'</> class.',
|
||||
' Completing <comment>'.$completionInput->getCompletionType().'</> for <comment>'.$completionInput->getCompletionName().'</>',
|
||||
]);
|
||||
if (null !== $compval = $completionInput->getCompletionValue()) {
|
||||
$this->log(' Current value: <comment>'.$compval.'</>');
|
||||
}
|
||||
|
||||
$command->complete($completionInput, $suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
/** @var CompletionOutputInterface $completionOutput */
|
||||
$completionOutput = new $completionOutput();
|
||||
|
||||
$this->log('<info>Suggestions:</>');
|
||||
if ($options = $suggestions->getOptionSuggestions()) {
|
||||
$this->log(' --'.implode(' --', array_map(function ($o) { return $o->getName(); }, $options)));
|
||||
} elseif ($values = $suggestions->getValueSuggestions()) {
|
||||
$this->log(' '.implode(' ', $values));
|
||||
} else {
|
||||
$this->log(' <comment>No suggestions were provided</>');
|
||||
}
|
||||
|
||||
$completionOutput->write($suggestions, $output);
|
||||
} catch (\Throwable $e) {
|
||||
$this->log([
|
||||
'<error>Error!</error>',
|
||||
(string) $e,
|
||||
]);
|
||||
|
||||
if ($output->isDebug()) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function createCompletionInput(InputInterface $input): CompletionInput
|
||||
{
|
||||
$currentIndex = $input->getOption('current');
|
||||
if (!$currentIndex || !ctype_digit($currentIndex)) {
|
||||
throw new \RuntimeException('The "--current" option must be set and it must be an integer.');
|
||||
}
|
||||
|
||||
$completionInput = CompletionInput::fromTokens($input->getOption('input'), (int) $currentIndex);
|
||||
|
||||
try {
|
||||
$completionInput->bind($this->getApplication()->getDefinition());
|
||||
} catch (ExceptionInterface $e) {
|
||||
}
|
||||
|
||||
return $completionInput;
|
||||
}
|
||||
|
||||
private function findCommand(CompletionInput $completionInput, OutputInterface $output): ?Command
|
||||
{
|
||||
try {
|
||||
$inputName = $completionInput->getFirstArgument();
|
||||
if (null === $inputName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getApplication()->find($inputName);
|
||||
} catch (CommandNotFoundException $e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function log($messages): void
|
||||
{
|
||||
if (!$this->isDebug) {
|
||||
return;
|
||||
}
|
||||
|
||||
$commandName = basename($_SERVER['argv'][0]);
|
||||
file_put_contents(sys_get_temp_dir().'/sf_'.$commandName.'.log', implode(\PHP_EOL, (array) $messages).\PHP_EOL, \FILE_APPEND);
|
||||
}
|
||||
}
|
||||
139
vendor/symfony/console/Command/DumpCompletionCommand.php
vendored
Normal file
139
vendor/symfony/console/Command/DumpCompletionCommand.php
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
/**
|
||||
* Dumps the completion script for the current shell.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
final class DumpCompletionCommand extends Command
|
||||
{
|
||||
protected static $defaultName = 'completion';
|
||||
protected static $defaultDescription = 'Dump the shell completion script';
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestArgumentValuesFor('shell')) {
|
||||
$suggestions->suggestValues($this->getSupportedShells());
|
||||
}
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$fullCommand = $_SERVER['PHP_SELF'];
|
||||
$commandName = basename($fullCommand);
|
||||
$fullCommand = @realpath($fullCommand) ?: $fullCommand;
|
||||
|
||||
$this
|
||||
->setHelp(<<<EOH
|
||||
The <info>%command.name%</> command dumps the shell completion script required
|
||||
to use shell autocompletion (currently only bash completion is supported).
|
||||
|
||||
<comment>Static installation
|
||||
-------------------</>
|
||||
|
||||
Dump the script to a global completion file and restart your shell:
|
||||
|
||||
<info>%command.full_name% bash | sudo tee /etc/bash_completion.d/{$commandName}</>
|
||||
|
||||
Or dump the script to a local file and source it:
|
||||
|
||||
<info>%command.full_name% bash > completion.sh</>
|
||||
|
||||
<comment># source the file whenever you use the project</>
|
||||
<info>source completion.sh</>
|
||||
|
||||
<comment># or add this line at the end of your "~/.bashrc" file:</>
|
||||
<info>source /path/to/completion.sh</>
|
||||
|
||||
<comment>Dynamic installation
|
||||
--------------------</>
|
||||
|
||||
Add this to the end of your shell configuration file (e.g. <info>"~/.bashrc"</>):
|
||||
|
||||
<info>eval "$({$fullCommand} completion bash)"</>
|
||||
EOH
|
||||
)
|
||||
->addArgument('shell', InputArgument::OPTIONAL, 'The shell type (e.g. "bash"), the value of the "$SHELL" env var will be used if this is not given')
|
||||
->addOption('debug', null, InputOption::VALUE_NONE, 'Tail the completion debug log')
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$commandName = basename($_SERVER['argv'][0]);
|
||||
|
||||
if ($input->getOption('debug')) {
|
||||
$this->tailDebugLog($commandName, $output);
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$shell = $input->getArgument('shell') ?? self::guessShell();
|
||||
$completionFile = __DIR__.'/../Resources/completion.'.$shell;
|
||||
if (!file_exists($completionFile)) {
|
||||
$supportedShells = $this->getSupportedShells();
|
||||
|
||||
if ($output instanceof ConsoleOutputInterface) {
|
||||
$output = $output->getErrorOutput();
|
||||
}
|
||||
if ($shell) {
|
||||
$output->writeln(sprintf('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, implode('", "', $supportedShells)));
|
||||
} else {
|
||||
$output->writeln(sprintf('<error>Shell not detected, Symfony shell completion only supports "%s").</>', implode('", "', $supportedShells)));
|
||||
}
|
||||
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
$output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, $this->getApplication()->getVersion()], file_get_contents($completionFile)));
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private static function guessShell(): string
|
||||
{
|
||||
return basename($_SERVER['SHELL'] ?? '');
|
||||
}
|
||||
|
||||
private function tailDebugLog(string $commandName, OutputInterface $output): void
|
||||
{
|
||||
$debugFile = sys_get_temp_dir().'/sf_'.$commandName.'.log';
|
||||
if (!file_exists($debugFile)) {
|
||||
touch($debugFile);
|
||||
}
|
||||
$process = new Process(['tail', '-f', $debugFile], null, null, null, 0);
|
||||
$process->run(function (string $type, string $line) use ($output): void {
|
||||
$output->write($line);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getSupportedShells(): array
|
||||
{
|
||||
return array_map(function ($f) {
|
||||
return pathinfo($f, \PATHINFO_EXTENSION);
|
||||
}, glob(__DIR__.'/../Resources/completion.*'));
|
||||
}
|
||||
}
|
||||
49
vendor/symfony/console/Command/HelpCommand.php
vendored
49
vendor/symfony/console/Command/HelpCommand.php
vendored
@@ -11,10 +11,13 @@
|
||||
|
||||
namespace Symfony\Component\Console\Command;
|
||||
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Descriptor\ApplicationDescription;
|
||||
use Symfony\Component\Console\Helper\DescriptorHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
@@ -35,20 +38,20 @@ class HelpCommand extends Command
|
||||
|
||||
$this
|
||||
->setName('help')
|
||||
->setDefinition(array(
|
||||
->setDefinition([
|
||||
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
|
||||
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
|
||||
))
|
||||
->setDescription('Displays help for a command')
|
||||
])
|
||||
->setDescription('Display help for a command')
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command displays help for a given command:
|
||||
|
||||
<info>php %command.full_name% list</info>
|
||||
<info>%command.full_name% list</info>
|
||||
|
||||
You can also output the help in other formats by using the <comment>--format</comment> option:
|
||||
|
||||
<info>php %command.full_name% --format=xml list</info>
|
||||
<info>%command.full_name% --format=xml list</info>
|
||||
|
||||
To display the list of available commands, please use the <info>list</info> command.
|
||||
EOF
|
||||
@@ -56,11 +59,6 @@ EOF
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command.
|
||||
*
|
||||
* @param Command $command The command to set
|
||||
*/
|
||||
public function setCommand(Command $command)
|
||||
{
|
||||
$this->command = $command;
|
||||
@@ -69,18 +67,33 @@ EOF
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
if (null === $this->command) {
|
||||
$this->command = $this->getApplication()->find($input->getArgument('command_name'));
|
||||
}
|
||||
$this->command ??= $this->getApplication()->find($input->getArgument('command_name'));
|
||||
|
||||
$helper = new DescriptorHelper();
|
||||
$helper->describe($output, $this->command, array(
|
||||
$helper->describe($output, $this->command, [
|
||||
'format' => $input->getOption('format'),
|
||||
'raw_text' => $input->getOption('raw'),
|
||||
));
|
||||
]);
|
||||
|
||||
$this->command = null;
|
||||
unset($this->command);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestArgumentValuesFor('command_name')) {
|
||||
$descriptor = new ApplicationDescription($this->getApplication());
|
||||
$suggestions->suggestValues(array_keys($descriptor->getCommands()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->mustSuggestOptionValuesFor('format')) {
|
||||
$helper = new DescriptorHelper();
|
||||
$suggestions->suggestValues($helper->getFormats());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
194
vendor/symfony/console/Command/LazyCommand.php
vendored
Normal file
194
vendor/symfony/console/Command/LazyCommand.php
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class LazyCommand extends Command
|
||||
{
|
||||
private $command;
|
||||
private ?bool $isEnabled;
|
||||
|
||||
public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = true)
|
||||
{
|
||||
$this->setName($name)
|
||||
->setAliases($aliases)
|
||||
->setHidden($isHidden)
|
||||
->setDescription($description);
|
||||
|
||||
$this->command = $commandFactory;
|
||||
$this->isEnabled = $isEnabled;
|
||||
}
|
||||
|
||||
public function ignoreValidationErrors(): void
|
||||
{
|
||||
$this->getCommand()->ignoreValidationErrors();
|
||||
}
|
||||
|
||||
public function setApplication(Application $application = null): void
|
||||
{
|
||||
if ($this->command instanceof parent) {
|
||||
$this->command->setApplication($application);
|
||||
}
|
||||
|
||||
parent::setApplication($application);
|
||||
}
|
||||
|
||||
public function setHelperSet(HelperSet $helperSet): void
|
||||
{
|
||||
if ($this->command instanceof parent) {
|
||||
$this->command->setHelperSet($helperSet);
|
||||
}
|
||||
|
||||
parent::setHelperSet($helperSet);
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->isEnabled ?? $this->getCommand()->isEnabled();
|
||||
}
|
||||
|
||||
public function run(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return $this->getCommand()->run($input, $output);
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
$this->getCommand()->complete($input, $suggestions);
|
||||
}
|
||||
|
||||
public function setCode(callable $code): static
|
||||
{
|
||||
$this->getCommand()->setCode($code);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function mergeApplicationDefinition(bool $mergeArgs = true): void
|
||||
{
|
||||
$this->getCommand()->mergeApplicationDefinition($mergeArgs);
|
||||
}
|
||||
|
||||
public function setDefinition(array|InputDefinition $definition): static
|
||||
{
|
||||
$this->getCommand()->setDefinition($definition);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDefinition(): InputDefinition
|
||||
{
|
||||
return $this->getCommand()->getDefinition();
|
||||
}
|
||||
|
||||
public function getNativeDefinition(): InputDefinition
|
||||
{
|
||||
return $this->getCommand()->getNativeDefinition();
|
||||
}
|
||||
|
||||
public function addArgument(string $name, int $mode = null, string $description = '', mixed $default = null): static
|
||||
{
|
||||
$this->getCommand()->addArgument($name, $mode, $description, $default);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addOption(string $name, string|array $shortcut = null, int $mode = null, string $description = '', mixed $default = null): static
|
||||
{
|
||||
$this->getCommand()->addOption($name, $shortcut, $mode, $description, $default);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setProcessTitle(string $title): static
|
||||
{
|
||||
$this->getCommand()->setProcessTitle($title);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHelp(string $help): static
|
||||
{
|
||||
$this->getCommand()->setHelp($help);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHelp(): string
|
||||
{
|
||||
return $this->getCommand()->getHelp();
|
||||
}
|
||||
|
||||
public function getProcessedHelp(): string
|
||||
{
|
||||
return $this->getCommand()->getProcessedHelp();
|
||||
}
|
||||
|
||||
public function getSynopsis(bool $short = false): string
|
||||
{
|
||||
return $this->getCommand()->getSynopsis($short);
|
||||
}
|
||||
|
||||
public function addUsage(string $usage): static
|
||||
{
|
||||
$this->getCommand()->addUsage($usage);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUsages(): array
|
||||
{
|
||||
return $this->getCommand()->getUsages();
|
||||
}
|
||||
|
||||
public function getHelper(string $name): mixed
|
||||
{
|
||||
return $this->getCommand()->getHelper($name);
|
||||
}
|
||||
|
||||
public function getCommand(): parent
|
||||
{
|
||||
if (!$this->command instanceof \Closure) {
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
$command = $this->command = ($this->command)();
|
||||
$command->setApplication($this->getApplication());
|
||||
|
||||
if (null !== $this->getHelperSet()) {
|
||||
$command->setHelperSet($this->getHelperSet());
|
||||
}
|
||||
|
||||
$command->setName($this->getName())
|
||||
->setAliases($this->getAliases())
|
||||
->setHidden($this->isHidden())
|
||||
->setDescription($this->getDescription());
|
||||
|
||||
// Will throw if the command is not correctly initialized.
|
||||
$command->getDefinition();
|
||||
|
||||
return $command;
|
||||
}
|
||||
}
|
||||
61
vendor/symfony/console/Command/ListCommand.php
vendored
61
vendor/symfony/console/Command/ListCommand.php
vendored
@@ -11,12 +11,14 @@
|
||||
|
||||
namespace Symfony\Component\Console\Command;
|
||||
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Descriptor\ApplicationDescription;
|
||||
use Symfony\Component\Console\Helper\DescriptorHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
|
||||
/**
|
||||
* ListCommand displays the list of all available commands for the application.
|
||||
@@ -32,24 +34,29 @@ class ListCommand extends Command
|
||||
{
|
||||
$this
|
||||
->setName('list')
|
||||
->setDefinition($this->createDefinition())
|
||||
->setDescription('Lists commands')
|
||||
->setDefinition([
|
||||
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
|
||||
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
|
||||
new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments'),
|
||||
])
|
||||
->setDescription('List commands')
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command lists all commands:
|
||||
|
||||
<info>php %command.full_name%</info>
|
||||
<info>%command.full_name%</info>
|
||||
|
||||
You can also display the commands for a specific namespace:
|
||||
|
||||
<info>php %command.full_name% test</info>
|
||||
<info>%command.full_name% test</info>
|
||||
|
||||
You can also output the information in other formats by using the <comment>--format</comment> option:
|
||||
|
||||
<info>php %command.full_name% --format=xml</info>
|
||||
<info>%command.full_name% --format=xml</info>
|
||||
|
||||
It's also possible to get raw list of commands (useful for embedding command runner):
|
||||
|
||||
<info>php %command.full_name% --raw</info>
|
||||
<info>%command.full_name% --raw</info>
|
||||
EOF
|
||||
)
|
||||
;
|
||||
@@ -58,33 +65,31 @@ EOF
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNativeDefinition()
|
||||
{
|
||||
return $this->createDefinition();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$helper = new DescriptorHelper();
|
||||
$helper->describe($output, $this->getApplication(), array(
|
||||
$helper->describe($output, $this->getApplication(), [
|
||||
'format' => $input->getOption('format'),
|
||||
'raw_text' => $input->getOption('raw'),
|
||||
'namespace' => $input->getArgument('namespace'),
|
||||
));
|
||||
'short' => $input->getOption('short'),
|
||||
]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private function createDefinition()
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
return new InputDefinition(array(
|
||||
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
|
||||
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
|
||||
));
|
||||
if ($input->mustSuggestArgumentValuesFor('namespace')) {
|
||||
$descriptor = new ApplicationDescription($this->getApplication());
|
||||
$suggestions->suggestValues(array_keys($descriptor->getNamespaces()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->mustSuggestOptionValuesFor('format')) {
|
||||
$helper = new DescriptorHelper();
|
||||
$suggestions->suggestValues($helper->getFormats());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
vendor/symfony/console/Command/LockableTrait.php
vendored
34
vendor/symfony/console/Command/LockableTrait.php
vendored
@@ -12,8 +12,9 @@
|
||||
namespace Symfony\Component\Console\Command;
|
||||
|
||||
use Symfony\Component\Console\Exception\LogicException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Filesystem\LockHandler;
|
||||
use Symfony\Component\Lock\LockFactory;
|
||||
use Symfony\Component\Lock\Store\FlockStore;
|
||||
use Symfony\Component\Lock\Store\SemaphoreStore;
|
||||
|
||||
/**
|
||||
* Basic lock feature for commands.
|
||||
@@ -22,27 +23,30 @@ use Symfony\Component\Filesystem\LockHandler;
|
||||
*/
|
||||
trait LockableTrait
|
||||
{
|
||||
private $lockHandler;
|
||||
private $lock = null;
|
||||
|
||||
/**
|
||||
* Locks a command.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function lock($name = null, $blocking = false)
|
||||
private function lock(string $name = null, bool $blocking = false): bool
|
||||
{
|
||||
if (!class_exists(LockHandler::class)) {
|
||||
throw new RuntimeException('To enable the locking feature you must install the symfony/filesystem component.');
|
||||
if (!class_exists(SemaphoreStore::class)) {
|
||||
throw new LogicException('To enable the locking feature you must install the symfony/lock component.');
|
||||
}
|
||||
|
||||
if (null !== $this->lockHandler) {
|
||||
if (null !== $this->lock) {
|
||||
throw new LogicException('A lock is already in place.');
|
||||
}
|
||||
|
||||
$this->lockHandler = new LockHandler($name ?: $this->getName());
|
||||
if (SemaphoreStore::isSupported()) {
|
||||
$store = new SemaphoreStore();
|
||||
} else {
|
||||
$store = new FlockStore();
|
||||
}
|
||||
|
||||
if (!$this->lockHandler->lock($blocking)) {
|
||||
$this->lockHandler = null;
|
||||
$this->lock = (new LockFactory($store))->createLock($name ?: $this->getName());
|
||||
if (!$this->lock->acquire($blocking)) {
|
||||
$this->lock = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -55,9 +59,9 @@ trait LockableTrait
|
||||
*/
|
||||
private function release()
|
||||
{
|
||||
if ($this->lockHandler) {
|
||||
$this->lockHandler->release();
|
||||
$this->lockHandler = null;
|
||||
if ($this->lock) {
|
||||
$this->lock->release();
|
||||
$this->lock = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
vendor/symfony/console/Command/SignalableCommandInterface.php
vendored
Normal file
30
vendor/symfony/console/Command/SignalableCommandInterface.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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\Command;
|
||||
|
||||
/**
|
||||
* Interface for command reacting to signal.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrix.info>
|
||||
*/
|
||||
interface SignalableCommandInterface
|
||||
{
|
||||
/**
|
||||
* Returns the list of signals to subscribe.
|
||||
*/
|
||||
public function getSubscribedSignals(): array;
|
||||
|
||||
/**
|
||||
* The method will be called when the application is signaled.
|
||||
*/
|
||||
public function handleSignal(int $signal): void;
|
||||
}
|
||||
38
vendor/symfony/console/CommandLoader/CommandLoaderInterface.php
vendored
Normal file
38
vendor/symfony/console/CommandLoader/CommandLoaderInterface.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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\CommandLoader;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
|
||||
/**
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
interface CommandLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Loads a command.
|
||||
*
|
||||
* @throws CommandNotFoundException
|
||||
*/
|
||||
public function get(string $name): Command;
|
||||
|
||||
/**
|
||||
* Checks if a command exists.
|
||||
*/
|
||||
public function has(string $name): bool;
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNames(): array;
|
||||
}
|
||||
64
vendor/symfony/console/CommandLoader/ContainerCommandLoader.php
vendored
Normal file
64
vendor/symfony/console/CommandLoader/ContainerCommandLoader.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?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\CommandLoader;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
|
||||
/**
|
||||
* Loads commands from a PSR-11 container.
|
||||
*
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
class ContainerCommandLoader implements CommandLoaderInterface
|
||||
{
|
||||
private $container;
|
||||
private array $commandMap;
|
||||
|
||||
/**
|
||||
* @param array $commandMap An array with command names as keys and service ids as values
|
||||
*/
|
||||
public function __construct(ContainerInterface $container, array $commandMap)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->commandMap = $commandMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get(string $name): Command
|
||||
{
|
||||
if (!$this->has($name)) {
|
||||
throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
|
||||
}
|
||||
|
||||
return $this->container->get($this->commandMap[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has(string $name): bool
|
||||
{
|
||||
return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNames(): array
|
||||
{
|
||||
return array_keys($this->commandMap);
|
||||
}
|
||||
}
|
||||
63
vendor/symfony/console/CommandLoader/FactoryCommandLoader.php
vendored
Normal file
63
vendor/symfony/console/CommandLoader/FactoryCommandLoader.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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\CommandLoader;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
|
||||
/**
|
||||
* A simple command loader using factories to instantiate commands lazily.
|
||||
*
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class FactoryCommandLoader implements CommandLoaderInterface
|
||||
{
|
||||
private array $factories;
|
||||
|
||||
/**
|
||||
* @param callable[] $factories Indexed by command names
|
||||
*/
|
||||
public function __construct(array $factories)
|
||||
{
|
||||
$this->factories = $factories;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has(string $name): bool
|
||||
{
|
||||
return isset($this->factories[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get(string $name): Command
|
||||
{
|
||||
if (!isset($this->factories[$name])) {
|
||||
throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
|
||||
}
|
||||
|
||||
$factory = $this->factories[$name];
|
||||
|
||||
return $factory();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNames(): array
|
||||
{
|
||||
return array_keys($this->factories);
|
||||
}
|
||||
}
|
||||
249
vendor/symfony/console/Completion/CompletionInput.php
vendored
Normal file
249
vendor/symfony/console/Completion/CompletionInput.php
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
<?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\Completion;
|
||||
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
/**
|
||||
* An input specialized for shell completion.
|
||||
*
|
||||
* This input allows unfinished option names or values and exposes what kind of
|
||||
* completion is expected.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
final class CompletionInput extends ArgvInput
|
||||
{
|
||||
public const TYPE_ARGUMENT_VALUE = 'argument_value';
|
||||
public const TYPE_OPTION_VALUE = 'option_value';
|
||||
public const TYPE_OPTION_NAME = 'option_name';
|
||||
public const TYPE_NONE = 'none';
|
||||
|
||||
private $tokens;
|
||||
private $currentIndex;
|
||||
private $completionType;
|
||||
private $completionName = null;
|
||||
private $completionValue = '';
|
||||
|
||||
/**
|
||||
* Converts a terminal string into tokens.
|
||||
*
|
||||
* This is required for shell completions without COMP_WORDS support.
|
||||
*/
|
||||
public static function fromString(string $inputStr, int $currentIndex): self
|
||||
{
|
||||
preg_match_all('/(?<=^|\s)([\'"]?)(.+?)(?<!\\\\)\1(?=$|\s)/', $inputStr, $tokens);
|
||||
|
||||
return self::fromTokens($tokens[0], $currentIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an input based on an COMP_WORDS token list.
|
||||
*
|
||||
* @param string[] $tokens the set of split tokens (e.g. COMP_WORDS or argv)
|
||||
* @param $currentIndex the index of the cursor (e.g. COMP_CWORD)
|
||||
*/
|
||||
public static function fromTokens(array $tokens, int $currentIndex): self
|
||||
{
|
||||
$input = new self($tokens);
|
||||
$input->tokens = $tokens;
|
||||
$input->currentIndex = $currentIndex;
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function bind(InputDefinition $definition): void
|
||||
{
|
||||
parent::bind($definition);
|
||||
|
||||
$relevantToken = $this->getRelevantToken();
|
||||
if ('-' === $relevantToken[0]) {
|
||||
// the current token is an input option: complete either option name or option value
|
||||
[$optionToken, $optionValue] = explode('=', $relevantToken, 2) + ['', ''];
|
||||
|
||||
$option = $this->getOptionFromToken($optionToken);
|
||||
if (null === $option && !$this->isCursorFree()) {
|
||||
$this->completionType = self::TYPE_OPTION_NAME;
|
||||
$this->completionValue = $relevantToken;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (null !== $option && $option->acceptValue()) {
|
||||
$this->completionType = self::TYPE_OPTION_VALUE;
|
||||
$this->completionName = $option->getName();
|
||||
$this->completionValue = $optionValue ?: (!str_starts_with($optionToken, '--') ? substr($optionToken, 2) : '');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$previousToken = $this->tokens[$this->currentIndex - 1];
|
||||
if ('-' === $previousToken[0] && '' !== trim($previousToken, '-')) {
|
||||
// check if previous option accepted a value
|
||||
$previousOption = $this->getOptionFromToken($previousToken);
|
||||
if (null !== $previousOption && $previousOption->acceptValue()) {
|
||||
$this->completionType = self::TYPE_OPTION_VALUE;
|
||||
$this->completionName = $previousOption->getName();
|
||||
$this->completionValue = $relevantToken;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// complete argument value
|
||||
$this->completionType = self::TYPE_ARGUMENT_VALUE;
|
||||
|
||||
foreach ($this->definition->getArguments() as $argumentName => $argument) {
|
||||
if (!isset($this->arguments[$argumentName])) {
|
||||
break;
|
||||
}
|
||||
|
||||
$argumentValue = $this->arguments[$argumentName];
|
||||
$this->completionName = $argumentName;
|
||||
if (\is_array($argumentValue)) {
|
||||
$this->completionValue = $argumentValue ? $argumentValue[array_key_last($argumentValue)] : null;
|
||||
} else {
|
||||
$this->completionValue = $argumentValue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->currentIndex >= \count($this->tokens)) {
|
||||
if (!isset($this->arguments[$argumentName]) || $this->definition->getArgument($argumentName)->isArray()) {
|
||||
$this->completionName = $argumentName;
|
||||
$this->completionValue = '';
|
||||
} else {
|
||||
// we've reached the end
|
||||
$this->completionType = self::TYPE_NONE;
|
||||
$this->completionName = null;
|
||||
$this->completionValue = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of completion required.
|
||||
*
|
||||
* TYPE_ARGUMENT_VALUE when completing the value of an input argument
|
||||
* TYPE_OPTION_VALUE when completing the value of an input option
|
||||
* TYPE_OPTION_NAME when completing the name of an input option
|
||||
* TYPE_NONE when nothing should be completed
|
||||
*
|
||||
* @return string One of self::TYPE_* constants. TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component
|
||||
*/
|
||||
public function getCompletionType(): string
|
||||
{
|
||||
return $this->completionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the input option or argument when completing a value.
|
||||
*
|
||||
* @return string|null returns null when completing an option name
|
||||
*/
|
||||
public function getCompletionName(): ?string
|
||||
{
|
||||
return $this->completionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value already typed by the user (or empty string).
|
||||
*/
|
||||
public function getCompletionValue(): string
|
||||
{
|
||||
return $this->completionValue;
|
||||
}
|
||||
|
||||
public function mustSuggestOptionValuesFor(string $optionName): bool
|
||||
{
|
||||
return self::TYPE_OPTION_VALUE === $this->getCompletionType() && $optionName === $this->getCompletionName();
|
||||
}
|
||||
|
||||
public function mustSuggestArgumentValuesFor(string $argumentName): bool
|
||||
{
|
||||
return self::TYPE_ARGUMENT_VALUE === $this->getCompletionType() && $argumentName === $this->getCompletionName();
|
||||
}
|
||||
|
||||
protected function parseToken(string $token, bool $parseOptions): bool
|
||||
{
|
||||
try {
|
||||
return parent::parseToken($token, $parseOptions);
|
||||
} catch (RuntimeException $e) {
|
||||
// suppress errors, completed input is almost never valid
|
||||
}
|
||||
|
||||
return $parseOptions;
|
||||
}
|
||||
|
||||
private function getOptionFromToken(string $optionToken): ?InputOption
|
||||
{
|
||||
$optionName = ltrim($optionToken, '-');
|
||||
if (!$optionName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ('-' === ($optionToken[1] ?? ' ')) {
|
||||
// long option name
|
||||
return $this->definition->hasOption($optionName) ? $this->definition->getOption($optionName) : null;
|
||||
}
|
||||
|
||||
// short option name
|
||||
return $this->definition->hasShortcut($optionName[0]) ? $this->definition->getOptionForShortcut($optionName[0]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The token of the cursor, or the last token if the cursor is at the end of the input.
|
||||
*/
|
||||
private function getRelevantToken(): string
|
||||
{
|
||||
return $this->tokens[$this->isCursorFree() ? $this->currentIndex - 1 : $this->currentIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the cursor is "free" (i.e. at the end of the input preceded by a space).
|
||||
*/
|
||||
private function isCursorFree(): bool
|
||||
{
|
||||
$nrOfTokens = \count($this->tokens);
|
||||
if ($this->currentIndex > $nrOfTokens) {
|
||||
throw new \LogicException('Current index is invalid, it must be the number of input tokens or one more.');
|
||||
}
|
||||
|
||||
return $this->currentIndex >= $nrOfTokens;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$str = '';
|
||||
foreach ($this->tokens as $i => $token) {
|
||||
$str .= $token;
|
||||
|
||||
if ($this->currentIndex === $i) {
|
||||
$str .= '|';
|
||||
}
|
||||
|
||||
$str .= ' ';
|
||||
}
|
||||
|
||||
if ($this->currentIndex > $i) {
|
||||
$str .= '|';
|
||||
}
|
||||
|
||||
return rtrim($str);
|
||||
}
|
||||
}
|
||||
97
vendor/symfony/console/Completion/CompletionSuggestions.php
vendored
Normal file
97
vendor/symfony/console/Completion/CompletionSuggestions.php
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
<?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\Completion;
|
||||
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
/**
|
||||
* Stores all completion suggestions for the current input.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
final class CompletionSuggestions
|
||||
{
|
||||
private $valueSuggestions = [];
|
||||
private $optionSuggestions = [];
|
||||
|
||||
/**
|
||||
* Add a suggested value for an input option or argument.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function suggestValue(string|Suggestion $value): static
|
||||
{
|
||||
$this->valueSuggestions[] = !$value instanceof Suggestion ? new Suggestion($value) : $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple suggested values at once for an input option or argument.
|
||||
*
|
||||
* @param list<string|Suggestion> $values
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function suggestValues(array $values): static
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
$this->suggestValue($value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a suggestion for an input option name.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function suggestOption(InputOption $option): static
|
||||
{
|
||||
$this->optionSuggestions[] = $option;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple suggestions for input option names at once.
|
||||
*
|
||||
* @param InputOption[] $options
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function suggestOptions(array $options): static
|
||||
{
|
||||
foreach ($options as $option) {
|
||||
$this->suggestOption($option);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InputOption[]
|
||||
*/
|
||||
public function getOptionSuggestions(): array
|
||||
{
|
||||
return $this->optionSuggestions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Suggestion[]
|
||||
*/
|
||||
public function getValueSuggestions(): array
|
||||
{
|
||||
return $this->valueSuggestions;
|
||||
}
|
||||
}
|
||||
33
vendor/symfony/console/Completion/Output/BashCompletionOutput.php
vendored
Normal file
33
vendor/symfony/console/Completion/Output/BashCompletionOutput.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?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\Completion\Output;
|
||||
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class BashCompletionOutput implements CompletionOutputInterface
|
||||
{
|
||||
public function write(CompletionSuggestions $suggestions, OutputInterface $output): void
|
||||
{
|
||||
$values = $suggestions->getValueSuggestions();
|
||||
foreach ($suggestions->getOptionSuggestions() as $option) {
|
||||
$values[] = '--'.$option->getName();
|
||||
if ($option->isNegatable()) {
|
||||
$values[] = '--no-'.$option->getName();
|
||||
}
|
||||
}
|
||||
$output->writeln(implode("\n", $values));
|
||||
}
|
||||
}
|
||||
25
vendor/symfony/console/Completion/Output/CompletionOutputInterface.php
vendored
Normal file
25
vendor/symfony/console/Completion/Output/CompletionOutputInterface.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\Completion\Output;
|
||||
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Transforms the {@see CompletionSuggestions} object into output readable by the shell completion.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
interface CompletionOutputInterface
|
||||
{
|
||||
public function write(CompletionSuggestions $suggestions, OutputInterface $output): void;
|
||||
}
|
||||
37
vendor/symfony/console/Completion/Suggestion.php
vendored
Normal file
37
vendor/symfony/console/Completion/Suggestion.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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\Completion;
|
||||
|
||||
/**
|
||||
* Represents a single suggested value.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class Suggestion
|
||||
{
|
||||
private string $value;
|
||||
|
||||
public function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
}
|
||||
54
vendor/symfony/console/ConsoleEvents.php
vendored
54
vendor/symfony/console/ConsoleEvents.php
vendored
@@ -11,6 +11,11 @@
|
||||
|
||||
namespace Symfony\Component\Console;
|
||||
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
use Symfony\Component\Console\Event\ConsoleErrorEvent;
|
||||
use Symfony\Component\Console\Event\ConsoleSignalEvent;
|
||||
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
|
||||
|
||||
/**
|
||||
* Contains all events dispatched by an Application.
|
||||
*
|
||||
@@ -21,38 +26,27 @@ final class ConsoleEvents
|
||||
/**
|
||||
* The COMMAND event allows you to attach listeners before any command is
|
||||
* executed by the console. It also allows you to modify the command, input and output
|
||||
* before they are handled to the command.
|
||||
* before they are handed to the command.
|
||||
*
|
||||
* @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const COMMAND = 'console.command';
|
||||
public const COMMAND = 'console.command';
|
||||
|
||||
/**
|
||||
* The SIGNAL event allows you to perform some actions
|
||||
* after the command execution was interrupted.
|
||||
*
|
||||
* @Event("Symfony\Component\Console\Event\ConsoleSignalEvent")
|
||||
*/
|
||||
public const SIGNAL = 'console.signal';
|
||||
|
||||
/**
|
||||
* The TERMINATE event allows you to attach listeners after a command is
|
||||
* executed by the console.
|
||||
*
|
||||
* @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent")
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TERMINATE = 'console.terminate';
|
||||
|
||||
/**
|
||||
* The EXCEPTION event occurs when an uncaught exception appears
|
||||
* while executing Command#run().
|
||||
*
|
||||
* This event allows you to deal with the exception or
|
||||
* to modify the thrown exception.
|
||||
*
|
||||
* @Event("Symfony\Component\Console\Event\ConsoleExceptionEvent")
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @deprecated The console.exception event is deprecated since version 3.3 and will be removed in 4.0. Use the console.error event instead.
|
||||
*/
|
||||
const EXCEPTION = 'console.exception';
|
||||
public const TERMINATE = 'console.terminate';
|
||||
|
||||
/**
|
||||
* The ERROR event occurs when an uncaught exception or error appears.
|
||||
@@ -61,8 +55,18 @@ final class ConsoleEvents
|
||||
* to modify the thrown exception.
|
||||
*
|
||||
* @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ERROR = 'console.error';
|
||||
public const ERROR = 'console.error';
|
||||
|
||||
/**
|
||||
* Event aliases.
|
||||
*
|
||||
* These aliases can be consumed by RegisterListenersPass.
|
||||
*/
|
||||
public const ALIASES = [
|
||||
ConsoleCommandEvent::class => self::COMMAND,
|
||||
ConsoleErrorEvent::class => self::ERROR,
|
||||
ConsoleSignalEvent::class => self::SIGNAL,
|
||||
ConsoleTerminateEvent::class => self::TERMINATE,
|
||||
];
|
||||
}
|
||||
|
||||
207
vendor/symfony/console/Cursor.php
vendored
Normal file
207
vendor/symfony/console/Cursor.php
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console;
|
||||
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @author Pierre du Plessis <pdples@gmail.com>
|
||||
*/
|
||||
final class Cursor
|
||||
{
|
||||
private $output;
|
||||
private $input;
|
||||
|
||||
/**
|
||||
* @param resource|null $input
|
||||
*/
|
||||
public function __construct(OutputInterface $output, $input = null)
|
||||
{
|
||||
$this->output = $output;
|
||||
$this->input = $input ?? (\defined('STDIN') ? \STDIN : fopen('php://input', 'r+'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function moveUp(int $lines = 1): static
|
||||
{
|
||||
$this->output->write(sprintf("\x1b[%dA", $lines));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function moveDown(int $lines = 1): static
|
||||
{
|
||||
$this->output->write(sprintf("\x1b[%dB", $lines));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function moveRight(int $columns = 1): static
|
||||
{
|
||||
$this->output->write(sprintf("\x1b[%dC", $columns));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function moveLeft(int $columns = 1): static
|
||||
{
|
||||
$this->output->write(sprintf("\x1b[%dD", $columns));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function moveToColumn(int $column): static
|
||||
{
|
||||
$this->output->write(sprintf("\x1b[%dG", $column));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function moveToPosition(int $column, int $row): static
|
||||
{
|
||||
$this->output->write(sprintf("\x1b[%d;%dH", $row + 1, $column));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function savePosition(): static
|
||||
{
|
||||
$this->output->write("\x1b7");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function restorePosition(): static
|
||||
{
|
||||
$this->output->write("\x1b8");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function hide(): static
|
||||
{
|
||||
$this->output->write("\x1b[?25l");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function show(): static
|
||||
{
|
||||
$this->output->write("\x1b[?25h\x1b[?0c");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all the output from the current line.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function clearLine(): static
|
||||
{
|
||||
$this->output->write("\x1b[2K");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all the output from the current line after the current position.
|
||||
*/
|
||||
public function clearLineAfter(): self
|
||||
{
|
||||
$this->output->write("\x1b[K");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all the output from the cursors' current position to the end of the screen.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function clearOutput(): static
|
||||
{
|
||||
$this->output->write("\x1b[0J");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the entire screen.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function clearScreen(): static
|
||||
{
|
||||
$this->output->write("\x1b[2J");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current cursor position as x,y coordinates.
|
||||
*/
|
||||
public function getCurrentPosition(): array
|
||||
{
|
||||
static $isTtySupported;
|
||||
|
||||
if (null === $isTtySupported && \function_exists('proc_open')) {
|
||||
$isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes);
|
||||
}
|
||||
|
||||
if (!$isTtySupported) {
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
$sttyMode = shell_exec('stty -g');
|
||||
shell_exec('stty -icanon -echo');
|
||||
|
||||
@fwrite($this->input, "\033[6n");
|
||||
|
||||
$code = trim(fread($this->input, 1024));
|
||||
|
||||
shell_exec(sprintf('stty %s', $sttyMode));
|
||||
|
||||
sscanf($code, "\033[%d;%dR", $row, $col);
|
||||
|
||||
return [$col, $row];
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,15 @@
|
||||
namespace Symfony\Component\Console\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Command\LazyCommand;
|
||||
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
|
||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
|
||||
/**
|
||||
* Registers console commands.
|
||||
@@ -26,31 +32,100 @@ class AddConsoleCommandPass implements CompilerPassInterface
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$commandServices = $container->findTaggedServiceIds('console.command', true);
|
||||
$serviceIds = array();
|
||||
$lazyCommandMap = [];
|
||||
$lazyCommandRefs = [];
|
||||
$serviceIds = [];
|
||||
|
||||
foreach ($commandServices as $id => $tags) {
|
||||
$definition = $container->getDefinition($id);
|
||||
$definition->addTag('container.no_preload');
|
||||
$class = $container->getParameterBag()->resolveValue($definition->getClass());
|
||||
|
||||
if (!$r = $container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
|
||||
}
|
||||
if (!$r->isSubclassOf(Command::class)) {
|
||||
throw new InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must be a subclass of "%s".', $id, Command::class));
|
||||
if (isset($tags[0]['command'])) {
|
||||
$aliases = $tags[0]['command'];
|
||||
} else {
|
||||
if (!$r = $container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
|
||||
}
|
||||
if (!$r->isSubclassOf(Command::class)) {
|
||||
throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class));
|
||||
}
|
||||
$aliases = str_replace('%', '%%', $class::getDefaultName() ?? '');
|
||||
}
|
||||
|
||||
$commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class));
|
||||
if ($container->hasAlias($commandId) || isset($serviceIds[$commandId])) {
|
||||
$commandId = $commandId.'_'.$id;
|
||||
}
|
||||
if (!$definition->isPublic()) {
|
||||
$container->setAlias($commandId, $id);
|
||||
$id = $commandId;
|
||||
$aliases = explode('|', $aliases ?? '');
|
||||
$commandName = array_shift($aliases);
|
||||
|
||||
if ($isHidden = '' === $commandName) {
|
||||
$commandName = array_shift($aliases);
|
||||
}
|
||||
|
||||
$serviceIds[$commandId] = $id;
|
||||
if (null === $commandName) {
|
||||
if (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag('container.private')) {
|
||||
$commandId = 'console.command.public_alias.'.$id;
|
||||
$container->setAlias($commandId, $id)->setPublic(true);
|
||||
$id = $commandId;
|
||||
}
|
||||
$serviceIds[] = $id;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$description = $tags[0]['description'] ?? null;
|
||||
|
||||
unset($tags[0]);
|
||||
$lazyCommandMap[$commandName] = $id;
|
||||
$lazyCommandRefs[$id] = new TypedReference($id, $class);
|
||||
|
||||
foreach ($aliases as $alias) {
|
||||
$lazyCommandMap[$alias] = $id;
|
||||
}
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if (isset($tag['command'])) {
|
||||
$aliases[] = $tag['command'];
|
||||
$lazyCommandMap[$tag['command']] = $id;
|
||||
}
|
||||
|
||||
$description = $description ?? $tag['description'] ?? null;
|
||||
}
|
||||
|
||||
$definition->addMethodCall('setName', [$commandName]);
|
||||
|
||||
if ($aliases) {
|
||||
$definition->addMethodCall('setAliases', [$aliases]);
|
||||
}
|
||||
|
||||
if ($isHidden) {
|
||||
$definition->addMethodCall('setHidden', [true]);
|
||||
}
|
||||
|
||||
if (!$description) {
|
||||
if (!$r = $container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
|
||||
}
|
||||
if (!$r->isSubclassOf(Command::class)) {
|
||||
throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class));
|
||||
}
|
||||
$description = str_replace('%', '%%', $class::getDefaultDescription() ?? '');
|
||||
}
|
||||
|
||||
if ($description) {
|
||||
$definition->addMethodCall('setDescription', [$description]);
|
||||
|
||||
$container->register('.'.$id.'.lazy', LazyCommand::class)
|
||||
->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]);
|
||||
|
||||
$lazyCommandRefs[$id] = new Reference('.'.$id.'.lazy');
|
||||
}
|
||||
}
|
||||
|
||||
$container
|
||||
->register('console.command_loader', ContainerCommandLoader::class)
|
||||
->setPublic(true)
|
||||
->addTag('container.no_preload')
|
||||
->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]);
|
||||
|
||||
$container->setParameter('console.command.ids', $serviceIds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,58 +22,33 @@ use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
*/
|
||||
class ApplicationDescription
|
||||
{
|
||||
const GLOBAL_NAMESPACE = '_global';
|
||||
public const GLOBAL_NAMESPACE = '_global';
|
||||
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
private $application;
|
||||
private ?string $namespace;
|
||||
private bool $showHidden;
|
||||
private array $namespaces;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
* @var array<string, Command>
|
||||
*/
|
||||
private $namespace;
|
||||
private array $commands;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var array<string, Command>
|
||||
*/
|
||||
private $namespaces;
|
||||
private array $aliases = [];
|
||||
|
||||
/**
|
||||
* @var Command[]
|
||||
*/
|
||||
private $commands;
|
||||
|
||||
/**
|
||||
* @var Command[]
|
||||
*/
|
||||
private $aliases;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $showHidden;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Application $application
|
||||
* @param string|null $namespace
|
||||
* @param bool $showHidden
|
||||
*/
|
||||
public function __construct(Application $application, $namespace = null, $showHidden = false)
|
||||
public function __construct(Application $application, string $namespace = null, bool $showHidden = false)
|
||||
{
|
||||
$this->application = $application;
|
||||
$this->namespace = $namespace;
|
||||
$this->showHidden = $showHidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getNamespaces()
|
||||
public function getNamespaces(): array
|
||||
{
|
||||
if (null === $this->namespaces) {
|
||||
if (!isset($this->namespaces)) {
|
||||
$this->inspectApplication();
|
||||
}
|
||||
|
||||
@@ -83,9 +58,9 @@ class ApplicationDescription
|
||||
/**
|
||||
* @return Command[]
|
||||
*/
|
||||
public function getCommands()
|
||||
public function getCommands(): array
|
||||
{
|
||||
if (null === $this->commands) {
|
||||
if (!isset($this->commands)) {
|
||||
$this->inspectApplication();
|
||||
}
|
||||
|
||||
@@ -93,29 +68,25 @@ class ApplicationDescription
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return Command
|
||||
*
|
||||
* @throws CommandNotFoundException
|
||||
*/
|
||||
public function getCommand($name)
|
||||
public function getCommand(string $name): Command
|
||||
{
|
||||
if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
|
||||
throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
|
||||
throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
|
||||
}
|
||||
|
||||
return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
|
||||
return $this->commands[$name] ?? $this->aliases[$name];
|
||||
}
|
||||
|
||||
private function inspectApplication()
|
||||
{
|
||||
$this->commands = array();
|
||||
$this->namespaces = array();
|
||||
$this->commands = [];
|
||||
$this->namespaces = [];
|
||||
|
||||
$all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
|
||||
foreach ($this->sortCommands($all) as $namespace => $commands) {
|
||||
$names = array();
|
||||
$names = [];
|
||||
|
||||
/** @var Command $command */
|
||||
foreach ($commands as $name => $command) {
|
||||
@@ -132,36 +103,37 @@ class ApplicationDescription
|
||||
$names[] = $name;
|
||||
}
|
||||
|
||||
$this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
|
||||
$this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $commands
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function sortCommands(array $commands)
|
||||
private function sortCommands(array $commands): array
|
||||
{
|
||||
$namespacedCommands = array();
|
||||
$globalCommands = array();
|
||||
$namespacedCommands = [];
|
||||
$globalCommands = [];
|
||||
$sortedCommands = [];
|
||||
foreach ($commands as $name => $command) {
|
||||
$key = $this->application->extractNamespace($name, 1);
|
||||
if (!$key) {
|
||||
$globalCommands['_global'][$name] = $command;
|
||||
if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) {
|
||||
$globalCommands[$name] = $command;
|
||||
} else {
|
||||
$namespacedCommands[$key][$name] = $command;
|
||||
}
|
||||
}
|
||||
ksort($namespacedCommands);
|
||||
$namespacedCommands = array_merge($globalCommands, $namespacedCommands);
|
||||
|
||||
foreach ($namespacedCommands as &$commandsSet) {
|
||||
ksort($commandsSet);
|
||||
if ($globalCommands) {
|
||||
ksort($globalCommands);
|
||||
$sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands;
|
||||
}
|
||||
// unset reference to keep scope clear
|
||||
unset($commandsSet);
|
||||
|
||||
return $namespacedCommands;
|
||||
if ($namespacedCommands) {
|
||||
ksort($namespacedCommands, \SORT_STRING);
|
||||
foreach ($namespacedCommands as $key => $commandsSet) {
|
||||
ksort($commandsSet);
|
||||
$sortedCommands[$key] = $commandsSet;
|
||||
}
|
||||
}
|
||||
|
||||
return $sortedCommands;
|
||||
}
|
||||
}
|
||||
|
||||
46
vendor/symfony/console/Descriptor/Descriptor.php
vendored
46
vendor/symfony/console/Descriptor/Descriptor.php
vendored
@@ -13,11 +13,11 @@ namespace Symfony\Component\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
@@ -34,7 +34,7 @@ abstract class Descriptor implements DescriptorInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function describe(OutputInterface $output, $object, array $options = array())
|
||||
public function describe(OutputInterface $output, object $object, array $options = [])
|
||||
{
|
||||
$this->output = $output;
|
||||
|
||||
@@ -55,68 +55,40 @@ abstract class Descriptor implements DescriptorInterface
|
||||
$this->describeApplication($object, $options);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
|
||||
throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes content to output.
|
||||
*
|
||||
* @param string $content
|
||||
* @param bool $decorated
|
||||
*/
|
||||
protected function write($content, $decorated = false)
|
||||
protected function write(string $content, bool $decorated = false)
|
||||
{
|
||||
$this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes an InputArgument instance.
|
||||
*
|
||||
* @param InputArgument $argument
|
||||
* @param array $options
|
||||
*
|
||||
* @return string|mixed
|
||||
*/
|
||||
abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
|
||||
abstract protected function describeInputArgument(InputArgument $argument, array $options = []);
|
||||
|
||||
/**
|
||||
* Describes an InputOption instance.
|
||||
*
|
||||
* @param InputOption $option
|
||||
* @param array $options
|
||||
*
|
||||
* @return string|mixed
|
||||
*/
|
||||
abstract protected function describeInputOption(InputOption $option, array $options = array());
|
||||
abstract protected function describeInputOption(InputOption $option, array $options = []);
|
||||
|
||||
/**
|
||||
* Describes an InputDefinition instance.
|
||||
*
|
||||
* @param InputDefinition $definition
|
||||
* @param array $options
|
||||
*
|
||||
* @return string|mixed
|
||||
*/
|
||||
abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
|
||||
abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []);
|
||||
|
||||
/**
|
||||
* Describes a Command instance.
|
||||
*
|
||||
* @param Command $command
|
||||
* @param array $options
|
||||
*
|
||||
* @return string|mixed
|
||||
*/
|
||||
abstract protected function describeCommand(Command $command, array $options = array());
|
||||
abstract protected function describeCommand(Command $command, array $options = []);
|
||||
|
||||
/**
|
||||
* Describes an Application instance.
|
||||
*
|
||||
* @param Application $application
|
||||
* @param array $options
|
||||
*
|
||||
* @return string|mixed
|
||||
*/
|
||||
abstract protected function describeApplication(Application $application, array $options = array());
|
||||
abstract protected function describeApplication(Application $application, array $options = []);
|
||||
}
|
||||
|
||||
@@ -20,12 +20,5 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
*/
|
||||
interface DescriptorInterface
|
||||
{
|
||||
/**
|
||||
* Describes an InputArgument instance.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param object $object
|
||||
* @param array $options
|
||||
*/
|
||||
public function describe(OutputInterface $output, $object, array $options = array());
|
||||
public function describe(OutputInterface $output, object $object, array $options = []);
|
||||
}
|
||||
|
||||
120
vendor/symfony/console/Descriptor/JsonDescriptor.php
vendored
120
vendor/symfony/console/Descriptor/JsonDescriptor.php
vendored
@@ -29,7 +29,7 @@ class JsonDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = array())
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = [])
|
||||
{
|
||||
$this->writeData($this->getInputArgumentData($argument), $options);
|
||||
}
|
||||
@@ -37,15 +37,18 @@ class JsonDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputOption(InputOption $option, array $options = array())
|
||||
protected function describeInputOption(InputOption $option, array $options = [])
|
||||
{
|
||||
$this->writeData($this->getInputOptionData($option), $options);
|
||||
if ($option->isNegatable()) {
|
||||
$this->writeData($this->getInputOptionData($option, true), $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = [])
|
||||
{
|
||||
$this->writeData($this->getInputDefinitionData($definition), $options);
|
||||
}
|
||||
@@ -53,25 +56,25 @@ class JsonDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeCommand(Command $command, array $options = array())
|
||||
protected function describeCommand(Command $command, array $options = [])
|
||||
{
|
||||
$this->writeData($this->getCommandData($command), $options);
|
||||
$this->writeData($this->getCommandData($command, $options['short'] ?? false), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeApplication(Application $application, array $options = array())
|
||||
protected function describeApplication(Application $application, array $options = [])
|
||||
{
|
||||
$describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
|
||||
$describedNamespace = $options['namespace'] ?? null;
|
||||
$description = new ApplicationDescription($application, $describedNamespace, true);
|
||||
$commands = array();
|
||||
$commands = [];
|
||||
|
||||
foreach ($description->getCommands() as $command) {
|
||||
$commands[] = $this->getCommandData($command);
|
||||
$commands[] = $this->getCommandData($command, $options['short'] ?? false);
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$data = [];
|
||||
if ('UNKNOWN' !== $application->getName()) {
|
||||
$data['application']['name'] = $application->getName();
|
||||
if ('UNKNOWN' !== $application->getVersion()) {
|
||||
@@ -92,88 +95,87 @@ class JsonDescriptor extends Descriptor
|
||||
|
||||
/**
|
||||
* Writes data as json.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $options
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function writeData(array $data, array $options)
|
||||
{
|
||||
$this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
|
||||
$flags = $options['json_encoding'] ?? 0;
|
||||
|
||||
$this->write(json_encode($data, $flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputArgument $argument
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getInputArgumentData(InputArgument $argument)
|
||||
private function getInputArgumentData(InputArgument $argument): array
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
'name' => $argument->getName(),
|
||||
'is_required' => $argument->isRequired(),
|
||||
'is_array' => $argument->isArray(),
|
||||
'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
|
||||
'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
|
||||
);
|
||||
'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputOption $option
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getInputOptionData(InputOption $option)
|
||||
private function getInputOptionData(InputOption $option, bool $negated = false): array
|
||||
{
|
||||
return array(
|
||||
return $negated ? [
|
||||
'name' => '--no-'.$option->getName(),
|
||||
'shortcut' => '',
|
||||
'accept_value' => false,
|
||||
'is_value_required' => false,
|
||||
'is_multiple' => false,
|
||||
'description' => 'Negate the "--'.$option->getName().'" option',
|
||||
'default' => false,
|
||||
] : [
|
||||
'name' => '--'.$option->getName(),
|
||||
'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
|
||||
'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '',
|
||||
'accept_value' => $option->acceptValue(),
|
||||
'is_value_required' => $option->isValueRequired(),
|
||||
'is_multiple' => $option->isArray(),
|
||||
'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
|
||||
'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
|
||||
);
|
||||
'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputDefinition $definition
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getInputDefinitionData(InputDefinition $definition)
|
||||
private function getInputDefinitionData(InputDefinition $definition): array
|
||||
{
|
||||
$inputArguments = array();
|
||||
$inputArguments = [];
|
||||
foreach ($definition->getArguments() as $name => $argument) {
|
||||
$inputArguments[$name] = $this->getInputArgumentData($argument);
|
||||
}
|
||||
|
||||
$inputOptions = array();
|
||||
$inputOptions = [];
|
||||
foreach ($definition->getOptions() as $name => $option) {
|
||||
$inputOptions[$name] = $this->getInputOptionData($option);
|
||||
if ($option->isNegatable()) {
|
||||
$inputOptions['no-'.$name] = $this->getInputOptionData($option, true);
|
||||
}
|
||||
}
|
||||
|
||||
return array('arguments' => $inputArguments, 'options' => $inputOptions);
|
||||
return ['arguments' => $inputArguments, 'options' => $inputOptions];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $command
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getCommandData(Command $command)
|
||||
private function getCommandData(Command $command, bool $short = false): array
|
||||
{
|
||||
$command->getSynopsis();
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
return array(
|
||||
$data = [
|
||||
'name' => $command->getName(),
|
||||
'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
|
||||
'description' => $command->getDescription(),
|
||||
'help' => $command->getProcessedHelp(),
|
||||
'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
|
||||
'hidden' => $command->isHidden(),
|
||||
);
|
||||
];
|
||||
|
||||
if ($short) {
|
||||
$data += [
|
||||
'usage' => $command->getAliases(),
|
||||
];
|
||||
} else {
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
$data += [
|
||||
'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()),
|
||||
'help' => $command->getProcessedHelp(),
|
||||
'definition' => $this->getInputDefinitionData($command->getDefinition()),
|
||||
];
|
||||
}
|
||||
|
||||
$data['hidden'] = $command->isHidden();
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class MarkdownDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function describe(OutputInterface $output, $object, array $options = array())
|
||||
public function describe(OutputInterface $output, object $object, array $options = [])
|
||||
{
|
||||
$decorated = $output->isDecorated();
|
||||
$output->setDecorated(false);
|
||||
@@ -44,7 +44,7 @@ class MarkdownDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function write($content, $decorated = true)
|
||||
protected function write(string $content, bool $decorated = true)
|
||||
{
|
||||
parent::write($content, $decorated);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ class MarkdownDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = array())
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = [])
|
||||
{
|
||||
$this->write(
|
||||
'#### `'.($argument->getName() ?: '<none>')."`\n\n"
|
||||
@@ -66,11 +66,14 @@ class MarkdownDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputOption(InputOption $option, array $options = array())
|
||||
protected function describeInputOption(InputOption $option, array $options = [])
|
||||
{
|
||||
$name = '--'.$option->getName();
|
||||
if ($option->isNegatable()) {
|
||||
$name .= '|--no-'.$option->getName();
|
||||
}
|
||||
if ($option->getShortcut()) {
|
||||
$name .= '|-'.implode('|-', explode('|', $option->getShortcut())).'';
|
||||
$name .= '|-'.str_replace('|', '|-', $option->getShortcut()).'';
|
||||
}
|
||||
|
||||
$this->write(
|
||||
@@ -79,6 +82,7 @@ class MarkdownDescriptor extends Descriptor
|
||||
.'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
|
||||
.'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
|
||||
.'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
|
||||
.'* Is negatable: '.($option->isNegatable() ? 'yes' : 'no')."\n"
|
||||
.'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
|
||||
);
|
||||
}
|
||||
@@ -86,17 +90,19 @@ class MarkdownDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = [])
|
||||
{
|
||||
if ($showArguments = count($definition->getArguments()) > 0) {
|
||||
if ($showArguments = \count($definition->getArguments()) > 0) {
|
||||
$this->write('### Arguments');
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
$this->write("\n\n");
|
||||
$this->write($this->describeInputArgument($argument));
|
||||
if (null !== $describeInputArgument = $this->describeInputArgument($argument)) {
|
||||
$this->write($describeInputArgument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($definition->getOptions()) > 0) {
|
||||
if (\count($definition->getOptions()) > 0) {
|
||||
if ($showArguments) {
|
||||
$this->write("\n\n");
|
||||
}
|
||||
@@ -104,7 +110,9 @@ class MarkdownDescriptor extends Descriptor
|
||||
$this->write('### Options');
|
||||
foreach ($definition->getOptions() as $option) {
|
||||
$this->write("\n\n");
|
||||
$this->write($this->describeInputOption($option));
|
||||
if (null !== $describeInputOption = $this->describeInputOption($option)) {
|
||||
$this->write($describeInputOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,17 +120,30 @@ class MarkdownDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeCommand(Command $command, array $options = array())
|
||||
protected function describeCommand(Command $command, array $options = [])
|
||||
{
|
||||
$command->getSynopsis();
|
||||
if ($options['short'] ?? false) {
|
||||
$this->write(
|
||||
'`'.$command->getName()."`\n"
|
||||
.str_repeat('-', Helper::width($command->getName()) + 2)."\n\n"
|
||||
.($command->getDescription() ? $command->getDescription()."\n\n" : '')
|
||||
.'### Usage'."\n\n"
|
||||
.array_reduce($command->getAliases(), function ($carry, $usage) {
|
||||
return $carry.'* `'.$usage.'`'."\n";
|
||||
})
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
$this->write(
|
||||
'`'.$command->getName()."`\n"
|
||||
.str_repeat('-', Helper::strlen($command->getName()) + 2)."\n\n"
|
||||
.str_repeat('-', Helper::width($command->getName()) + 2)."\n\n"
|
||||
.($command->getDescription() ? $command->getDescription()."\n\n" : '')
|
||||
.'### Usage'."\n\n"
|
||||
.array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
|
||||
.array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
|
||||
return $carry.'* `'.$usage.'`'."\n";
|
||||
})
|
||||
);
|
||||
@@ -132,22 +153,23 @@ class MarkdownDescriptor extends Descriptor
|
||||
$this->write($help);
|
||||
}
|
||||
|
||||
if ($command->getNativeDefinition()) {
|
||||
$definition = $command->getDefinition();
|
||||
if ($definition->getOptions() || $definition->getArguments()) {
|
||||
$this->write("\n\n");
|
||||
$this->describeInputDefinition($command->getNativeDefinition());
|
||||
$this->describeInputDefinition($definition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeApplication(Application $application, array $options = array())
|
||||
protected function describeApplication(Application $application, array $options = [])
|
||||
{
|
||||
$describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
|
||||
$describedNamespace = $options['namespace'] ?? null;
|
||||
$description = new ApplicationDescription($application, $describedNamespace);
|
||||
$title = $this->getApplicationTitle($application);
|
||||
|
||||
$this->write($title."\n".str_repeat('=', Helper::strlen($title)));
|
||||
$this->write($title."\n".str_repeat('=', Helper::width($title)));
|
||||
|
||||
foreach ($description->getNamespaces() as $namespace) {
|
||||
if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
|
||||
@@ -163,11 +185,13 @@ class MarkdownDescriptor extends Descriptor
|
||||
|
||||
foreach ($description->getCommands() as $command) {
|
||||
$this->write("\n\n");
|
||||
$this->write($this->describeCommand($command));
|
||||
if (null !== $describeCommand = $this->describeCommand($command, $options)) {
|
||||
$this->write($describeCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getApplicationTitle(Application $application)
|
||||
private function getApplicationTitle(Application $application): string
|
||||
{
|
||||
if ('UNKNOWN' !== $application->getName()) {
|
||||
if ('UNKNOWN' !== $application->getVersion()) {
|
||||
|
||||
115
vendor/symfony/console/Descriptor/TextDescriptor.php
vendored
115
vendor/symfony/console/Descriptor/TextDescriptor.php
vendored
@@ -31,16 +31,16 @@ class TextDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = array())
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = [])
|
||||
{
|
||||
if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
|
||||
if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
|
||||
$default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
|
||||
} else {
|
||||
$default = '';
|
||||
}
|
||||
|
||||
$totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
|
||||
$spacingWidth = $totalWidth - strlen($argument->getName());
|
||||
$totalWidth = $options['total_width'] ?? Helper::width($argument->getName());
|
||||
$spacingWidth = $totalWidth - \strlen($argument->getName());
|
||||
|
||||
$this->writeText(sprintf(' <info>%s</info> %s%s%s',
|
||||
$argument->getName(),
|
||||
@@ -54,9 +54,9 @@ class TextDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputOption(InputOption $option, array $options = array())
|
||||
protected function describeInputOption(InputOption $option, array $options = [])
|
||||
{
|
||||
if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
|
||||
if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
|
||||
$default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
|
||||
} else {
|
||||
$default = '';
|
||||
@@ -71,13 +71,13 @@ class TextDescriptor extends Descriptor
|
||||
}
|
||||
}
|
||||
|
||||
$totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
|
||||
$totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]);
|
||||
$synopsis = sprintf('%s%s',
|
||||
$option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ',
|
||||
sprintf('--%s%s', $option->getName(), $value)
|
||||
sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value)
|
||||
);
|
||||
|
||||
$spacingWidth = $totalWidth - Helper::strlen($synopsis);
|
||||
$spacingWidth = $totalWidth - Helper::width($synopsis);
|
||||
|
||||
$this->writeText(sprintf(' <info>%s</info> %s%s%s%s',
|
||||
$synopsis,
|
||||
@@ -92,18 +92,18 @@ class TextDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = [])
|
||||
{
|
||||
$totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
$totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
|
||||
$totalWidth = max($totalWidth, Helper::width($argument->getName()));
|
||||
}
|
||||
|
||||
if ($definition->getArguments()) {
|
||||
$this->writeText('<comment>Arguments:</comment>', $options);
|
||||
$this->writeText("\n");
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
$this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
|
||||
$this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth]));
|
||||
$this->writeText("\n");
|
||||
}
|
||||
}
|
||||
@@ -113,20 +113,20 @@ class TextDescriptor extends Descriptor
|
||||
}
|
||||
|
||||
if ($definition->getOptions()) {
|
||||
$laterOptions = array();
|
||||
$laterOptions = [];
|
||||
|
||||
$this->writeText('<comment>Options:</comment>', $options);
|
||||
foreach ($definition->getOptions() as $option) {
|
||||
if (strlen($option->getShortcut()) > 1) {
|
||||
if (\strlen($option->getShortcut() ?? '') > 1) {
|
||||
$laterOptions[] = $option;
|
||||
continue;
|
||||
}
|
||||
$this->writeText("\n");
|
||||
$this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
|
||||
$this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
|
||||
}
|
||||
foreach ($laterOptions as $option) {
|
||||
$this->writeText("\n");
|
||||
$this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
|
||||
$this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,27 +134,33 @@ class TextDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeCommand(Command $command, array $options = array())
|
||||
protected function describeCommand(Command $command, array $options = [])
|
||||
{
|
||||
$command->getSynopsis(true);
|
||||
$command->getSynopsis(false);
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
$this->writeText('<comment>Usage:</comment>', $options);
|
||||
foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
|
||||
if ($description = $command->getDescription()) {
|
||||
$this->writeText('<comment>Description:</comment>', $options);
|
||||
$this->writeText("\n");
|
||||
$this->writeText(' '.$usage, $options);
|
||||
$this->writeText(' '.$description);
|
||||
$this->writeText("\n\n");
|
||||
}
|
||||
|
||||
$this->writeText('<comment>Usage:</comment>', $options);
|
||||
foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) {
|
||||
$this->writeText("\n");
|
||||
$this->writeText(' '.OutputFormatter::escape($usage), $options);
|
||||
}
|
||||
$this->writeText("\n");
|
||||
|
||||
$definition = $command->getNativeDefinition();
|
||||
$definition = $command->getDefinition();
|
||||
if ($definition->getOptions() || $definition->getArguments()) {
|
||||
$this->writeText("\n");
|
||||
$this->describeInputDefinition($definition, $options);
|
||||
$this->writeText("\n");
|
||||
}
|
||||
|
||||
if ($help = $command->getProcessedHelp()) {
|
||||
$help = $command->getProcessedHelp();
|
||||
if ($help && $help !== $description) {
|
||||
$this->writeText("\n");
|
||||
$this->writeText('<comment>Help:</comment>', $options);
|
||||
$this->writeText("\n");
|
||||
@@ -166,9 +172,9 @@ class TextDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeApplication(Application $application, array $options = array())
|
||||
protected function describeApplication(Application $application, array $options = [])
|
||||
{
|
||||
$describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
|
||||
$describedNamespace = $options['namespace'] ?? null;
|
||||
$description = new ApplicationDescription($application, $describedNamespace);
|
||||
|
||||
if (isset($options['raw_text']) && $options['raw_text']) {
|
||||
@@ -202,9 +208,9 @@ class TextDescriptor extends Descriptor
|
||||
}
|
||||
|
||||
// calculate max. width based on available commands per namespace
|
||||
$width = $this->getColumnWidth(call_user_func_array('array_merge', array_map(function ($namespace) use ($commands) {
|
||||
$width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) {
|
||||
return array_intersect($namespace['commands'], array_keys($commands));
|
||||
}, $namespaces)));
|
||||
}, array_values($namespaces)))));
|
||||
|
||||
if ($describedNamespace) {
|
||||
$this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
|
||||
@@ -228,7 +234,7 @@ class TextDescriptor extends Descriptor
|
||||
|
||||
foreach ($namespace['commands'] as $name) {
|
||||
$this->writeText("\n");
|
||||
$spacingWidth = $width - Helper::strlen($name);
|
||||
$spacingWidth = $width - Helper::width($name);
|
||||
$command = $commands[$name];
|
||||
$commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : '';
|
||||
$this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options);
|
||||
@@ -242,7 +248,7 @@ class TextDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private function writeText($content, array $options = array())
|
||||
private function writeText(string $content, array $options = [])
|
||||
{
|
||||
$this->write(
|
||||
isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
|
||||
@@ -252,12 +258,8 @@ class TextDescriptor extends Descriptor
|
||||
|
||||
/**
|
||||
* Formats command aliases to show them in the command description.
|
||||
*
|
||||
* @param Command $command
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getCommandAliasesText($command)
|
||||
private function getCommandAliasesText(Command $command): string
|
||||
{
|
||||
$text = '';
|
||||
$aliases = $command->getAliases();
|
||||
@@ -271,47 +273,41 @@ class TextDescriptor extends Descriptor
|
||||
|
||||
/**
|
||||
* Formats input option/argument default value.
|
||||
*
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatDefaultValue($default)
|
||||
private function formatDefaultValue(mixed $default): string
|
||||
{
|
||||
if (INF === $default) {
|
||||
if (\INF === $default) {
|
||||
return 'INF';
|
||||
}
|
||||
|
||||
if (is_string($default)) {
|
||||
if (\is_string($default)) {
|
||||
$default = OutputFormatter::escape($default);
|
||||
} elseif (is_array($default)) {
|
||||
} elseif (\is_array($default)) {
|
||||
foreach ($default as $key => $value) {
|
||||
if (is_string($value)) {
|
||||
if (\is_string($value)) {
|
||||
$default[$key] = OutputFormatter::escape($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param (Command|string)[] $commands
|
||||
*
|
||||
* @return int
|
||||
* @param array<Command|string> $commands
|
||||
*/
|
||||
private function getColumnWidth(array $commands)
|
||||
private function getColumnWidth(array $commands): int
|
||||
{
|
||||
$widths = array();
|
||||
$widths = [];
|
||||
|
||||
foreach ($commands as $command) {
|
||||
if ($command instanceof Command) {
|
||||
$widths[] = Helper::strlen($command->getName());
|
||||
$widths[] = Helper::width($command->getName());
|
||||
foreach ($command->getAliases() as $alias) {
|
||||
$widths[] = Helper::strlen($alias);
|
||||
$widths[] = Helper::width($alias);
|
||||
}
|
||||
} else {
|
||||
$widths[] = Helper::strlen($command);
|
||||
$widths[] = Helper::width($command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,18 +316,17 @@ class TextDescriptor extends Descriptor
|
||||
|
||||
/**
|
||||
* @param InputOption[] $options
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function calculateTotalWidthForOptions($options)
|
||||
private function calculateTotalWidthForOptions(array $options): int
|
||||
{
|
||||
$totalWidth = 0;
|
||||
foreach ($options as $option) {
|
||||
// "-" + shortcut + ", --" + name
|
||||
$nameLength = 1 + max(Helper::strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
|
||||
|
||||
if ($option->acceptValue()) {
|
||||
$valueLength = 1 + Helper::strlen($option->getName()); // = + value
|
||||
$nameLength = 1 + max(Helper::width($option->getShortcut()), 1) + 4 + Helper::width($option->getName());
|
||||
if ($option->isNegatable()) {
|
||||
$nameLength += 6 + Helper::width($option->getName()); // |--no- + name
|
||||
} elseif ($option->acceptValue()) {
|
||||
$valueLength = 1 + Helper::width($option->getName()); // = + value
|
||||
$valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]
|
||||
|
||||
$nameLength += $valueLength;
|
||||
|
||||
109
vendor/symfony/console/Descriptor/XmlDescriptor.php
vendored
109
vendor/symfony/console/Descriptor/XmlDescriptor.php
vendored
@@ -26,12 +26,7 @@ use Symfony\Component\Console\Input\InputOption;
|
||||
*/
|
||||
class XmlDescriptor extends Descriptor
|
||||
{
|
||||
/**
|
||||
* @param InputDefinition $definition
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function getInputDefinitionDocument(InputDefinition $definition)
|
||||
public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($definitionXML = $dom->createElement('definition'));
|
||||
@@ -49,55 +44,49 @@ class XmlDescriptor extends Descriptor
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $command
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function getCommandDocument(Command $command)
|
||||
public function getCommandDocument(Command $command, bool $short = false): \DOMDocument
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($commandXML = $dom->createElement('command'));
|
||||
|
||||
$command->getSynopsis();
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
$commandXML->setAttribute('id', $command->getName());
|
||||
$commandXML->setAttribute('name', $command->getName());
|
||||
$commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0);
|
||||
|
||||
$commandXML->appendChild($usagesXML = $dom->createElement('usages'));
|
||||
|
||||
foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
|
||||
$usagesXML->appendChild($dom->createElement('usage', $usage));
|
||||
}
|
||||
|
||||
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
|
||||
$descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
|
||||
|
||||
$commandXML->appendChild($helpXML = $dom->createElement('help'));
|
||||
$helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
|
||||
if ($short) {
|
||||
foreach ($command->getAliases() as $usage) {
|
||||
$usagesXML->appendChild($dom->createElement('usage', $usage));
|
||||
}
|
||||
} else {
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
$definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
|
||||
$this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
|
||||
foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) {
|
||||
$usagesXML->appendChild($dom->createElement('usage', $usage));
|
||||
}
|
||||
|
||||
$commandXML->appendChild($helpXML = $dom->createElement('help'));
|
||||
$helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
|
||||
|
||||
$definitionXML = $this->getInputDefinitionDocument($command->getDefinition());
|
||||
$this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $application
|
||||
* @param string|null $namespace
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function getApplicationDocument(Application $application, $namespace = null)
|
||||
public function getApplicationDocument(Application $application, string $namespace = null, bool $short = false): \DOMDocument
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($rootXml = $dom->createElement('symfony'));
|
||||
|
||||
if ($application->getName() !== 'UNKNOWN') {
|
||||
if ('UNKNOWN' !== $application->getName()) {
|
||||
$rootXml->setAttribute('name', $application->getName());
|
||||
if ($application->getVersion() !== 'UNKNOWN') {
|
||||
if ('UNKNOWN' !== $application->getVersion()) {
|
||||
$rootXml->setAttribute('version', $application->getVersion());
|
||||
}
|
||||
}
|
||||
@@ -111,7 +100,7 @@ class XmlDescriptor extends Descriptor
|
||||
}
|
||||
|
||||
foreach ($description->getCommands() as $command) {
|
||||
$this->appendDocument($commandsXML, $this->getCommandDocument($command));
|
||||
$this->appendDocument($commandsXML, $this->getCommandDocument($command, $short));
|
||||
}
|
||||
|
||||
if (!$namespace) {
|
||||
@@ -134,7 +123,7 @@ class XmlDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = array())
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = [])
|
||||
{
|
||||
$this->writeDocument($this->getInputArgumentDocument($argument));
|
||||
}
|
||||
@@ -142,7 +131,7 @@ class XmlDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputOption(InputOption $option, array $options = array())
|
||||
protected function describeInputOption(InputOption $option, array $options = [])
|
||||
{
|
||||
$this->writeDocument($this->getInputOptionDocument($option));
|
||||
}
|
||||
@@ -150,7 +139,7 @@ class XmlDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = [])
|
||||
{
|
||||
$this->writeDocument($this->getInputDefinitionDocument($definition));
|
||||
}
|
||||
@@ -158,24 +147,21 @@ class XmlDescriptor extends Descriptor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeCommand(Command $command, array $options = array())
|
||||
protected function describeCommand(Command $command, array $options = [])
|
||||
{
|
||||
$this->writeDocument($this->getCommandDocument($command));
|
||||
$this->writeDocument($this->getCommandDocument($command, $options['short'] ?? false));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeApplication(Application $application, array $options = array())
|
||||
protected function describeApplication(Application $application, array $options = [])
|
||||
{
|
||||
$this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
|
||||
$this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends document children to parent node.
|
||||
*
|
||||
* @param \DOMNode $parentNode
|
||||
* @param \DOMNode $importedParent
|
||||
*/
|
||||
private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
|
||||
{
|
||||
@@ -186,10 +172,6 @@ class XmlDescriptor extends Descriptor
|
||||
|
||||
/**
|
||||
* Writes DOM document.
|
||||
*
|
||||
* @param \DOMDocument $dom
|
||||
*
|
||||
* @return \DOMDocument|string
|
||||
*/
|
||||
private function writeDocument(\DOMDocument $dom)
|
||||
{
|
||||
@@ -197,12 +179,7 @@ class XmlDescriptor extends Descriptor
|
||||
$this->write($dom->saveXML());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputArgument $argument
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getInputArgumentDocument(InputArgument $argument)
|
||||
private function getInputArgumentDocument(InputArgument $argument): \DOMDocument
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
|
||||
@@ -214,7 +191,7 @@ class XmlDescriptor extends Descriptor
|
||||
$descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
|
||||
|
||||
$objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
|
||||
$defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
|
||||
$defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : []));
|
||||
foreach ($defaults as $default) {
|
||||
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
|
||||
$defaultXML->appendChild($dom->createTextNode($default));
|
||||
@@ -223,21 +200,16 @@ class XmlDescriptor extends Descriptor
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputOption $option
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getInputOptionDocument(InputOption $option)
|
||||
private function getInputOptionDocument(InputOption $option): \DOMDocument
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
|
||||
$dom->appendChild($objectXML = $dom->createElement('option'));
|
||||
$objectXML->setAttribute('name', '--'.$option->getName());
|
||||
$pos = strpos($option->getShortcut(), '|');
|
||||
$pos = strpos($option->getShortcut() ?? '', '|');
|
||||
if (false !== $pos) {
|
||||
$objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
|
||||
$objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
|
||||
$objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut()));
|
||||
} else {
|
||||
$objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
|
||||
}
|
||||
@@ -248,7 +220,7 @@ class XmlDescriptor extends Descriptor
|
||||
$descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
|
||||
|
||||
if ($option->acceptValue()) {
|
||||
$defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
|
||||
$defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : []));
|
||||
$objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
|
||||
|
||||
if (!empty($defaults)) {
|
||||
@@ -259,6 +231,17 @@ class XmlDescriptor extends Descriptor
|
||||
}
|
||||
}
|
||||
|
||||
if ($option->isNegatable()) {
|
||||
$dom->appendChild($objectXML = $dom->createElement('option'));
|
||||
$objectXML->setAttribute('name', '--no-'.$option->getName());
|
||||
$objectXML->setAttribute('shortcut', '');
|
||||
$objectXML->setAttribute('accept_value', 0);
|
||||
$objectXML->setAttribute('is_value_required', 0);
|
||||
$objectXML->setAttribute('is_multiple', 0);
|
||||
$objectXML->appendChild($descriptionXML = $dom->createElement('description'));
|
||||
$descriptionXML->appendChild($dom->createTextNode('Negate the "--'.$option->getName().'" option'));
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,46 +16,35 @@ namespace Symfony\Component\Console\Event;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class ConsoleCommandEvent extends ConsoleEvent
|
||||
final class ConsoleCommandEvent extends ConsoleEvent
|
||||
{
|
||||
/**
|
||||
* The return code for skipped commands, this will also be passed into the terminate event.
|
||||
*/
|
||||
const RETURN_CODE_DISABLED = 113;
|
||||
public const RETURN_CODE_DISABLED = 113;
|
||||
|
||||
/**
|
||||
* Indicates if the command should be run or skipped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $commandShouldRun = true;
|
||||
private bool $commandShouldRun = true;
|
||||
|
||||
/**
|
||||
* Disables the command, so it won't be run.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function disableCommand()
|
||||
public function disableCommand(): bool
|
||||
{
|
||||
return $this->commandShouldRun = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the command.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function enableCommand()
|
||||
public function enableCommand(): bool
|
||||
{
|
||||
return $this->commandShouldRun = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the command is runnable, false otherwise.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function commandShouldRun()
|
||||
public function commandShouldRun(): bool
|
||||
{
|
||||
return $this->commandShouldRun;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
namespace Symfony\Component\Console\Event;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
@@ -23,61 +22,37 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
*/
|
||||
final class ConsoleErrorEvent extends ConsoleEvent
|
||||
{
|
||||
private $error;
|
||||
private $exitCode;
|
||||
private \Throwable $error;
|
||||
private int $exitCode;
|
||||
|
||||
public function __construct(InputInterface $input, OutputInterface $output, $error, Command $command = null)
|
||||
public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null)
|
||||
{
|
||||
parent::__construct($command, $input, $output);
|
||||
|
||||
$this->setError($error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thrown error/exception.
|
||||
*
|
||||
* @return \Throwable
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the thrown error/exception.
|
||||
*
|
||||
* @param \Throwable $error
|
||||
*/
|
||||
public function setError($error)
|
||||
{
|
||||
if (!$error instanceof \Throwable && !$error instanceof \Exception) {
|
||||
throw new InvalidArgumentException(sprintf('The error passed to ConsoleErrorEvent must be an instance of \Throwable or \Exception, "%s" was passed instead.', is_object($error) ? get_class($error) : gettype($error)));
|
||||
}
|
||||
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exit code.
|
||||
*
|
||||
* @param int $exitCode The command exit code
|
||||
*/
|
||||
public function setExitCode($exitCode)
|
||||
public function getError(): \Throwable
|
||||
{
|
||||
$this->exitCode = (int) $exitCode;
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
public function setError(\Throwable $error): void
|
||||
{
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
public function setExitCode(int $exitCode): void
|
||||
{
|
||||
$this->exitCode = $exitCode;
|
||||
|
||||
$r = new \ReflectionProperty($this->error, 'code');
|
||||
$r->setAccessible(true);
|
||||
$r->setValue($this->error, $this->exitCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exit code.
|
||||
*
|
||||
* @return int The command exit code
|
||||
*/
|
||||
public function getExitCode()
|
||||
public function getExitCode(): int
|
||||
{
|
||||
return null !== $this->exitCode ? $this->exitCode : ($this->error->getCode() ?: 1);
|
||||
return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
|
||||
}
|
||||
}
|
||||
|
||||
16
vendor/symfony/console/Event/ConsoleEvent.php
vendored
16
vendor/symfony/console/Event/ConsoleEvent.php
vendored
@@ -14,7 +14,7 @@ namespace Symfony\Component\Console\Event;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Allows to inspect input and output of a command.
|
||||
@@ -28,7 +28,7 @@ class ConsoleEvent extends Event
|
||||
private $input;
|
||||
private $output;
|
||||
|
||||
public function __construct(Command $command = null, InputInterface $input, OutputInterface $output)
|
||||
public function __construct(?Command $command, InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->command = $command;
|
||||
$this->input = $input;
|
||||
@@ -37,30 +37,24 @@ class ConsoleEvent extends Event
|
||||
|
||||
/**
|
||||
* Gets the command that is executed.
|
||||
*
|
||||
* @return Command|null A Command instance
|
||||
*/
|
||||
public function getCommand()
|
||||
public function getCommand(): ?Command
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input instance.
|
||||
*
|
||||
* @return InputInterface An InputInterface instance
|
||||
*/
|
||||
public function getInput()
|
||||
public function getInput(): InputInterface
|
||||
{
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output instance.
|
||||
*
|
||||
* @return OutputInterface An OutputInterface instance
|
||||
*/
|
||||
public function getOutput()
|
||||
public function getOutput(): OutputInterface
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console\Event;
|
||||
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since version 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', ConsoleExceptionEvent::class), E_USER_DEPRECATED);
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Allows to handle exception thrown in a command.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0. Use ConsoleErrorEvent instead.
|
||||
*/
|
||||
class ConsoleExceptionEvent extends ConsoleEvent
|
||||
{
|
||||
private $exception;
|
||||
private $exitCode;
|
||||
|
||||
public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
|
||||
{
|
||||
parent::__construct($command, $input, $output);
|
||||
|
||||
$this->setException($exception);
|
||||
$this->exitCode = (int) $exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thrown exception.
|
||||
*
|
||||
* @return \Exception The thrown exception
|
||||
*/
|
||||
public function getException()
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the thrown exception.
|
||||
*
|
||||
* This exception will be thrown if no response is set in the event.
|
||||
*
|
||||
* @param \Exception $exception The thrown exception
|
||||
*/
|
||||
public function setException(\Exception $exception)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exit code.
|
||||
*
|
||||
* @return int The command exit code
|
||||
*/
|
||||
public function getExitCode()
|
||||
{
|
||||
return $this->exitCode;
|
||||
}
|
||||
}
|
||||
35
vendor/symfony/console/Event/ConsoleSignalEvent.php
vendored
Normal file
35
vendor/symfony/console/Event/ConsoleSignalEvent.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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\Event;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @author marie <marie@users.noreply.github.com>
|
||||
*/
|
||||
final class ConsoleSignalEvent extends ConsoleEvent
|
||||
{
|
||||
private int $handlingSignal;
|
||||
|
||||
public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal)
|
||||
{
|
||||
parent::__construct($command, $input, $output);
|
||||
$this->handlingSignal = $handlingSignal;
|
||||
}
|
||||
|
||||
public function getHandlingSignal(): int
|
||||
{
|
||||
return $this->handlingSignal;
|
||||
}
|
||||
}
|
||||
@@ -20,38 +20,23 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
*
|
||||
* @author Francesco Levorato <git@flevour.net>
|
||||
*/
|
||||
class ConsoleTerminateEvent extends ConsoleEvent
|
||||
final class ConsoleTerminateEvent extends ConsoleEvent
|
||||
{
|
||||
/**
|
||||
* The exit code of the command.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $exitCode;
|
||||
private int $exitCode;
|
||||
|
||||
public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
|
||||
public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode)
|
||||
{
|
||||
parent::__construct($command, $input, $output);
|
||||
|
||||
$this->setExitCode($exitCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exit code.
|
||||
*
|
||||
* @param int $exitCode The command exit code
|
||||
*/
|
||||
public function setExitCode($exitCode)
|
||||
public function setExitCode(int $exitCode): void
|
||||
{
|
||||
$this->exitCode = (int) $exitCode;
|
||||
$this->exitCode = $exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exit code.
|
||||
*
|
||||
* @return int The command exit code
|
||||
*/
|
||||
public function getExitCode()
|
||||
public function getExitCode(): int
|
||||
{
|
||||
return $this->exitCode;
|
||||
}
|
||||
|
||||
@@ -40,10 +40,12 @@ class ErrorListener implements EventSubscriberInterface
|
||||
$error = $event->getError();
|
||||
|
||||
if (!$inputString = $this->getInputString($event)) {
|
||||
return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => $error->getMessage()));
|
||||
$this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => $inputString, 'message' => $error->getMessage()));
|
||||
$this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]);
|
||||
}
|
||||
|
||||
public function onConsoleTerminate(ConsoleTerminateEvent $event)
|
||||
@@ -59,28 +61,30 @@ class ErrorListener implements EventSubscriberInterface
|
||||
}
|
||||
|
||||
if (!$inputString = $this->getInputString($event)) {
|
||||
return $this->logger->error('The console exited with code "{code}"', array('code' => $exitCode));
|
||||
$this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logger->error('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode));
|
||||
$this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return array(
|
||||
ConsoleEvents::ERROR => array('onConsoleError', -128),
|
||||
ConsoleEvents::TERMINATE => array('onConsoleTerminate', -128),
|
||||
);
|
||||
return [
|
||||
ConsoleEvents::ERROR => ['onConsoleError', -128],
|
||||
ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128],
|
||||
];
|
||||
}
|
||||
|
||||
private static function getInputString(ConsoleEvent $event)
|
||||
private static function getInputString(ConsoleEvent $event): ?string
|
||||
{
|
||||
$commandName = $event->getCommand() ? $event->getCommand()->getName() : null;
|
||||
$input = $event->getInput();
|
||||
|
||||
if (method_exists($input, '__toString')) {
|
||||
if ($input instanceof \Stringable) {
|
||||
if ($commandName) {
|
||||
return str_replace(array("'$commandName'", "\"$commandName\""), $commandName, (string) $input);
|
||||
return str_replace(["'$commandName'", "\"$commandName\""], $commandName, (string) $input);
|
||||
}
|
||||
|
||||
return (string) $input;
|
||||
|
||||
@@ -18,15 +18,15 @@ namespace Symfony\Component\Console\Exception;
|
||||
*/
|
||||
class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
private $alternatives;
|
||||
private array $alternatives;
|
||||
|
||||
/**
|
||||
* @param string $message Exception message to throw
|
||||
* @param array $alternatives List of similar defined names
|
||||
* @param int $code Exception code
|
||||
* @param Exception $previous previous exception used for the exception chaining
|
||||
* @param string $message Exception message to throw
|
||||
* @param string[] $alternatives List of similar defined names
|
||||
* @param int $code Exception code
|
||||
* @param \Throwable|null $previous Previous exception used for the exception chaining
|
||||
*/
|
||||
public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
|
||||
public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
|
||||
@@ -34,9 +34,9 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array A list of similar defined names
|
||||
* @return string[]
|
||||
*/
|
||||
public function getAlternatives()
|
||||
public function getAlternatives(): array
|
||||
{
|
||||
return $this->alternatives;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ namespace Symfony\Component\Console\Exception;
|
||||
*
|
||||
* @author Jérôme Tamarelle <jerome@tamarelle.net>
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
interface ExceptionInterface extends \Throwable
|
||||
{
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Symfony\Component\Console\Exception;
|
||||
|
||||
/**
|
||||
* Represents an incorrect option name typed in the console.
|
||||
* Represents an incorrect option name or value typed in the console.
|
||||
*
|
||||
* @author Jérôme Tamarelle <jerome@tamarelle.net>
|
||||
*/
|
||||
|
||||
21
vendor/symfony/console/Exception/MissingInputException.php
vendored
Normal file
21
vendor/symfony/console/Exception/MissingInputException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console\Exception;
|
||||
|
||||
/**
|
||||
* Represents failure to read input from stdin.
|
||||
*
|
||||
* @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com>
|
||||
*/
|
||||
class MissingInputException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
21
vendor/symfony/console/Exception/NamespaceNotFoundException.php
vendored
Normal file
21
vendor/symfony/console/Exception/NamespaceNotFoundException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console\Exception;
|
||||
|
||||
/**
|
||||
* Represents an incorrect namespace typed in the console.
|
||||
*
|
||||
* @author Pierre du Plessis <pdples@gmail.com>
|
||||
*/
|
||||
class NamespaceNotFoundException extends CommandNotFoundException
|
||||
{
|
||||
}
|
||||
69
vendor/symfony/console/Formatter/NullOutputFormatter.php
vendored
Normal file
69
vendor/symfony/console/Formatter/NullOutputFormatter.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @author Tien Xuan Vo <tien.xuan.vo@gmail.com>
|
||||
*/
|
||||
final class NullOutputFormatter implements OutputFormatterInterface
|
||||
{
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function format(?string $message): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getStyle(string $name): OutputFormatterStyleInterface
|
||||
{
|
||||
// to comply with the interface we must return a OutputFormatterStyleInterface
|
||||
return $this->style ?? $this->style = new NullOutputFormatterStyle();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasStyle(string $name): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDecorated(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDecorated(bool $decorated): void
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setStyle(string $name, OutputFormatterStyleInterface $style): void
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
66
vendor/symfony/console/Formatter/NullOutputFormatterStyle.php
vendored
Normal file
66
vendor/symfony/console/Formatter/NullOutputFormatterStyle.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @author Tien Xuan Vo <tien.xuan.vo@gmail.com>
|
||||
*/
|
||||
final class NullOutputFormatterStyle implements OutputFormatterStyleInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply(string $text): string
|
||||
{
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setBackground(string $color = null): void
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setForeground(string $color = null): void
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOption(string $option): void
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOptions(array $options): void
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unsetOption(string $option): void
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
187
vendor/symfony/console/Formatter/OutputFormatter.php
vendored
187
vendor/symfony/console/Formatter/OutputFormatter.php
vendored
@@ -17,23 +17,28 @@ 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();
|
||||
private bool $decorated;
|
||||
private array $styles = [];
|
||||
private $styleStack;
|
||||
|
||||
/**
|
||||
* Escapes "<" special char in given text.
|
||||
*
|
||||
* @param string $text Text to escape
|
||||
*
|
||||
* @return string Escaped text
|
||||
*/
|
||||
public static function escape($text)
|
||||
public function __clone()
|
||||
{
|
||||
$text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
|
||||
$this->styleStack = clone $this->styleStack;
|
||||
foreach ($this->styles as $key => $value) {
|
||||
$this->styles[$key] = clone $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes "<" and ">" special chars in given text.
|
||||
*/
|
||||
public static function escape(string $text): string
|
||||
{
|
||||
$text = preg_replace('/([^\\\\]|^)([<>])/', '$1\\\\$2', $text);
|
||||
|
||||
return self::escapeTrailingBackslash($text);
|
||||
}
|
||||
@@ -41,18 +46,15 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
/**
|
||||
* Escapes trailing "\" in given text.
|
||||
*
|
||||
* @param string $text Text to escape
|
||||
*
|
||||
* @return string Escaped text
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function escapeTrailingBackslash($text)
|
||||
public static function escapeTrailingBackslash(string $text): string
|
||||
{
|
||||
if ('\\' === substr($text, -1)) {
|
||||
$len = strlen($text);
|
||||
if (str_ends_with($text, '\\')) {
|
||||
$len = \strlen($text);
|
||||
$text = rtrim($text, '\\');
|
||||
$text .= str_repeat('<<', $len - strlen($text));
|
||||
$text = str_replace("\0", '', $text);
|
||||
$text .= str_repeat("\0", $len - \strlen($text));
|
||||
}
|
||||
|
||||
return $text;
|
||||
@@ -61,12 +63,11 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
/**
|
||||
* Initializes console output formatter.
|
||||
*
|
||||
* @param bool $decorated Whether this formatter should actually decorate strings
|
||||
* @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
|
||||
* @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
|
||||
*/
|
||||
public function __construct($decorated = false, array $styles = array())
|
||||
public function __construct(bool $decorated = false, array $styles = [])
|
||||
{
|
||||
$this->decorated = (bool) $decorated;
|
||||
$this->decorated = $decorated;
|
||||
|
||||
$this->setStyle('error', new OutputFormatterStyle('white', 'red'));
|
||||
$this->setStyle('info', new OutputFormatterStyle('green'));
|
||||
@@ -83,15 +84,15 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDecorated($decorated)
|
||||
public function setDecorated(bool $decorated)
|
||||
{
|
||||
$this->decorated = (bool) $decorated;
|
||||
$this->decorated = $decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDecorated()
|
||||
public function isDecorated(): bool
|
||||
{
|
||||
return $this->decorated;
|
||||
}
|
||||
@@ -99,7 +100,7 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setStyle($name, OutputFormatterStyleInterface $style)
|
||||
public function setStyle(string $name, OutputFormatterStyleInterface $style)
|
||||
{
|
||||
$this->styles[strtolower($name)] = $style;
|
||||
}
|
||||
@@ -107,7 +108,7 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasStyle($name)
|
||||
public function hasStyle(string $name): bool
|
||||
{
|
||||
return isset($this->styles[strtolower($name)]);
|
||||
}
|
||||
@@ -115,10 +116,10 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getStyle($name)
|
||||
public function getStyle(string $name): OutputFormatterStyleInterface
|
||||
{
|
||||
if (!$this->hasStyle($name)) {
|
||||
throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
|
||||
throw new InvalidArgumentException(sprintf('Undefined style: "%s".', $name));
|
||||
}
|
||||
|
||||
return $this->styles[strtolower($name)];
|
||||
@@ -127,13 +128,26 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function format($message)
|
||||
public function format(?string $message): ?string
|
||||
{
|
||||
$message = (string) $message;
|
||||
return $this->formatAndWrap($message, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function formatAndWrap(?string $message, int $width)
|
||||
{
|
||||
if (null === $message) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$offset = 0;
|
||||
$output = '';
|
||||
$tagRegex = '[a-z][a-z0-9,_=;-]*+';
|
||||
preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
|
||||
$openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*';
|
||||
$closeTagRegex = '[a-z][^<>]*+';
|
||||
$currentLineLength = 0;
|
||||
preg_match_all("#<(($openTagRegex) | /($closeTagRegex)?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE);
|
||||
foreach ($matches[0] as $i => $match) {
|
||||
$pos = $match[1];
|
||||
$text = $match[0];
|
||||
@@ -143,21 +157,21 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
}
|
||||
|
||||
// add the text up to the next tag
|
||||
$output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
|
||||
$offset = $pos + strlen($text);
|
||||
$output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
|
||||
$offset = $pos + \strlen($text);
|
||||
|
||||
// opening tag?
|
||||
if ($open = '/' != $text[1]) {
|
||||
$tag = $matches[1][$i][0];
|
||||
} else {
|
||||
$tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
|
||||
$tag = $matches[3][$i][0] ?? '';
|
||||
}
|
||||
|
||||
if (!$open && !$tag) {
|
||||
// </>
|
||||
$this->styleStack->pop();
|
||||
} elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
|
||||
$output .= $this->applyCurrentStyle($text);
|
||||
} elseif (null === $style = $this->createStyleFromString($tag)) {
|
||||
$output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength);
|
||||
} elseif ($open) {
|
||||
$this->styleStack->push($style);
|
||||
} else {
|
||||
@@ -165,62 +179,49 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
}
|
||||
}
|
||||
|
||||
$output .= $this->applyCurrentStyle(substr($message, $offset));
|
||||
$output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength);
|
||||
|
||||
if (false !== strpos($output, '<<')) {
|
||||
return strtr($output, array('\\<' => '<', '<<' => '\\'));
|
||||
}
|
||||
|
||||
return str_replace('\\<', '<', $output);
|
||||
return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OutputFormatterStyleStack
|
||||
*/
|
||||
public function getStyleStack()
|
||||
public function getStyleStack(): OutputFormatterStyleStack
|
||||
{
|
||||
return $this->styleStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to create new style instance from string.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return OutputFormatterStyle|false false if string is not format string
|
||||
*/
|
||||
private function createStyleFromString($string)
|
||||
private function createStyleFromString(string $string): ?OutputFormatterStyleInterface
|
||||
{
|
||||
if (isset($this->styles[$string])) {
|
||||
return $this->styles[$string];
|
||||
}
|
||||
|
||||
if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, PREG_SET_ORDER)) {
|
||||
return false;
|
||||
if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$style = new OutputFormatterStyle();
|
||||
foreach ($matches as $match) {
|
||||
array_shift($match);
|
||||
$match[0] = strtolower($match[0]);
|
||||
|
||||
if ('fg' == $match[0]) {
|
||||
$style->setForeground($match[1]);
|
||||
$style->setForeground(strtolower($match[1]));
|
||||
} elseif ('bg' == $match[0]) {
|
||||
$style->setBackground($match[1]);
|
||||
$style->setBackground(strtolower($match[1]));
|
||||
} elseif ('href' === $match[0]) {
|
||||
$url = preg_replace('{\\\\([<>])}', '$1', $match[1]);
|
||||
$style->setHref($url);
|
||||
} elseif ('options' === $match[0]) {
|
||||
preg_match_all('([^,;]+)', $match[1], $options);
|
||||
preg_match_all('([^,;]+)', strtolower($match[1]), $options);
|
||||
$options = array_shift($options);
|
||||
foreach ($options as $option) {
|
||||
try {
|
||||
$style->setOption($option);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
@trigger_error(sprintf('Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "%s".', $e->getMessage()), E_USER_DEPRECATED);
|
||||
|
||||
return false;
|
||||
}
|
||||
$style->setOption($option);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,13 +230,51 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
|
||||
/**
|
||||
* Applies current style from stack to text, if must be applied.
|
||||
*
|
||||
* @param string $text Input text
|
||||
*
|
||||
* @return string Styled text
|
||||
*/
|
||||
private function applyCurrentStyle($text)
|
||||
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);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$currentLineLength += \strlen($line);
|
||||
if ($width <= $currentLineLength) {
|
||||
$currentLineLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isDecorated()) {
|
||||
foreach ($lines as $i => $line) {
|
||||
$lines[$i] = $this->styleStack->getCurrent()->apply($line);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $lines);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,52 +20,33 @@ interface OutputFormatterInterface
|
||||
{
|
||||
/**
|
||||
* Sets the decorated flag.
|
||||
*
|
||||
* @param bool $decorated Whether to decorate the messages or not
|
||||
*/
|
||||
public function setDecorated($decorated);
|
||||
public function setDecorated(bool $decorated);
|
||||
|
||||
/**
|
||||
* Gets the decorated flag.
|
||||
*
|
||||
* @return bool true if the output will decorate messages, false otherwise
|
||||
* Whether the output will decorate messages.
|
||||
*/
|
||||
public function isDecorated();
|
||||
public function isDecorated(): bool;
|
||||
|
||||
/**
|
||||
* Sets a new style.
|
||||
*
|
||||
* @param string $name The style name
|
||||
* @param OutputFormatterStyleInterface $style The style instance
|
||||
*/
|
||||
public function setStyle($name, OutputFormatterStyleInterface $style);
|
||||
public function setStyle(string $name, OutputFormatterStyleInterface $style);
|
||||
|
||||
/**
|
||||
* Checks if output formatter has style with specified name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasStyle($name);
|
||||
public function hasStyle(string $name): bool;
|
||||
|
||||
/**
|
||||
* Gets style options from style with specified name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return OutputFormatterStyleInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException When style isn't defined
|
||||
*/
|
||||
public function getStyle($name);
|
||||
public function getStyle(string $name): OutputFormatterStyleInterface;
|
||||
|
||||
/**
|
||||
* Formats a message according to the given styles.
|
||||
*
|
||||
* @param string $message The message to style
|
||||
*
|
||||
* @return string The styled message
|
||||
*/
|
||||
public function format($message);
|
||||
public function format(?string $message): ?string;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Console\Formatter;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Color;
|
||||
|
||||
/**
|
||||
* Formatter style class for defining styles.
|
||||
@@ -20,202 +20,87 @@ use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
*/
|
||||
class OutputFormatterStyle implements OutputFormatterStyleInterface
|
||||
{
|
||||
private static $availableForegroundColors = array(
|
||||
'black' => array('set' => 30, 'unset' => 39),
|
||||
'red' => array('set' => 31, 'unset' => 39),
|
||||
'green' => array('set' => 32, 'unset' => 39),
|
||||
'yellow' => array('set' => 33, 'unset' => 39),
|
||||
'blue' => array('set' => 34, 'unset' => 39),
|
||||
'magenta' => array('set' => 35, 'unset' => 39),
|
||||
'cyan' => array('set' => 36, 'unset' => 39),
|
||||
'white' => array('set' => 37, 'unset' => 39),
|
||||
'default' => array('set' => 39, 'unset' => 39),
|
||||
);
|
||||
private static $availableBackgroundColors = array(
|
||||
'black' => array('set' => 40, 'unset' => 49),
|
||||
'red' => array('set' => 41, 'unset' => 49),
|
||||
'green' => array('set' => 42, 'unset' => 49),
|
||||
'yellow' => array('set' => 43, 'unset' => 49),
|
||||
'blue' => array('set' => 44, 'unset' => 49),
|
||||
'magenta' => array('set' => 45, 'unset' => 49),
|
||||
'cyan' => array('set' => 46, 'unset' => 49),
|
||||
'white' => array('set' => 47, 'unset' => 49),
|
||||
'default' => array('set' => 49, 'unset' => 49),
|
||||
);
|
||||
private static $availableOptions = array(
|
||||
'bold' => array('set' => 1, 'unset' => 22),
|
||||
'underscore' => array('set' => 4, 'unset' => 24),
|
||||
'blink' => array('set' => 5, 'unset' => 25),
|
||||
'reverse' => array('set' => 7, 'unset' => 27),
|
||||
'conceal' => array('set' => 8, 'unset' => 28),
|
||||
);
|
||||
|
||||
private $foreground;
|
||||
private $background;
|
||||
private $options = array();
|
||||
private $color;
|
||||
private string $foreground;
|
||||
private string $background;
|
||||
private array $options;
|
||||
private ?string $href = null;
|
||||
private bool $handlesHrefGracefully;
|
||||
|
||||
/**
|
||||
* Initializes output formatter style.
|
||||
*
|
||||
* @param string|null $foreground The style foreground color name
|
||||
* @param string|null $background The style background color name
|
||||
* @param array $options The style options
|
||||
*/
|
||||
public function __construct($foreground = null, $background = null, array $options = array())
|
||||
public function __construct(string $foreground = null, string $background = null, array $options = [])
|
||||
{
|
||||
if (null !== $foreground) {
|
||||
$this->setForeground($foreground);
|
||||
}
|
||||
if (null !== $background) {
|
||||
$this->setBackground($background);
|
||||
}
|
||||
if (count($options)) {
|
||||
$this->setOptions($options);
|
||||
}
|
||||
$this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets style foreground color.
|
||||
*
|
||||
* @param string|null $color The color name
|
||||
*
|
||||
* @throws InvalidArgumentException When the color name isn't defined
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setForeground($color = null)
|
||||
public function setForeground(string $color = null)
|
||||
{
|
||||
if (null === $color) {
|
||||
$this->foreground = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset(static::$availableForegroundColors[$color])) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid foreground color specified: "%s". Expected one of (%s)',
|
||||
$color,
|
||||
implode(', ', array_keys(static::$availableForegroundColors))
|
||||
));
|
||||
}
|
||||
|
||||
$this->foreground = static::$availableForegroundColors[$color];
|
||||
$this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets style background color.
|
||||
*
|
||||
* @param string|null $color The color name
|
||||
*
|
||||
* @throws InvalidArgumentException When the color name isn't defined
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setBackground($color = null)
|
||||
public function setBackground(string $color = null)
|
||||
{
|
||||
if (null === $color) {
|
||||
$this->background = null;
|
||||
$this->color = new Color($this->foreground, $this->background = $color ?: '', $this->options);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset(static::$availableBackgroundColors[$color])) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid background color specified: "%s". Expected one of (%s)',
|
||||
$color,
|
||||
implode(', ', array_keys(static::$availableBackgroundColors))
|
||||
));
|
||||
}
|
||||
|
||||
$this->background = static::$availableBackgroundColors[$color];
|
||||
public function setHref(string $url): void
|
||||
{
|
||||
$this->href = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets some specific style option.
|
||||
*
|
||||
* @param string $option The option name
|
||||
*
|
||||
* @throws InvalidArgumentException When the option name isn't defined
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOption($option)
|
||||
public function setOption(string $option)
|
||||
{
|
||||
if (!isset(static::$availableOptions[$option])) {
|
||||
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)) {
|
||||
$this->options[] = static::$availableOptions[$option];
|
||||
}
|
||||
$this->options[] = $option;
|
||||
$this->color = new Color($this->foreground, $this->background, $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets some specific style option.
|
||||
*
|
||||
* @param string $option The option name
|
||||
*
|
||||
* @throws InvalidArgumentException When the option name isn't defined
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unsetOption($option)
|
||||
public function unsetOption(string $option)
|
||||
{
|
||||
if (!isset(static::$availableOptions[$option])) {
|
||||
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);
|
||||
$pos = array_search($option, $this->options);
|
||||
if (false !== $pos) {
|
||||
unset($this->options[$pos]);
|
||||
}
|
||||
|
||||
$this->color = new Color($this->foreground, $this->background, $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets multiple style options at once.
|
||||
*
|
||||
* @param array $options
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
$this->options = array();
|
||||
|
||||
foreach ($options as $option) {
|
||||
$this->setOption($option);
|
||||
}
|
||||
$this->color = new Color($this->foreground, $this->background, $this->options = $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style to a given text.
|
||||
*
|
||||
* @param string $text The text to style
|
||||
*
|
||||
* @return string
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply($text)
|
||||
public function apply(string $text): string
|
||||
{
|
||||
$setCodes = array();
|
||||
$unsetCodes = array();
|
||||
$this->handlesHrefGracefully ??= 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')
|
||||
&& (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100);
|
||||
|
||||
if (null !== $this->foreground) {
|
||||
$setCodes[] = $this->foreground['set'];
|
||||
$unsetCodes[] = $this->foreground['unset'];
|
||||
}
|
||||
if (null !== $this->background) {
|
||||
$setCodes[] = $this->background['set'];
|
||||
$unsetCodes[] = $this->background['unset'];
|
||||
}
|
||||
if (count($this->options)) {
|
||||
foreach ($this->options as $option) {
|
||||
$setCodes[] = $option['set'];
|
||||
$unsetCodes[] = $option['unset'];
|
||||
}
|
||||
if (null !== $this->href && $this->handlesHrefGracefully) {
|
||||
$text = "\033]8;;$this->href\033\\$text\033]8;;\033\\";
|
||||
}
|
||||
|
||||
if (0 === count($setCodes)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
|
||||
return $this->color->apply($text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,45 +20,31 @@ interface OutputFormatterStyleInterface
|
||||
{
|
||||
/**
|
||||
* Sets style foreground color.
|
||||
*
|
||||
* @param string $color The color name
|
||||
*/
|
||||
public function setForeground($color = null);
|
||||
public function setForeground(string $color = null);
|
||||
|
||||
/**
|
||||
* Sets style background color.
|
||||
*
|
||||
* @param string $color The color name
|
||||
*/
|
||||
public function setBackground($color = null);
|
||||
public function setBackground(string $color = null);
|
||||
|
||||
/**
|
||||
* Sets some specific style option.
|
||||
*
|
||||
* @param string $option The option name
|
||||
*/
|
||||
public function setOption($option);
|
||||
public function setOption(string $option);
|
||||
|
||||
/**
|
||||
* Unsets some specific style option.
|
||||
*
|
||||
* @param string $option The option name
|
||||
*/
|
||||
public function unsetOption($option);
|
||||
public function unsetOption(string $option);
|
||||
|
||||
/**
|
||||
* Sets multiple style options at once.
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function setOptions(array $options);
|
||||
|
||||
/**
|
||||
* Applies the style to a given text.
|
||||
*
|
||||
* @param string $text The text to style
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function apply($text);
|
||||
public function apply(string $text): string;
|
||||
}
|
||||
|
||||
@@ -12,30 +12,23 @@
|
||||
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[]
|
||||
*/
|
||||
private $styles;
|
||||
private array $styles = [];
|
||||
|
||||
/**
|
||||
* @var OutputFormatterStyleInterface
|
||||
*/
|
||||
private $emptyStyle;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param OutputFormatterStyleInterface|null $emptyStyle
|
||||
*/
|
||||
public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
|
||||
{
|
||||
$this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
|
||||
$this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle();
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
@@ -44,13 +37,11 @@ class OutputFormatterStyleStack
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->styles = array();
|
||||
$this->styles = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a style in the stack.
|
||||
*
|
||||
* @param OutputFormatterStyleInterface $style
|
||||
*/
|
||||
public function push(OutputFormatterStyleInterface $style)
|
||||
{
|
||||
@@ -60,13 +51,9 @@ class OutputFormatterStyleStack
|
||||
/**
|
||||
* Pops a style from the stack.
|
||||
*
|
||||
* @param OutputFormatterStyleInterface|null $style
|
||||
*
|
||||
* @return OutputFormatterStyleInterface
|
||||
*
|
||||
* @throws InvalidArgumentException When style tags incorrectly nested
|
||||
*/
|
||||
public function pop(OutputFormatterStyleInterface $style = null)
|
||||
public function pop(OutputFormatterStyleInterface $style = null): OutputFormatterStyleInterface
|
||||
{
|
||||
if (empty($this->styles)) {
|
||||
return $this->emptyStyle;
|
||||
@@ -78,7 +65,7 @@ class OutputFormatterStyleStack
|
||||
|
||||
foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
|
||||
if ($style->apply('') === $stackedStyle->apply('')) {
|
||||
$this->styles = array_slice($this->styles, 0, $index);
|
||||
$this->styles = \array_slice($this->styles, 0, $index);
|
||||
|
||||
return $stackedStyle;
|
||||
}
|
||||
@@ -89,34 +76,27 @@ class OutputFormatterStyleStack
|
||||
|
||||
/**
|
||||
* Computes current style with stacks top codes.
|
||||
*
|
||||
* @return OutputFormatterStyle
|
||||
*/
|
||||
public function getCurrent()
|
||||
public function getCurrent(): OutputFormatterStyleInterface
|
||||
{
|
||||
if (empty($this->styles)) {
|
||||
return $this->emptyStyle;
|
||||
}
|
||||
|
||||
return $this->styles[count($this->styles) - 1];
|
||||
return $this->styles[\count($this->styles) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OutputFormatterStyleInterface $emptyStyle
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
|
||||
public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle): static
|
||||
{
|
||||
$this->emptyStyle = $emptyStyle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OutputFormatterStyleInterface
|
||||
*/
|
||||
public function getEmptyStyle()
|
||||
public function getEmptyStyle(): OutputFormatterStyleInterface
|
||||
{
|
||||
return $this->emptyStyle;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -20,38 +20,24 @@ namespace Symfony\Component\Console\Helper;
|
||||
*/
|
||||
class DebugFormatterHelper extends Helper
|
||||
{
|
||||
private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
|
||||
private $started = array();
|
||||
private $count = -1;
|
||||
private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'];
|
||||
private array $started = [];
|
||||
private int $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'): string
|
||||
{
|
||||
$this->started[$id] = array('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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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'): string
|
||||
{
|
||||
$message = '';
|
||||
|
||||
@@ -84,15 +70,8 @@ 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'): string
|
||||
{
|
||||
$trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
|
||||
|
||||
@@ -107,20 +86,15 @@ class DebugFormatterHelper extends Helper
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id The id of the formatting session
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getBorder($id)
|
||||
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']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'debug_formatter';
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ use Symfony\Component\Console\Descriptor\JsonDescriptor;
|
||||
use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
|
||||
use Symfony\Component\Console\Descriptor\TextDescriptor;
|
||||
use Symfony\Component\Console\Descriptor\XmlDescriptor;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* This class adds helper method to describe objects in various formats.
|
||||
@@ -29,11 +29,8 @@ class DescriptorHelper extends Helper
|
||||
/**
|
||||
* @var DescriptorInterface[]
|
||||
*/
|
||||
private $descriptors = array();
|
||||
private array $descriptors = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
@@ -51,18 +48,14 @@ class DescriptorHelper extends Helper
|
||||
* * format: string, the output format name
|
||||
* * raw_text: boolean, sets output type as raw
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param object $object
|
||||
* @param array $options
|
||||
*
|
||||
* @throws InvalidArgumentException when the given format is not supported
|
||||
*/
|
||||
public function describe(OutputInterface $output, $object, array $options = array())
|
||||
public function describe(OutputInterface $output, ?object $object, array $options = [])
|
||||
{
|
||||
$options = array_merge(array(
|
||||
$options = array_merge([
|
||||
'raw_text' => false,
|
||||
'format' => 'txt',
|
||||
), $options);
|
||||
], $options);
|
||||
|
||||
if (!isset($this->descriptors[$options['format']])) {
|
||||
throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
|
||||
@@ -75,12 +68,9 @@ class DescriptorHelper extends Helper
|
||||
/**
|
||||
* Registers a descriptor.
|
||||
*
|
||||
* @param string $format
|
||||
* @param DescriptorInterface $descriptor
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function register($format, DescriptorInterface $descriptor)
|
||||
public function register(string $format, DescriptorInterface $descriptor): static
|
||||
{
|
||||
$this->descriptors[$format] = $descriptor;
|
||||
|
||||
@@ -90,8 +80,13 @@ class DescriptorHelper extends Helper
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'descriptor';
|
||||
}
|
||||
|
||||
public function getFormats(): array
|
||||
{
|
||||
return array_keys($this->descriptors);
|
||||
}
|
||||
}
|
||||
|
||||
64
vendor/symfony/console/Helper/Dumper.php
vendored
Normal file
64
vendor/symfony/console/Helper/Dumper.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||
|
||||
/**
|
||||
* @author Roland Franssen <franssen.roland@gmail.com>
|
||||
*/
|
||||
final class Dumper
|
||||
{
|
||||
private $output;
|
||||
private $dumper;
|
||||
private $cloner;
|
||||
private \Closure $handler;
|
||||
|
||||
public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null)
|
||||
{
|
||||
$this->output = $output;
|
||||
$this->dumper = $dumper;
|
||||
$this->cloner = $cloner;
|
||||
|
||||
if (class_exists(CliDumper::class)) {
|
||||
$this->handler = function ($var): string {
|
||||
$dumper = $this->dumper ?? $this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR);
|
||||
$dumper->setColors($this->output->isDecorated());
|
||||
|
||||
return rtrim($dumper->dump(($this->cloner ?? $this->cloner = new VarCloner())->cloneVar($var)->withRefHandles(false), true));
|
||||
};
|
||||
} else {
|
||||
$this->handler = function ($var): string {
|
||||
switch (true) {
|
||||
case null === $var:
|
||||
return 'null';
|
||||
case true === $var:
|
||||
return 'true';
|
||||
case false === $var:
|
||||
return 'false';
|
||||
case \is_string($var):
|
||||
return '"'.$var.'"';
|
||||
default:
|
||||
return rtrim(print_r($var, true));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public function __invoke(mixed $var): string
|
||||
{
|
||||
return ($this->handler)($var);
|
||||
}
|
||||
}
|
||||
@@ -22,44 +22,32 @@ 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
|
||||
*/
|
||||
public function formatSection($section, $message, $style = 'info')
|
||||
public function formatSection(string $section, string $message, string $style = 'info'): string
|
||||
{
|
||||
return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a message as a block of text.
|
||||
*
|
||||
* @param string|array $messages The message to write in the block
|
||||
* @param string $style The style to apply to the whole block
|
||||
* @param bool $large Whether to return a large block
|
||||
*
|
||||
* @return string The formatter message
|
||||
*/
|
||||
public function formatBlock($messages, $style, $large = false)
|
||||
public function formatBlock(string|array $messages, string $style, bool $large = false): string
|
||||
{
|
||||
if (!is_array($messages)) {
|
||||
$messages = array($messages);
|
||||
if (!\is_array($messages)) {
|
||||
$messages = [$messages];
|
||||
}
|
||||
|
||||
$len = 0;
|
||||
$lines = array();
|
||||
$lines = [];
|
||||
foreach ($messages as $message) {
|
||||
$message = OutputFormatter::escape($message);
|
||||
$lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
|
||||
$len = max($this->strlen($message) + ($large ? 4 : 2), $len);
|
||||
$len = max(self::width($message) + ($large ? 4 : 2), $len);
|
||||
}
|
||||
|
||||
$messages = $large ? array(str_repeat(' ', $len)) : array();
|
||||
$messages = $large ? [str_repeat(' ', $len)] : [];
|
||||
for ($i = 0; isset($lines[$i]); ++$i) {
|
||||
$messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
|
||||
$messages[] = $lines[$i].str_repeat(' ', $len - self::width($lines[$i]));
|
||||
}
|
||||
if ($large) {
|
||||
$messages[] = str_repeat(' ', $len);
|
||||
@@ -74,32 +62,22 @@ 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 = '...'): string
|
||||
{
|
||||
$computedLength = $length - $this->strlen($suffix);
|
||||
$computedLength = $length - self::width($suffix);
|
||||
|
||||
if ($computedLength > $this->strlen($message)) {
|
||||
if ($computedLength > self::width($message)) {
|
||||
return $message;
|
||||
}
|
||||
|
||||
if (false === $encoding = mb_detect_encoding($message, null, true)) {
|
||||
return substr($message, 0, $length).$suffix;
|
||||
}
|
||||
|
||||
return mb_substr($message, 0, $length, $encoding).$suffix;
|
||||
return self::substr($message, 0, $length).$suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'formatter';
|
||||
}
|
||||
|
||||
102
vendor/symfony/console/Helper/Helper.php
vendored
102
vendor/symfony/console/Helper/Helper.php
vendored
@@ -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.
|
||||
@@ -23,9 +24,7 @@ abstract class Helper implements HelperInterface
|
||||
protected $helperSet = null;
|
||||
|
||||
/**
|
||||
* Sets the helper set associated with this helper.
|
||||
*
|
||||
* @param HelperSet $helperSet A HelperSet instance
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setHelperSet(HelperSet $helperSet = null)
|
||||
{
|
||||
@@ -33,42 +32,58 @@ abstract class Helper implements HelperInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the helper set associated with this helper.
|
||||
*
|
||||
* @return HelperSet|null
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHelperSet()
|
||||
public function getHelperSet(): ?HelperSet
|
||||
{
|
||||
return $this->helperSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of a string, using mb_strwidth if it is available.
|
||||
*
|
||||
* @param string $string The string to check its length
|
||||
*
|
||||
* @return int The length of the 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 strlen($string)
|
||||
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);
|
||||
return \strlen($string);
|
||||
}
|
||||
|
||||
return mb_strwidth($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
|
||||
* 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 substr($string, $from, $length = null)
|
||||
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.
|
||||
*/
|
||||
public static function substr(?string $string, int $from, int $length = null): string
|
||||
{
|
||||
$string ?? $string = '';
|
||||
|
||||
if (false === $encoding = mb_detect_encoding($string, null, true)) {
|
||||
return substr($string, $from, $length);
|
||||
}
|
||||
@@ -76,26 +91,26 @@ abstract class Helper implements HelperInterface
|
||||
return mb_substr($string, $from, $length, $encoding);
|
||||
}
|
||||
|
||||
public static function formatTime($secs)
|
||||
public static function formatTime(int|float $secs)
|
||||
{
|
||||
static $timeFormats = array(
|
||||
array(0, '< 1 sec'),
|
||||
array(1, '1 sec'),
|
||||
array(2, 'secs', 1),
|
||||
array(60, '1 min'),
|
||||
array(120, 'mins', 60),
|
||||
array(3600, '1 hr'),
|
||||
array(7200, 'hrs', 3600),
|
||||
array(86400, '1 day'),
|
||||
array(172800, 'days', 86400),
|
||||
);
|
||||
static $timeFormats = [
|
||||
[0, '< 1 sec'],
|
||||
[1, '1 sec'],
|
||||
[2, 'secs', 1],
|
||||
[60, '1 min'],
|
||||
[120, 'mins', 60],
|
||||
[3600, '1 hr'],
|
||||
[7200, 'hrs', 3600],
|
||||
[86400, '1 day'],
|
||||
[172800, 'days', 86400],
|
||||
];
|
||||
|
||||
foreach ($timeFormats as $index => $format) {
|
||||
if ($secs >= $format[0]) {
|
||||
if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
|
||||
|| $index == count($timeFormats) - 1
|
||||
|| $index == \count($timeFormats) - 1
|
||||
) {
|
||||
if (2 == count($format)) {
|
||||
if (2 == \count($format)) {
|
||||
return $format[1];
|
||||
}
|
||||
|
||||
@@ -105,7 +120,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,19 +137,16 @@ abstract class Helper implements HelperInterface
|
||||
return sprintf('%d B', $memory);
|
||||
}
|
||||
|
||||
public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
|
||||
{
|
||||
return self::strlen(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 ?? '');
|
||||
$formatter->setDecorated($isDecorated);
|
||||
|
||||
return $string;
|
||||
|
||||
@@ -20,22 +20,18 @@ interface HelperInterface
|
||||
{
|
||||
/**
|
||||
* Sets the helper set associated with this helper.
|
||||
*
|
||||
* @param HelperSet $helperSet A HelperSet instance
|
||||
*/
|
||||
public function setHelperSet(HelperSet $helperSet = null);
|
||||
|
||||
/**
|
||||
* Gets the helper set associated with this helper.
|
||||
*
|
||||
* @return HelperSet A HelperSet instance
|
||||
*/
|
||||
public function getHelperSet();
|
||||
public function getHelperSet(): ?HelperSet;
|
||||
|
||||
/**
|
||||
* Returns the canonical name of this helper.
|
||||
*
|
||||
* @return string The canonical name
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
}
|
||||
|
||||
61
vendor/symfony/console/Helper/HelperSet.php
vendored
61
vendor/symfony/console/Helper/HelperSet.php
vendored
@@ -11,41 +11,31 @@
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* HelperSet represents a set of helpers to be used with a command.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @implements \IteratorAggregate<string, Helper>
|
||||
*/
|
||||
class HelperSet implements \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var Helper[]
|
||||
*/
|
||||
private $helpers = array();
|
||||
private $command;
|
||||
/** @var array<string, Helper> */
|
||||
private array $helpers = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Helper[] $helpers An array of helper
|
||||
*/
|
||||
public function __construct(array $helpers = array())
|
||||
public function __construct(array $helpers = [])
|
||||
{
|
||||
foreach ($helpers as $alias => $helper) {
|
||||
$this->set($helper, is_int($alias) ? null : $alias);
|
||||
$this->set($helper, \is_int($alias) ? null : $alias);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a helper.
|
||||
*
|
||||
* @param HelperInterface $helper The helper instance
|
||||
* @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) {
|
||||
@@ -57,12 +47,8 @@ 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
|
||||
*/
|
||||
public function has($name)
|
||||
public function has(string $name): bool
|
||||
{
|
||||
return isset($this->helpers[$name]);
|
||||
}
|
||||
@@ -70,13 +56,9 @@ class HelperSet implements \IteratorAggregate
|
||||
/**
|
||||
* Gets a helper value.
|
||||
*
|
||||
* @param string $name The helper name
|
||||
*
|
||||
* @return HelperInterface The helper instance
|
||||
*
|
||||
* @throws InvalidArgumentException if the helper is not defined
|
||||
*/
|
||||
public function get($name)
|
||||
public function get(string $name): HelperInterface
|
||||
{
|
||||
if (!$this->has($name)) {
|
||||
throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
|
||||
@@ -85,30 +67,7 @@ class HelperSet implements \IteratorAggregate
|
||||
return $this->helpers[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command associated with this helper set.
|
||||
*
|
||||
* @param Command $command A Command instance
|
||||
*/
|
||||
public function setCommand(Command $command = null)
|
||||
{
|
||||
$this->command = $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command associated with this helper set.
|
||||
*
|
||||
* @return Command A Command instance
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Helper[]
|
||||
*/
|
||||
public function getIterator()
|
||||
public function getIterator(): \Traversable
|
||||
{
|
||||
return new \ArrayIterator($this->helpers);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputAwareInterface;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* An implementation of InputAwareInterface for Helpers.
|
||||
|
||||
64
vendor/symfony/console/Helper/ProcessHelper.php
vendored
64
vendor/symfony/console/Helper/ProcessHelper.php
vendored
@@ -15,41 +15,47 @@ use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\ProcessBuilder;
|
||||
|
||||
/**
|
||||
* The ProcessHelper class provides helpers to run external processes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @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, array|Process $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".');
|
||||
}
|
||||
|
||||
if ($output instanceof ConsoleOutputInterface) {
|
||||
$output = $output->getErrorOutput();
|
||||
}
|
||||
|
||||
$formatter = $this->getHelperSet()->get('debug_formatter');
|
||||
|
||||
if (is_array($cmd)) {
|
||||
$process = ProcessBuilder::create($cmd)->getProcess();
|
||||
} elseif ($cmd instanceof Process) {
|
||||
$process = $cmd;
|
||||
} else {
|
||||
if ($cmd instanceof Process) {
|
||||
$cmd = [$cmd];
|
||||
}
|
||||
|
||||
if (\is_string($cmd[0] ?? null)) {
|
||||
$process = new Process($cmd);
|
||||
$cmd = [];
|
||||
} 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 be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__));
|
||||
}
|
||||
|
||||
if ($verbosity <= $output->getVerbosity()) {
|
||||
@@ -60,7 +66,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());
|
||||
@@ -80,19 +86,15 @@ class ProcessHelper extends Helper
|
||||
* This is identical to run() except that an exception is thrown if the process
|
||||
* exits with a non-zero exit code.
|
||||
*
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @param string|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
|
||||
* @param array|Process $cmd An instance of Process or a command to run
|
||||
* @param callable|null $callback A PHP callback to run whenever there is some
|
||||
* output available on STDOUT or STDERR
|
||||
*
|
||||
* @throws ProcessFailedException
|
||||
*
|
||||
* @see run()
|
||||
*/
|
||||
public function mustRun(OutputInterface $output, $cmd, $error = null, callable $callback = null)
|
||||
public function mustRun(OutputInterface $output, array|Process $cmd, string $error = null, callable $callback = null): Process
|
||||
{
|
||||
$process = $this->run($output, $cmd, $error, $callback);
|
||||
|
||||
@@ -105,14 +107,8 @@ class ProcessHelper extends Helper
|
||||
|
||||
/**
|
||||
* Wraps a Process callback to add debugging output.
|
||||
*
|
||||
* @param OutputInterface $output An OutputInterface interface
|
||||
* @param Process $process The Process
|
||||
* @param callable|null $callback A PHP callable
|
||||
*
|
||||
* @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();
|
||||
@@ -124,12 +120,12 @@ class ProcessHelper extends Helper
|
||||
$output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type));
|
||||
|
||||
if (null !== $callback) {
|
||||
call_user_func($callback, $type, $buffer);
|
||||
$callback($type, $buffer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private function escapeString($str)
|
||||
private function escapeString(string $str): string
|
||||
{
|
||||
return str_replace('<', '\\<', $str);
|
||||
}
|
||||
@@ -137,7 +133,7 @@ class ProcessHelper extends Helper
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'process';
|
||||
}
|
||||
|
||||
477
vendor/symfony/console/Helper/ProgressBar.php
vendored
477
vendor/symfony/console/Helper/ProgressBar.php
vendored
@@ -11,9 +11,11 @@
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Cursor;
|
||||
use Symfony\Component\Console\Exception\LogicException;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Terminal;
|
||||
|
||||
/**
|
||||
@@ -24,38 +26,46 @@ use Symfony\Component\Console\Terminal;
|
||||
*/
|
||||
final class ProgressBar
|
||||
{
|
||||
// options
|
||||
private $barWidth = 28;
|
||||
private $barChar;
|
||||
private $emptyBarChar = '-';
|
||||
private $progressChar = '>';
|
||||
private $format;
|
||||
private $internalFormat;
|
||||
private $redrawFreq = 1;
|
||||
public const FORMAT_VERBOSE = 'verbose';
|
||||
public const FORMAT_VERY_VERBOSE = 'very_verbose';
|
||||
public const FORMAT_DEBUG = 'debug';
|
||||
public const FORMAT_NORMAL = 'normal';
|
||||
|
||||
/**
|
||||
* @var OutputInterface
|
||||
*/
|
||||
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 int $barWidth = 28;
|
||||
private string $barChar;
|
||||
private string $emptyBarChar = '-';
|
||||
private string $progressChar = '>';
|
||||
private ?string $format = null;
|
||||
private ?string $internalFormat = null;
|
||||
private ?int $redrawFreq = 1;
|
||||
private int $writeCount = 0;
|
||||
private float $lastWriteTime = 0;
|
||||
private float $minSecondsBetweenRedraws = 0;
|
||||
private float $maxSecondsBetweenRedraws = 1;
|
||||
private $output;
|
||||
private $step = 0;
|
||||
private $max;
|
||||
private $startTime;
|
||||
private $stepWidth;
|
||||
private $percent = 0.0;
|
||||
private $formatLineCount;
|
||||
private $messages = array();
|
||||
private $overwrite = true;
|
||||
private int $step = 0;
|
||||
private ?int $max = null;
|
||||
private int $startTime;
|
||||
private int $stepWidth;
|
||||
private float $percent = 0.0;
|
||||
private array $messages = [];
|
||||
private bool $overwrite = true;
|
||||
private $terminal;
|
||||
private $firstRun = true;
|
||||
private ?string $previousMessage = null;
|
||||
private $cursor;
|
||||
|
||||
private static $formatters;
|
||||
private static $formats;
|
||||
private static array $formatters;
|
||||
private static array $formats;
|
||||
|
||||
/**
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @param int $max Maximum steps (0 if unknown)
|
||||
* @param int $max Maximum steps (0 if unknown)
|
||||
*/
|
||||
public function __construct(OutputInterface $output, $max = 0)
|
||||
public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25)
|
||||
{
|
||||
if ($output instanceof ConsoleOutputInterface) {
|
||||
$output = $output->getErrorOutput();
|
||||
@@ -65,15 +75,21 @@ final class ProgressBar
|
||||
$this->setMaxSteps($max);
|
||||
$this->terminal = new Terminal();
|
||||
|
||||
if (0 < $minSecondsBetweenRedraws) {
|
||||
$this->redrawFreq = null;
|
||||
$this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws;
|
||||
}
|
||||
|
||||
if (!$this->output->isDecorated()) {
|
||||
// disable overwrite when output does not support ANSI codes.
|
||||
$this->overwrite = false;
|
||||
|
||||
// set a reasonable redraw frequency so output isn't flooded
|
||||
$this->setRedrawFrequency($max / 10);
|
||||
$this->redrawFreq = null;
|
||||
}
|
||||
|
||||
$this->startTime = time();
|
||||
$this->cursor = new Cursor($output);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,11 +100,9 @@ final class ProgressBar
|
||||
* @param string $name The placeholder name (including the delimiter char like %)
|
||||
* @param callable $callable A PHP callable
|
||||
*/
|
||||
public static function setPlaceholderFormatterDefinition($name, callable $callable)
|
||||
public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void
|
||||
{
|
||||
if (!self::$formatters) {
|
||||
self::$formatters = self::initPlaceholderFormatters();
|
||||
}
|
||||
self::$formatters ??= self::initPlaceholderFormatters();
|
||||
|
||||
self::$formatters[$name] = $callable;
|
||||
}
|
||||
@@ -97,16 +111,12 @@ 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($name)
|
||||
public static function getPlaceholderFormatterDefinition(string $name): ?callable
|
||||
{
|
||||
if (!self::$formatters) {
|
||||
self::$formatters = self::initPlaceholderFormatters();
|
||||
}
|
||||
self::$formatters ??= self::initPlaceholderFormatters();
|
||||
|
||||
return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
|
||||
return self::$formatters[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,11 +127,9 @@ final class ProgressBar
|
||||
* @param string $name The format name
|
||||
* @param string $format A format string
|
||||
*/
|
||||
public static function setFormatDefinition($name, $format)
|
||||
public static function setFormatDefinition(string $name, string $format): void
|
||||
{
|
||||
if (!self::$formats) {
|
||||
self::$formats = self::initFormats();
|
||||
}
|
||||
self::$formats ??= self::initFormats();
|
||||
|
||||
self::$formats[$name] = $format;
|
||||
}
|
||||
@@ -130,16 +138,12 @@ 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($name)
|
||||
public static function getFormatDefinition(string $name): ?string
|
||||
{
|
||||
if (!self::$formats) {
|
||||
self::$formats = self::initFormats();
|
||||
}
|
||||
self::$formats ??= self::initFormats();
|
||||
|
||||
return isset(self::$formats[$name]) ? self::$formats[$name] : null;
|
||||
return self::$formats[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,156 +156,105 @@ final class ProgressBar
|
||||
* @param string $message The text to associate with the placeholder
|
||||
* @param string $name The name of the placeholder
|
||||
*/
|
||||
public function setMessage($message, $name = 'message')
|
||||
public function setMessage(string $message, string $name = 'message')
|
||||
{
|
||||
$this->messages[$name] = $message;
|
||||
}
|
||||
|
||||
public function getMessage($name = 'message')
|
||||
public function getMessage(string $name = 'message')
|
||||
{
|
||||
return $this->messages[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the progress bar start time.
|
||||
*
|
||||
* @return int The progress bar start time
|
||||
*/
|
||||
public function getStartTime()
|
||||
public function getStartTime(): int
|
||||
{
|
||||
return $this->startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the progress bar maximal steps.
|
||||
*
|
||||
* @return int The progress bar max steps
|
||||
*/
|
||||
public function getMaxSteps()
|
||||
public function getMaxSteps(): int
|
||||
{
|
||||
return $this->max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current step position.
|
||||
*
|
||||
* @return int The progress bar step
|
||||
*/
|
||||
public function getProgress()
|
||||
public function getProgress(): int
|
||||
{
|
||||
return $this->step;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the progress bar step width.
|
||||
*
|
||||
* @return int The progress bar step width
|
||||
*/
|
||||
private function getStepWidth()
|
||||
private function getStepWidth(): int
|
||||
{
|
||||
return $this->stepWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current progress bar percent.
|
||||
*
|
||||
* @return float The current progress bar percent
|
||||
*/
|
||||
public function getProgressPercent()
|
||||
public function getProgressPercent(): float
|
||||
{
|
||||
return $this->percent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress bar width.
|
||||
*
|
||||
* @param int $size The progress bar size
|
||||
*/
|
||||
public function setBarWidth($size)
|
||||
public function getBarOffset(): float
|
||||
{
|
||||
$this->barWidth = max(1, (int) $size);
|
||||
return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the progress bar width.
|
||||
*
|
||||
* @return int The progress bar size
|
||||
*/
|
||||
public function getBarWidth()
|
||||
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);
|
||||
}
|
||||
|
||||
public function getBarWidth(): int
|
||||
{
|
||||
return $this->barWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bar character.
|
||||
*
|
||||
* @param string $char A character
|
||||
*/
|
||||
public function setBarCharacter($char)
|
||||
public function setBarCharacter(string $char)
|
||||
{
|
||||
$this->barChar = $char;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bar character.
|
||||
*
|
||||
* @return string A character
|
||||
*/
|
||||
public function getBarCharacter()
|
||||
public function getBarCharacter(): string
|
||||
{
|
||||
if (null === $this->barChar) {
|
||||
return $this->max ? '=' : $this->emptyBarChar;
|
||||
}
|
||||
|
||||
return $this->barChar;
|
||||
return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the empty bar character.
|
||||
*
|
||||
* @param string $char A character
|
||||
*/
|
||||
public function setEmptyBarCharacter($char)
|
||||
public function setEmptyBarCharacter(string $char)
|
||||
{
|
||||
$this->emptyBarChar = $char;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the empty bar character.
|
||||
*
|
||||
* @return string A character
|
||||
*/
|
||||
public function getEmptyBarCharacter()
|
||||
public function getEmptyBarCharacter(): string
|
||||
{
|
||||
return $this->emptyBarChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress bar character.
|
||||
*
|
||||
* @param string $char A character
|
||||
*/
|
||||
public function setProgressCharacter($char)
|
||||
public function setProgressCharacter(string $char)
|
||||
{
|
||||
$this->progressChar = $char;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the progress bar character.
|
||||
*
|
||||
* @return string A character
|
||||
*/
|
||||
public function getProgressCharacter()
|
||||
public function getProgressCharacter(): string
|
||||
{
|
||||
return $this->progressChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress bar format.
|
||||
*
|
||||
* @param string $format The format
|
||||
*/
|
||||
public function setFormat($format)
|
||||
public function setFormat(string $format)
|
||||
{
|
||||
$this->format = null;
|
||||
$this->internalFormat = $format;
|
||||
@@ -310,11 +263,39 @@ final class ProgressBar
|
||||
/**
|
||||
* Sets the redraw frequency.
|
||||
*
|
||||
* @param int|float $freq The frequency in steps
|
||||
* @param int|null $freq The frequency in steps
|
||||
*/
|
||||
public function setRedrawFrequency($freq)
|
||||
public function setRedrawFrequency(?int $freq)
|
||||
{
|
||||
$this->redrawFreq = max((int) $freq, 1);
|
||||
$this->redrawFreq = null !== $freq ? max(1, $freq) : null;
|
||||
}
|
||||
|
||||
public function minSecondsBetweenRedraws(float $seconds): void
|
||||
{
|
||||
$this->minSecondsBetweenRedraws = $seconds;
|
||||
}
|
||||
|
||||
public function maxSecondsBetweenRedraws(float $seconds): void
|
||||
{
|
||||
$this->maxSecondsBetweenRedraws = $seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator that will automatically update the progress bar when iterated.
|
||||
*
|
||||
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
|
||||
*/
|
||||
public function iterate(iterable $iterable, int $max = null): iterable
|
||||
{
|
||||
$this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0));
|
||||
|
||||
foreach ($iterable as $key => $value) {
|
||||
yield $key => $value;
|
||||
|
||||
$this->advance();
|
||||
}
|
||||
|
||||
$this->finish();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,7 +303,7 @@ final class ProgressBar
|
||||
*
|
||||
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
|
||||
*/
|
||||
public function start($max = null)
|
||||
public function start(int $max = null)
|
||||
{
|
||||
$this->startTime = time();
|
||||
$this->step = 0;
|
||||
@@ -340,49 +321,63 @@ final class ProgressBar
|
||||
*
|
||||
* @param int $step Number of steps to advance
|
||||
*/
|
||||
public function advance($step = 1)
|
||||
public function advance(int $step = 1)
|
||||
{
|
||||
$this->setProgress($this->step + $step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to overwrite the progressbar, false for new line.
|
||||
*
|
||||
* @param bool $overwrite
|
||||
*/
|
||||
public function setOverwrite($overwrite)
|
||||
public function setOverwrite(bool $overwrite)
|
||||
{
|
||||
$this->overwrite = (bool) $overwrite;
|
||||
$this->overwrite = $overwrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current progress.
|
||||
*
|
||||
* @param int $step The current progress
|
||||
*/
|
||||
public function setProgress($step)
|
||||
public function setProgress(int $step)
|
||||
{
|
||||
$step = (int) $step;
|
||||
|
||||
if ($this->max && $step > $this->max) {
|
||||
$this->max = $step;
|
||||
} elseif ($step < 0) {
|
||||
$step = 0;
|
||||
}
|
||||
|
||||
$prevPeriod = (int) ($this->step / $this->redrawFreq);
|
||||
$currPeriod = (int) ($step / $this->redrawFreq);
|
||||
$redrawFreq = $this->redrawFreq ?? (($this->max ?: 10) / 10);
|
||||
$prevPeriod = (int) ($this->step / $redrawFreq);
|
||||
$currPeriod = (int) ($step / $redrawFreq);
|
||||
$this->step = $step;
|
||||
$this->percent = $this->max ? (float) $this->step / $this->max : 0;
|
||||
if ($prevPeriod !== $currPeriod || $this->max === $step) {
|
||||
$timeInterval = microtime(true) - $this->lastWriteTime;
|
||||
|
||||
// Draw regardless of other limits
|
||||
if ($this->max === $step) {
|
||||
$this->display();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Throttling
|
||||
if ($timeInterval < $this->minSecondsBetweenRedraws) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw each step period, but not too late
|
||||
if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) {
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
|
||||
public function setMaxSteps(int $max)
|
||||
{
|
||||
$this->format = null;
|
||||
$this->max = max(0, $max);
|
||||
$this->stepWidth = $this->max ? Helper::width((string) $this->max) : 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the progress output.
|
||||
*/
|
||||
public function finish()
|
||||
public function finish(): void
|
||||
{
|
||||
if (!$this->max) {
|
||||
$this->max = $this->step;
|
||||
@@ -399,7 +394,7 @@ final class ProgressBar
|
||||
/**
|
||||
* Outputs the current progress string.
|
||||
*/
|
||||
public function display()
|
||||
public function display(): void
|
||||
{
|
||||
if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
|
||||
return;
|
||||
@@ -419,7 +414,7 @@ final class ProgressBar
|
||||
* while a progress bar is running.
|
||||
* Call display() to show the progress bar again.
|
||||
*/
|
||||
public function clear()
|
||||
public function clear(): void
|
||||
{
|
||||
if (!$this->overwrite) {
|
||||
return;
|
||||
@@ -432,12 +427,7 @@ final class ProgressBar
|
||||
$this->overwrite('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress bar format.
|
||||
*
|
||||
* @param string $format The format
|
||||
*/
|
||||
private function setRealFormat($format)
|
||||
private function setRealFormat(string $format)
|
||||
{
|
||||
// try to use the _nomax variant if available
|
||||
if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
|
||||
@@ -447,148 +437,139 @@ final class ProgressBar
|
||||
} else {
|
||||
$this->format = $format;
|
||||
}
|
||||
|
||||
$this->formatLineCount = substr_count($this->format, "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress bar maximal steps.
|
||||
*
|
||||
* @param int $max The progress bar max steps
|
||||
*/
|
||||
private function setMaxSteps($max)
|
||||
{
|
||||
$this->max = max(0, (int) $max);
|
||||
$this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites a previous message to the output.
|
||||
*
|
||||
* @param string $message The message
|
||||
*/
|
||||
private function overwrite($message)
|
||||
private function overwrite(string $message): void
|
||||
{
|
||||
if ($this->previousMessage === $message) {
|
||||
return;
|
||||
}
|
||||
|
||||
$originalMessage = $message;
|
||||
|
||||
if ($this->overwrite) {
|
||||
if (!$this->firstRun) {
|
||||
// Move the cursor to the beginning of the line
|
||||
$this->output->write("\x0D");
|
||||
if (null !== $this->previousMessage) {
|
||||
if ($this->output instanceof ConsoleSectionOutput) {
|
||||
$messageLines = explode("\n", $this->previousMessage);
|
||||
$lineCount = \count($messageLines);
|
||||
foreach ($messageLines as $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 {
|
||||
$lineCount = substr_count($this->previousMessage, "\n");
|
||||
for ($i = 0; $i < $lineCount; ++$i) {
|
||||
$this->cursor->moveToColumn(1);
|
||||
$this->cursor->clearLine();
|
||||
$this->cursor->moveUp();
|
||||
}
|
||||
|
||||
// Erase the line
|
||||
$this->output->write("\x1B[2K");
|
||||
|
||||
// Erase previous lines
|
||||
if ($this->formatLineCount > 0) {
|
||||
$this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
|
||||
$this->cursor->moveToColumn(1);
|
||||
$this->cursor->clearLine();
|
||||
}
|
||||
}
|
||||
} elseif ($this->step > 0) {
|
||||
$this->output->writeln('');
|
||||
$message = \PHP_EOL.$message;
|
||||
}
|
||||
|
||||
$this->firstRun = false;
|
||||
$this->previousMessage = $originalMessage;
|
||||
$this->lastWriteTime = microtime(true);
|
||||
|
||||
$this->output->write($message);
|
||||
++$this->writeCount;
|
||||
}
|
||||
|
||||
private function determineBestFormat()
|
||||
private function determineBestFormat(): string
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static function initPlaceholderFormatters()
|
||||
private static function initPlaceholderFormatters(): array
|
||||
{
|
||||
return array(
|
||||
'bar' => function (ProgressBar $bar, OutputInterface $output) {
|
||||
$completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
|
||||
return [
|
||||
'bar' => function (self $bar, OutputInterface $output) {
|
||||
$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);
|
||||
}
|
||||
|
||||
return $display;
|
||||
},
|
||||
'elapsed' => function (ProgressBar $bar) {
|
||||
'elapsed' => function (self $bar) {
|
||||
return Helper::formatTime(time() - $bar->getStartTime());
|
||||
},
|
||||
'remaining' => function (ProgressBar $bar) {
|
||||
'remaining' => function (self $bar) {
|
||||
if (!$bar->getMaxSteps()) {
|
||||
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 (ProgressBar $bar) {
|
||||
'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 (ProgressBar $bar) {
|
||||
'memory' => function (self $bar) {
|
||||
return Helper::formatMemory(memory_get_usage(true));
|
||||
},
|
||||
'current' => function (ProgressBar $bar) {
|
||||
return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
|
||||
'current' => function (self $bar) {
|
||||
return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT);
|
||||
},
|
||||
'max' => function (ProgressBar $bar) {
|
||||
'max' => function (self $bar) {
|
||||
return $bar->getMaxSteps();
|
||||
},
|
||||
'percent' => function (ProgressBar $bar) {
|
||||
'percent' => function (self $bar) {
|
||||
return floor($bar->getProgressPercent() * 100);
|
||||
},
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
private static function initFormats()
|
||||
private static function initFormats(): array
|
||||
{
|
||||
return array(
|
||||
'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
|
||||
'normal_nomax' => ' %current% [%bar%]',
|
||||
return [
|
||||
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%',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function buildLine()
|
||||
private function buildLine(): string
|
||||
{
|
||||
\assert(null !== $this->format);
|
||||
|
||||
$regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i";
|
||||
$callback = function ($matches) {
|
||||
if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) {
|
||||
$text = call_user_func($formatter, $this, $this->output);
|
||||
$text = $formatter($this, $this->output);
|
||||
} elseif (isset($this->messages[$matches[1]])) {
|
||||
$text = $this->messages[$matches[1]];
|
||||
} else {
|
||||
@@ -605,7 +586,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);
|
||||
|
||||
141
vendor/symfony/console/Helper/ProgressIndicator.php
vendored
141
vendor/symfony/console/Helper/ProgressIndicator.php
vendored
@@ -20,26 +20,37 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
*/
|
||||
class ProgressIndicator
|
||||
{
|
||||
private $output;
|
||||
private $startTime;
|
||||
private $format;
|
||||
private $message;
|
||||
private $indicatorValues;
|
||||
private $indicatorCurrent;
|
||||
private $indicatorChangeInterval;
|
||||
private $indicatorUpdateTime;
|
||||
private $started = false;
|
||||
private const FORMATS = [
|
||||
'normal' => ' %indicator% %message%',
|
||||
'normal_no_ansi' => ' %message%',
|
||||
|
||||
private static $formatters;
|
||||
private static $formats;
|
||||
'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 int $startTime;
|
||||
private ?string $format = null;
|
||||
private ?string $message = null;
|
||||
private array $indicatorValues;
|
||||
private int $indicatorCurrent;
|
||||
private int $indicatorChangeInterval;
|
||||
private float $indicatorUpdateTime;
|
||||
private bool $started = false;
|
||||
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
* @param string|null $format Indicator format
|
||||
* @param int $indicatorChangeInterval Change interval in milliseconds
|
||||
* @param array|null $indicatorValues Animated indicator characters
|
||||
* @var array<string, callable>
|
||||
*/
|
||||
public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
|
||||
private static array $formatters;
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
$this->output = $output;
|
||||
|
||||
@@ -48,12 +59,12 @@ class ProgressIndicator
|
||||
}
|
||||
|
||||
if (null === $indicatorValues) {
|
||||
$indicatorValues = array('-', '\\', '|', '/');
|
||||
$indicatorValues = ['-', '\\', '|', '/'];
|
||||
}
|
||||
|
||||
$indicatorValues = array_values($indicatorValues);
|
||||
|
||||
if (2 > count($indicatorValues)) {
|
||||
if (2 > \count($indicatorValues)) {
|
||||
throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
|
||||
}
|
||||
|
||||
@@ -65,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;
|
||||
|
||||
@@ -77,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.');
|
||||
@@ -125,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,51 +146,32 @@ class ProgressIndicator
|
||||
|
||||
/**
|
||||
* Gets the format for a given name.
|
||||
*
|
||||
* @param string $name The format name
|
||||
*
|
||||
* @return string|null A format string
|
||||
*/
|
||||
public static function getFormatDefinition($name)
|
||||
public static function getFormatDefinition(string $name): ?string
|
||||
{
|
||||
if (!self::$formats) {
|
||||
self::$formats = self::initFormats();
|
||||
}
|
||||
|
||||
return isset(self::$formats[$name]) ? 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();
|
||||
}
|
||||
self::$formatters ??= self::initPlaceholderFormatters();
|
||||
|
||||
self::$formatters[$name] = $callable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the placeholder formatter for a given name.
|
||||
*
|
||||
* @param string $name The placeholder name (including the delimiter char like %)
|
||||
*
|
||||
* @return callable|null A PHP callable
|
||||
* Gets the placeholder formatter for a given name (including the delimiter char like %).
|
||||
*/
|
||||
public static function getPlaceholderFormatterDefinition($name)
|
||||
public static function getPlaceholderFormatterDefinition(string $name): ?callable
|
||||
{
|
||||
if (!self::$formatters) {
|
||||
self::$formatters = self::initPlaceholderFormatters();
|
||||
}
|
||||
self::$formatters ??= self::initPlaceholderFormatters();
|
||||
|
||||
return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
|
||||
return self::$formatters[$name] ?? null;
|
||||
}
|
||||
|
||||
private function display()
|
||||
@@ -192,18 +180,16 @@ class ProgressIndicator
|
||||
return;
|
||||
}
|
||||
|
||||
$self = $this;
|
||||
|
||||
$this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
|
||||
if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
|
||||
return call_user_func($formatter, $self);
|
||||
$this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) {
|
||||
if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) {
|
||||
return $formatter($this);
|
||||
}
|
||||
|
||||
return $matches[0];
|
||||
}, $this->format));
|
||||
}, $this->format ?? ''));
|
||||
}
|
||||
|
||||
private function determineBestFormat()
|
||||
private function determineBestFormat(): string
|
||||
{
|
||||
switch ($this->output->getVerbosity()) {
|
||||
// OutputInterface::VERBOSITY_QUIET: display is disabled anyway
|
||||
@@ -219,10 +205,8 @@ class ProgressIndicator
|
||||
|
||||
/**
|
||||
* Overwrites a previous message to the output.
|
||||
*
|
||||
* @param string $message The message
|
||||
*/
|
||||
private function overwrite($message)
|
||||
private function overwrite(string $message)
|
||||
{
|
||||
if ($this->output->isDecorated()) {
|
||||
$this->output->write("\x0D\x1B[2K");
|
||||
@@ -232,40 +216,29 @@ class ProgressIndicator
|
||||
}
|
||||
}
|
||||
|
||||
private function getCurrentTimeInMilliseconds()
|
||||
private function getCurrentTimeInMilliseconds(): float
|
||||
{
|
||||
return round(microtime(true) * 1000);
|
||||
}
|
||||
|
||||
private static function initPlaceholderFormatters()
|
||||
/**
|
||||
* @return array<string, \Closure>
|
||||
*/
|
||||
private static function initPlaceholderFormatters(): array
|
||||
{
|
||||
return array(
|
||||
'indicator' => function (ProgressIndicator $indicator) {
|
||||
return $indicator->indicatorValues[$indicator->indicatorCurrent % count($indicator->indicatorValues)];
|
||||
return [
|
||||
'indicator' => function (self $indicator) {
|
||||
return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)];
|
||||
},
|
||||
'message' => function (ProgressIndicator $indicator) {
|
||||
'message' => function (self $indicator) {
|
||||
return $indicator->message;
|
||||
},
|
||||
'elapsed' => function (ProgressIndicator $indicator) {
|
||||
'elapsed' => function (self $indicator) {
|
||||
return Helper::formatTime(time() - $indicator->startTime);
|
||||
},
|
||||
'memory' => function () {
|
||||
return Helper::formatMemory(memory_get_usage(true));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private static function initFormats()
|
||||
{
|
||||
return array(
|
||||
'normal' => ' %indicator% %message%',
|
||||
'normal_no_ansi' => ' %message%',
|
||||
|
||||
'verbose' => ' %indicator% %message% (%elapsed:6s%)',
|
||||
'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
|
||||
|
||||
'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
|
||||
'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
489
vendor/symfony/console/Helper/QuestionHelper.php
vendored
489
vendor/symfony/console/Helper/QuestionHelper.php
vendored
@@ -11,15 +11,21 @@
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Cursor;
|
||||
use Symfony\Component\Console\Exception\MissingInputException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
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\Formatter\OutputFormatterStyle;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
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.
|
||||
@@ -28,90 +34,60 @@ use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
*/
|
||||
class QuestionHelper extends Helper
|
||||
{
|
||||
/**
|
||||
* @var resource|null
|
||||
*/
|
||||
private $inputStream;
|
||||
private static $shell;
|
||||
private static $stty;
|
||||
|
||||
private static bool $stty = true;
|
||||
private static bool $stdinIsInteractive;
|
||||
|
||||
/**
|
||||
* Asks a question to the user.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @param Question $question The question to ask
|
||||
*
|
||||
* @return mixed The user answer
|
||||
*
|
||||
* @throws RuntimeException If there is no data to read in the input stream
|
||||
*/
|
||||
public function ask(InputInterface $input, OutputInterface $output, Question $question)
|
||||
public function ask(InputInterface $input, OutputInterface $output, Question $question): mixed
|
||||
{
|
||||
if ($output instanceof ConsoleOutputInterface) {
|
||||
$output = $output->getErrorOutput();
|
||||
}
|
||||
|
||||
if (!$input->isInteractive()) {
|
||||
return $question->getDefault();
|
||||
return $this->getDefaultAnswer($question);
|
||||
}
|
||||
|
||||
if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) {
|
||||
$this->inputStream = $stream;
|
||||
}
|
||||
|
||||
if (!$question->getValidator()) {
|
||||
return $this->doAsk($output, $question);
|
||||
try {
|
||||
if (!$question->getValidator()) {
|
||||
return $this->doAsk($output, $question);
|
||||
}
|
||||
|
||||
$interviewer = function () use ($output, $question) {
|
||||
return $this->doAsk($output, $question);
|
||||
};
|
||||
|
||||
return $this->validateAttempts($interviewer, $output, $question);
|
||||
} catch (MissingInputException $exception) {
|
||||
$input->setInteractive(false);
|
||||
|
||||
if (null === $fallbackOutput = $this->getDefaultAnswer($question)) {
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return $fallbackOutput;
|
||||
}
|
||||
|
||||
$interviewer = function () use ($output, $question) {
|
||||
return $this->doAsk($output, $question);
|
||||
};
|
||||
|
||||
return $this->validateAttempts($interviewer, $output, $question);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the input stream to read from when interacting with the user.
|
||||
*
|
||||
* This is mainly useful for testing purpose.
|
||||
*
|
||||
* @deprecated since version 3.2, to be removed in 4.0. Use
|
||||
* StreamableInputInterface::setStream() instead.
|
||||
*
|
||||
* @param resource $stream The input stream
|
||||
*
|
||||
* @throws InvalidArgumentException In case the stream is not a resource
|
||||
*/
|
||||
public function setInputStream($stream)
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s::setStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED);
|
||||
|
||||
if (!is_resource($stream)) {
|
||||
throw new InvalidArgumentException('Input stream must be a valid resource.');
|
||||
}
|
||||
|
||||
$this->inputStream = $stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the helper's input stream.
|
||||
*
|
||||
* @deprecated since version 3.2, to be removed in 4.0. Use
|
||||
* StreamableInputInterface::getStream() instead.
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
public function getInputStream()
|
||||
{
|
||||
if (0 === func_num_args() || func_get_arg(0)) {
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s::getStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
return $this->inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'question';
|
||||
}
|
||||
@@ -127,25 +103,21 @@ class QuestionHelper extends Helper
|
||||
/**
|
||||
* Asks the question to the user.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param Question $question
|
||||
*
|
||||
* @return bool|mixed|null|string
|
||||
*
|
||||
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
|
||||
*/
|
||||
private function doAsk(OutputInterface $output, Question $question)
|
||||
private function doAsk(OutputInterface $output, Question $question): mixed
|
||||
{
|
||||
$this->writePrompt($output, $question);
|
||||
|
||||
$inputStream = $this->inputStream ?: STDIN;
|
||||
$autocomplete = $question->getAutocompleterValues();
|
||||
$inputStream = $this->inputStream ?: \STDIN;
|
||||
$autocomplete = $question->getAutocompleterCallback();
|
||||
|
||||
if (null === $autocomplete || !$this->hasSttyAvailable()) {
|
||||
if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) {
|
||||
$ret = false;
|
||||
if ($question->isHidden()) {
|
||||
try {
|
||||
$ret = trim($this->getHiddenResponse($output, $inputStream));
|
||||
$hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable());
|
||||
$ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse;
|
||||
} catch (RuntimeException $e) {
|
||||
if (!$question->isHiddenFallback()) {
|
||||
throw $e;
|
||||
@@ -154,17 +126,24 @@ class QuestionHelper extends Helper
|
||||
}
|
||||
|
||||
if (false === $ret) {
|
||||
$ret = fgets($inputStream, 4096);
|
||||
$ret = $this->readInput($inputStream, $question);
|
||||
if (false === $ret) {
|
||||
throw new RuntimeException('Aborted');
|
||||
throw new MissingInputException('Aborted.');
|
||||
}
|
||||
if ($question->isTrimmable()) {
|
||||
$ret = trim($ret);
|
||||
}
|
||||
$ret = trim($ret);
|
||||
}
|
||||
} else {
|
||||
$ret = trim($this->autocomplete($output, $question, $inputStream));
|
||||
$autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete);
|
||||
$ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete;
|
||||
}
|
||||
|
||||
$ret = strlen($ret) > 0 ? $ret : $question->getDefault();
|
||||
if ($output instanceof ConsoleSectionOutput) {
|
||||
$output->addContent($ret);
|
||||
}
|
||||
|
||||
$ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
|
||||
|
||||
if ($normalizer = $question->getNormalizer()) {
|
||||
return $normalizer($ret);
|
||||
@@ -173,26 +152,44 @@ class QuestionHelper extends Helper
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private function getDefaultAnswer(Question $question): mixed
|
||||
{
|
||||
$default = $question->getDefault();
|
||||
|
||||
if (null === $default) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ($validator = $question->getValidator()) {
|
||||
return \call_user_func($question->getValidator(), $default);
|
||||
} elseif ($question instanceof ChoiceQuestion) {
|
||||
$choices = $question->getChoices();
|
||||
|
||||
if (!$question->isMultiselect()) {
|
||||
return $choices[$default] ?? $default;
|
||||
}
|
||||
|
||||
$default = explode(',', $default);
|
||||
foreach ($default as $k => $v) {
|
||||
$v = $question->isTrimmable() ? trim($v) : $v;
|
||||
$default[$k] = $choices[$v] ?? $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the question prompt.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param Question $question
|
||||
*/
|
||||
protected function writePrompt(OutputInterface $output, Question $question)
|
||||
{
|
||||
$message = $question->getQuestion();
|
||||
|
||||
if ($question instanceof ChoiceQuestion) {
|
||||
$maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
|
||||
|
||||
$messages = (array) $question->getQuestion();
|
||||
foreach ($question->getChoices() as $key => $value) {
|
||||
$width = $maxWidth - $this->strlen($key);
|
||||
$messages[] = ' [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
|
||||
}
|
||||
|
||||
$output->writeln($messages);
|
||||
$output->writeln(array_merge([
|
||||
$question->getQuestion(),
|
||||
], $this->formatChoiceQuestionChoices($question, 'info')));
|
||||
|
||||
$message = $question->getPrompt();
|
||||
}
|
||||
@@ -200,11 +197,26 @@ class QuestionHelper extends Helper
|
||||
$output->write($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag): array
|
||||
{
|
||||
$messages = [];
|
||||
|
||||
$maxWidth = max(array_map([__CLASS__, 'width'], array_keys($choices = $question->getChoices())));
|
||||
|
||||
foreach ($choices as $key => $value) {
|
||||
$padding = str_repeat(' ', $maxWidth - self::width($key));
|
||||
|
||||
$messages[] = sprintf(" [<$tag>%s$padding</$tag>] %s", $key, $value);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs an error message.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param \Exception $error
|
||||
*/
|
||||
protected function writeError(OutputInterface $output, \Exception $error)
|
||||
{
|
||||
@@ -220,23 +232,24 @@ class QuestionHelper extends Helper
|
||||
/**
|
||||
* Autocompletes a question.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param Question $question
|
||||
* @param resource $inputStream
|
||||
*
|
||||
* @return string
|
||||
* @param resource $inputStream
|
||||
*/
|
||||
private function autocomplete(OutputInterface $output, Question $question, $inputStream)
|
||||
private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string
|
||||
{
|
||||
$autocomplete = $question->getAutocompleterValues();
|
||||
$cursor = new Cursor($output, $inputStream);
|
||||
|
||||
$fullChoice = '';
|
||||
$ret = '';
|
||||
|
||||
$i = 0;
|
||||
$ofs = -1;
|
||||
$matches = $autocomplete;
|
||||
$numMatches = count($matches);
|
||||
$matches = $autocomplete($ret);
|
||||
$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');
|
||||
@@ -246,26 +259,34 @@ 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);
|
||||
|
||||
// Backspace Character
|
||||
if ("\177" === $c) {
|
||||
// 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('stty '.$sttyMode);
|
||||
throw new MissingInputException('Aborted.');
|
||||
} elseif ("\177" === $c) { // Backspace Character
|
||||
if (0 === $numMatches && 0 !== $i) {
|
||||
--$i;
|
||||
// Move cursor backwards
|
||||
$output->write("\033[1D");
|
||||
$cursor->moveLeft(s($fullChoice)->slice(-1)->width(false));
|
||||
|
||||
$fullChoice = self::substr($fullChoice, 0, $i);
|
||||
}
|
||||
|
||||
if ($i === 0) {
|
||||
if (0 === $i) {
|
||||
$ofs = -1;
|
||||
$matches = $autocomplete;
|
||||
$numMatches = count($matches);
|
||||
$matches = $autocomplete($ret);
|
||||
$numMatches = \count($matches);
|
||||
} else {
|
||||
$numMatches = 0;
|
||||
}
|
||||
|
||||
// Pop the last character off the end of our string
|
||||
$ret = substr($ret, 0, $i);
|
||||
$ret = self::substr($ret, 0, $i);
|
||||
} elseif ("\033" === $c) {
|
||||
// Did we read an escape sequence?
|
||||
$c .= fread($inputStream, 2);
|
||||
@@ -283,13 +304,24 @@ class QuestionHelper extends Helper
|
||||
$ofs += ('A' === $c[2]) ? -1 : 1;
|
||||
$ofs = ($numMatches + $ofs) % $numMatches;
|
||||
}
|
||||
} elseif (ord($c) < 32) {
|
||||
} elseif (\ord($c) < 32) {
|
||||
if ("\t" === $c || "\n" === $c) {
|
||||
if ($numMatches > 0 && -1 !== $ofs) {
|
||||
$ret = $matches[$ofs];
|
||||
$ret = (string) $matches[$ofs];
|
||||
// Echo out remaining chars for current match
|
||||
$output->write(substr($ret, $i));
|
||||
$i = strlen($ret);
|
||||
$remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))));
|
||||
$output->write($remainingCharacters);
|
||||
$fullChoice .= $remainingCharacters;
|
||||
$i = (false === $encoding = mb_detect_encoding($fullChoice, null, true)) ? \strlen($fullChoice) : mb_strlen($fullChoice, $encoding);
|
||||
|
||||
$matches = array_filter(
|
||||
$autocomplete($ret),
|
||||
function ($match) use ($ret) {
|
||||
return '' === $ret || str_starts_with($match, $ret);
|
||||
}
|
||||
);
|
||||
$numMatches = \count($matches);
|
||||
$ofs = -1;
|
||||
}
|
||||
|
||||
if ("\n" === $c) {
|
||||
@@ -302,53 +334,75 @@ class QuestionHelper extends Helper
|
||||
|
||||
continue;
|
||||
} else {
|
||||
if ("\x80" <= $c) {
|
||||
$c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]);
|
||||
}
|
||||
|
||||
$output->write($c);
|
||||
$ret .= $c;
|
||||
$fullChoice .= $c;
|
||||
++$i;
|
||||
|
||||
$tempRet = $ret;
|
||||
|
||||
if ($question instanceof ChoiceQuestion && $question->isMultiselect()) {
|
||||
$tempRet = $this->mostRecentlyEnteredValue($fullChoice);
|
||||
}
|
||||
|
||||
$numMatches = 0;
|
||||
$ofs = 0;
|
||||
|
||||
foreach ($autocomplete as $value) {
|
||||
foreach ($autocomplete($ret) as $value) {
|
||||
// If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
|
||||
if (0 === strpos($value, $ret) && $i !== strlen($value)) {
|
||||
if (str_starts_with($value, $tempRet)) {
|
||||
$matches[$numMatches++] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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");
|
||||
// Write highlighted text
|
||||
$output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
|
||||
// Restore cursor position
|
||||
$output->write("\0338");
|
||||
$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>');
|
||||
$cursor->restorePosition();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset stty so it behaves normally again
|
||||
shell_exec(sprintf('stty %s', $sttyMode));
|
||||
shell_exec('stty '.$sttyMode);
|
||||
|
||||
return $ret;
|
||||
return $fullChoice;
|
||||
}
|
||||
|
||||
private function mostRecentlyEnteredValue(string $entered): string
|
||||
{
|
||||
// Determine the most recent value that the user entered
|
||||
if (!str_contains($entered, ',')) {
|
||||
return $entered;
|
||||
}
|
||||
|
||||
$choices = explode(',', $entered);
|
||||
if ('' !== $lastChoice = trim($choices[\count($choices) - 1])) {
|
||||
return $lastChoice;
|
||||
}
|
||||
|
||||
return $entered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a hidden response from user.
|
||||
*
|
||||
* @param OutputInterface $output An Output instance
|
||||
* @param resource $inputStream The handler resource
|
||||
*
|
||||
* @return string The answer
|
||||
* @param resource $inputStream The handler resource
|
||||
* @param bool $trimmable Is the answer trimmable
|
||||
*
|
||||
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
|
||||
*/
|
||||
private function getHiddenResponse(OutputInterface $output, $inputStream)
|
||||
private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = true): string
|
||||
{
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||
$exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
|
||||
|
||||
// handle code running from a phar
|
||||
@@ -358,7 +412,8 @@ class QuestionHelper extends Helper
|
||||
$exe = $tmpExe;
|
||||
}
|
||||
|
||||
$value = rtrim(shell_exec($exe));
|
||||
$sExec = shell_exec('"'.$exe.'"');
|
||||
$value = $trimmable ? rtrim($sExec) : $sExec;
|
||||
$output->writeln('');
|
||||
|
||||
if (isset($tmpExe)) {
|
||||
@@ -368,57 +423,49 @@ class QuestionHelper extends Helper
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ($this->hasSttyAvailable()) {
|
||||
if (self::$stty && Terminal::hasSttyAvailable()) {
|
||||
$sttyMode = shell_exec('stty -g');
|
||||
|
||||
shell_exec('stty -echo');
|
||||
$value = fgets($inputStream, 4096);
|
||||
shell_exec(sprintf('stty %s', $sttyMode));
|
||||
} elseif ($this->isInteractiveInput($inputStream)) {
|
||||
throw new RuntimeException('Unable to hide the response.');
|
||||
}
|
||||
|
||||
if (false === $value) {
|
||||
throw new RuntimeException('Aborted');
|
||||
}
|
||||
$value = fgets($inputStream, 4096);
|
||||
|
||||
if (self::$stty && Terminal::hasSttyAvailable()) {
|
||||
shell_exec('stty '.$sttyMode);
|
||||
}
|
||||
|
||||
if (false === $value) {
|
||||
throw new MissingInputException('Aborted.');
|
||||
}
|
||||
if ($trimmable) {
|
||||
$value = trim($value);
|
||||
$output->writeln('');
|
||||
|
||||
return $value;
|
||||
}
|
||||
$output->writeln('');
|
||||
|
||||
if (false !== $shell = $this->getShell()) {
|
||||
$readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
|
||||
$command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
|
||||
$value = rtrim(shell_exec($command));
|
||||
$output->writeln('');
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
throw new RuntimeException('Unable to hide the response.');
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an attempt.
|
||||
*
|
||||
* @param callable $interviewer A callable that will ask for a question and return the result
|
||||
* @param OutputInterface $output An Output instance
|
||||
* @param Question $question A Question instance
|
||||
*
|
||||
* @return mixed The validated response
|
||||
* @param callable $interviewer A callable that will ask for a question and return the result
|
||||
*
|
||||
* @throws \Exception In case the max number of attempts has been reached and no valid response has been given
|
||||
*/
|
||||
private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question)
|
||||
private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question): mixed
|
||||
{
|
||||
$error = null;
|
||||
$attempts = $question->getMaxAttempts();
|
||||
|
||||
while (null === $attempts || $attempts--) {
|
||||
if (null !== $error) {
|
||||
$this->writeError($output, $error);
|
||||
}
|
||||
|
||||
try {
|
||||
return call_user_func($question->getValidator(), $interviewer());
|
||||
return $question->getValidator()($interviewer());
|
||||
} catch (RuntimeException $e) {
|
||||
throw $e;
|
||||
} catch (\Exception $error) {
|
||||
@@ -428,46 +475,124 @@ class QuestionHelper extends Helper
|
||||
throw $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a valid unix shell.
|
||||
*
|
||||
* @return string|bool The valid shell name, false in case no valid shell is found
|
||||
*/
|
||||
private function getShell()
|
||||
private function isInteractiveInput($inputStream): bool
|
||||
{
|
||||
if (null !== self::$shell) {
|
||||
return self::$shell;
|
||||
if ('php://stdin' !== (stream_get_meta_data($inputStream)['uri'] ?? null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$shell = false;
|
||||
if (isset(self::$stdinIsInteractive)) {
|
||||
return self::$stdinIsInteractive;
|
||||
}
|
||||
|
||||
if (file_exists('/usr/bin/env')) {
|
||||
// handle other OSs with bash/zsh/ksh/csh if available to hide the answer
|
||||
$test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
|
||||
foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
|
||||
if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
|
||||
self::$shell = $sh;
|
||||
break;
|
||||
}
|
||||
if (\function_exists('stream_isatty')) {
|
||||
return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r'));
|
||||
}
|
||||
|
||||
if (\function_exists('posix_isatty')) {
|
||||
return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r'));
|
||||
}
|
||||
|
||||
if (!\function_exists('exec')) {
|
||||
return self::$stdinIsInteractive = true;
|
||||
}
|
||||
|
||||
exec('stty 2> /dev/null', $output, $status);
|
||||
|
||||
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
|
||||
*/
|
||||
private function readInput($inputStream, Question $question): string|false
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
private function setIOCodepage(): int
|
||||
{
|
||||
if (\function_exists('sapi_windows_cp_set')) {
|
||||
$cp = sapi_windows_cp_get();
|
||||
sapi_windows_cp_set(sapi_windows_cp_get('oem'));
|
||||
|
||||
return $cp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets console I/O to the specified code page and converts the user input.
|
||||
*/
|
||||
private function resetIOCodepage(int $cp, string|false $input): string|false
|
||||
{
|
||||
if (0 !== $cp) {
|
||||
sapi_windows_cp_set($cp);
|
||||
|
||||
if (false !== $input && '' !== $input) {
|
||||
$input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input);
|
||||
}
|
||||
}
|
||||
|
||||
return self::$shell;
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Stty is available or not.
|
||||
* Clones an input stream in order to act on one instance of the same
|
||||
* stream without affecting the other instance.
|
||||
*
|
||||
* @return bool
|
||||
* @param resource $inputStream The handler resource
|
||||
*
|
||||
* @return resource|null The cloned resource, null in case it could not be cloned
|
||||
*/
|
||||
private function hasSttyAvailable()
|
||||
private function cloneInputStream($inputStream)
|
||||
{
|
||||
if (null !== self::$stty) {
|
||||
return self::$stty;
|
||||
$streamMetaData = stream_get_meta_data($inputStream);
|
||||
$seekable = $streamMetaData['seekable'] ?? false;
|
||||
$mode = $streamMetaData['mode'] ?? 'rb';
|
||||
$uri = $streamMetaData['uri'] ?? null;
|
||||
|
||||
if (null === $uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
exec('stty 2>&1', $output, $exitcode);
|
||||
$cloneStream = fopen($uri, $mode);
|
||||
|
||||
return self::$stty = $exitcode === 0;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Exception\LogicException;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
|
||||
/**
|
||||
* Symfony Style Guide compliant question helper.
|
||||
@@ -27,28 +25,6 @@ use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
*/
|
||||
class SymfonyQuestionHelper extends QuestionHelper
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function ask(InputInterface $input, OutputInterface $output, Question $question)
|
||||
{
|
||||
$validator = $question->getValidator();
|
||||
$question->setValidator(function ($value) use ($validator) {
|
||||
if (null !== $validator) {
|
||||
$value = $validator($value);
|
||||
} else {
|
||||
// make required
|
||||
if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
|
||||
throw new LogicException('A value is required.');
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
});
|
||||
|
||||
return parent::ask($input, $output, $question);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -57,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);
|
||||
@@ -82,7 +62,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($choices[$default] ?? $default));
|
||||
|
||||
break;
|
||||
|
||||
@@ -92,15 +72,15 @@ class SymfonyQuestionHelper extends QuestionHelper
|
||||
|
||||
$output->writeln($text);
|
||||
|
||||
if ($question instanceof ChoiceQuestion) {
|
||||
$width = max(array_map('strlen', array_keys($question->getChoices())));
|
||||
$prompt = ' > ';
|
||||
|
||||
foreach ($question->getChoices() as $key => $value) {
|
||||
$output->writeln(sprintf(" [<comment>%-${width}s</comment>] %s", $key, $value));
|
||||
}
|
||||
if ($question instanceof ChoiceQuestion) {
|
||||
$output->writeln($this->formatChoiceQuestionChoices($question, 'comment'));
|
||||
|
||||
$prompt = $question->getPrompt();
|
||||
}
|
||||
|
||||
$output->write(' > ');
|
||||
$output->write($prompt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,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>';
|
||||
}
|
||||
}
|
||||
|
||||
712
vendor/symfony/console/Helper/Table.php
vendored
712
vendor/symfony/console/Helper/Table.php
vendored
File diff suppressed because it is too large
Load Diff
45
vendor/symfony/console/Helper/TableCell.php
vendored
45
vendor/symfony/console/Helper/TableCell.php
vendored
@@ -18,29 +18,15 @@ use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
*/
|
||||
class TableCell
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $options = array(
|
||||
private string $value;
|
||||
private array $options = [
|
||||
'rowspan' => 1,
|
||||
'colspan' => 1,
|
||||
);
|
||||
'style' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($value = '', array $options = array())
|
||||
public function __construct(string $value = '', array $options = [])
|
||||
{
|
||||
if (is_numeric($value) && !is_string($value)) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
|
||||
// check option names
|
||||
@@ -48,36 +34,39 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cell value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets number of colspan.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getColspan()
|
||||
public function getColspan(): int
|
||||
{
|
||||
return (int) $this->options['colspan'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets number of rowspan.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRowspan()
|
||||
public function getRowspan(): int
|
||||
{
|
||||
return (int) $this->options['rowspan'];
|
||||
}
|
||||
|
||||
public function getStyle(): ?TableCellStyle
|
||||
{
|
||||
return $this->options['style'];
|
||||
}
|
||||
}
|
||||
|
||||
86
vendor/symfony/console/Helper/TableCellStyle.php
vendored
Normal file
86
vendor/symfony/console/Helper/TableCellStyle.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?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 array $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(): array
|
||||
{
|
||||
return array_filter(
|
||||
$this->getOptions(),
|
||||
function ($key) {
|
||||
return \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]);
|
||||
},
|
||||
\ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
}
|
||||
|
||||
public function getPadByAlign(): int
|
||||
{
|
||||
return self::ALIGN_MAP[$this->getOptions()['align']];
|
||||
}
|
||||
|
||||
public function getCellFormat(): ?string
|
||||
{
|
||||
return $this->getOptions()['cellFormat'];
|
||||
}
|
||||
}
|
||||
30
vendor/symfony/console/Helper/TableRows.php
vendored
Normal file
30
vendor/symfony/console/Helper/TableRows.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class TableRows implements \IteratorAggregate
|
||||
{
|
||||
private \Closure $generator;
|
||||
|
||||
public function __construct(\Closure $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
public function getIterator(): \Traversable
|
||||
{
|
||||
return ($this->generator)();
|
||||
}
|
||||
}
|
||||
@@ -18,10 +18,7 @@ namespace Symfony\Component\Console\Helper;
|
||||
*/
|
||||
class TableSeparator extends TableCell
|
||||
{
|
||||
/**
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
parent::__construct('', $options);
|
||||
}
|
||||
|
||||
256
vendor/symfony/console/Helper/TableStyle.php
vendored
256
vendor/symfony/console/Helper/TableStyle.php
vendored
@@ -19,30 +19,44 @@ use Symfony\Component\Console\Exception\LogicException;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Саша Стаменковић <umpirsky@gmail.com>
|
||||
* @author Dany Maillard <danymaillard93b@gmail.com>
|
||||
*/
|
||||
class TableStyle
|
||||
{
|
||||
private $paddingChar = ' ';
|
||||
private $horizontalBorderChar = '-';
|
||||
private $verticalBorderChar = '|';
|
||||
private $crossingChar = '+';
|
||||
private $cellHeaderFormat = '<info>%s</info>';
|
||||
private $cellRowFormat = '%s';
|
||||
private $cellRowContentFormat = ' %s ';
|
||||
private $borderFormat = '%s';
|
||||
private $padType = STR_PAD_RIGHT;
|
||||
private string $paddingChar = ' ';
|
||||
private string $horizontalOutsideBorderChar = '-';
|
||||
private string $horizontalInsideBorderChar = '-';
|
||||
private string $verticalOutsideBorderChar = '|';
|
||||
private string $verticalInsideBorderChar = '|';
|
||||
private string $crossingChar = '+';
|
||||
private string $crossingTopRightChar = '+';
|
||||
private string $crossingTopMidChar = '+';
|
||||
private string $crossingTopLeftChar = '+';
|
||||
private string $crossingMidRightChar = '+';
|
||||
private string $crossingBottomRightChar = '+';
|
||||
private string $crossingBottomMidChar = '+';
|
||||
private string $crossingBottomLeftChar = '+';
|
||||
private string $crossingMidLeftChar = '+';
|
||||
private string $crossingTopLeftBottomChar = '+';
|
||||
private string $crossingTopMidBottomChar = '+';
|
||||
private string $crossingTopRightBottomChar = '+';
|
||||
private string $headerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
|
||||
private string $footerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
|
||||
private string $cellHeaderFormat = '<info>%s</info>';
|
||||
private string $cellRowFormat = '%s';
|
||||
private string $cellRowContentFormat = ' %s ';
|
||||
private string $borderFormat = '%s';
|
||||
private int $padType = \STR_PAD_RIGHT;
|
||||
|
||||
/**
|
||||
* Sets padding character, used for cell padding.
|
||||
*
|
||||
* @param string $paddingChar
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPaddingChar($paddingChar)
|
||||
public function setPaddingChar(string $paddingChar): static
|
||||
{
|
||||
if (!$paddingChar) {
|
||||
throw new LogicException('The padding char must not be empty');
|
||||
throw new LogicException('The padding char must not be empty.');
|
||||
}
|
||||
|
||||
$this->paddingChar = $paddingChar;
|
||||
@@ -52,94 +66,172 @@ class TableStyle
|
||||
|
||||
/**
|
||||
* Gets padding character, used for cell padding.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPaddingChar()
|
||||
public function getPaddingChar(): string
|
||||
{
|
||||
return $this->paddingChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets horizontal border character.
|
||||
* Sets horizontal border characters.
|
||||
*
|
||||
* @param string $horizontalBorderChar
|
||||
* <code>
|
||||
* ╔═══════════════╤══════════════════════════╤══════════════════╗
|
||||
* 1 ISBN 2 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 ║
|
||||
* ╚═══════════════╧══════════════════════════╧══════════════════╝
|
||||
* </code>
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHorizontalBorderChar($horizontalBorderChar)
|
||||
public function setHorizontalBorderChars(string $outside, string $inside = null): static
|
||||
{
|
||||
$this->horizontalBorderChar = $horizontalBorderChar;
|
||||
$this->horizontalOutsideBorderChar = $outside;
|
||||
$this->horizontalInsideBorderChar = $inside ?? $outside;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets horizontal border character.
|
||||
* Sets vertical border characters.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHorizontalBorderChar()
|
||||
{
|
||||
return $this->horizontalBorderChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets vertical border character.
|
||||
*
|
||||
* @param string $verticalBorderChar
|
||||
* <code>
|
||||
* ╔═══════════════╤══════════════════════════╤══════════════════╗
|
||||
* ║ ISBN │ Title │ Author ║
|
||||
* ╠═══════1═══════╪══════════════════════════╪══════════════════╣
|
||||
* ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║
|
||||
* ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║
|
||||
* ╟───────2───────┼──────────────────────────┼──────────────────╢
|
||||
* ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║
|
||||
* ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║
|
||||
* ╚═══════════════╧══════════════════════════╧══════════════════╝
|
||||
* </code>
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setVerticalBorderChar($verticalBorderChar)
|
||||
public function setVerticalBorderChars(string $outside, string $inside = null): static
|
||||
{
|
||||
$this->verticalBorderChar = $verticalBorderChar;
|
||||
$this->verticalOutsideBorderChar = $outside;
|
||||
$this->verticalInsideBorderChar = $inside ?? $outside;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets vertical border character.
|
||||
* Gets border characters.
|
||||
*
|
||||
* @return string
|
||||
* @internal
|
||||
*/
|
||||
public function getVerticalBorderChar()
|
||||
public function getBorderChars(): array
|
||||
{
|
||||
return $this->verticalBorderChar;
|
||||
return [
|
||||
$this->horizontalOutsideBorderChar,
|
||||
$this->verticalOutsideBorderChar,
|
||||
$this->horizontalInsideBorderChar,
|
||||
$this->verticalInsideBorderChar,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets crossing character.
|
||||
* Sets crossing characters.
|
||||
*
|
||||
* @param string $crossingChar
|
||||
* Example:
|
||||
* <code>
|
||||
* 1═══════════════2══════════════════════════2══════════════════3
|
||||
* ║ ISBN │ Title │ Author ║
|
||||
* 8'══════════════0'═════════════════════════0'═════════════════4'
|
||||
* ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║
|
||||
* ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║
|
||||
* 8───────────────0──────────────────────────0──────────────────4
|
||||
* ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║
|
||||
* ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║
|
||||
* 7═══════════════6══════════════════════════6══════════════════5
|
||||
* </code>
|
||||
*
|
||||
* @param string $cross Crossing char (see #0 of example)
|
||||
* @param string $topLeft Top left char (see #1 of example)
|
||||
* @param string $topMid Top mid char (see #2 of example)
|
||||
* @param string $topRight Top right char (see #3 of example)
|
||||
* @param string $midRight Mid right char (see #4 of example)
|
||||
* @param string $bottomRight Bottom right char (see #5 of example)
|
||||
* @param string $bottomMid Bottom mid char (see #6 of example)
|
||||
* @param string $bottomLeft Bottom left char (see #7 of example)
|
||||
* @param string $midLeft Mid left char (see #8 of example)
|
||||
* @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 setCrossingChar($crossingChar)
|
||||
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): static
|
||||
{
|
||||
$this->crossingChar = $crossingChar;
|
||||
$this->crossingChar = $cross;
|
||||
$this->crossingTopLeftChar = $topLeft;
|
||||
$this->crossingTopMidChar = $topMid;
|
||||
$this->crossingTopRightChar = $topRight;
|
||||
$this->crossingMidRightChar = $midRight;
|
||||
$this->crossingBottomRightChar = $bottomRight;
|
||||
$this->crossingBottomMidChar = $bottomMid;
|
||||
$this->crossingBottomLeftChar = $bottomLeft;
|
||||
$this->crossingMidLeftChar = $midLeft;
|
||||
$this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft;
|
||||
$this->crossingTopMidBottomChar = $topMidBottom ?? $cross;
|
||||
$this->crossingTopRightBottomChar = $topRightBottom ?? $midRight;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default crossing character used for each cross.
|
||||
*
|
||||
* @see {@link setCrossingChars()} for setting each crossing individually.
|
||||
*/
|
||||
public function setDefaultCrossingChar(string $char): self
|
||||
{
|
||||
return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets crossing character.
|
||||
*
|
||||
* @return string $crossingChar
|
||||
*/
|
||||
public function getCrossingChar()
|
||||
public function getCrossingChar(): string
|
||||
{
|
||||
return $this->crossingChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets header cell format.
|
||||
* Gets crossing characters.
|
||||
*
|
||||
* @param string $cellHeaderFormat
|
||||
* @internal
|
||||
*/
|
||||
public function getCrossingChars(): array
|
||||
{
|
||||
return [
|
||||
$this->crossingChar,
|
||||
$this->crossingTopLeftChar,
|
||||
$this->crossingTopMidChar,
|
||||
$this->crossingTopRightChar,
|
||||
$this->crossingMidRightChar,
|
||||
$this->crossingBottomRightChar,
|
||||
$this->crossingBottomMidChar,
|
||||
$this->crossingBottomLeftChar,
|
||||
$this->crossingMidLeftChar,
|
||||
$this->crossingTopLeftBottomChar,
|
||||
$this->crossingTopMidBottomChar,
|
||||
$this->crossingTopRightBottomChar,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets header cell format.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellHeaderFormat($cellHeaderFormat)
|
||||
public function setCellHeaderFormat(string $cellHeaderFormat): static
|
||||
{
|
||||
$this->cellHeaderFormat = $cellHeaderFormat;
|
||||
|
||||
@@ -148,10 +240,8 @@ class TableStyle
|
||||
|
||||
/**
|
||||
* Gets header cell format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCellHeaderFormat()
|
||||
public function getCellHeaderFormat(): string
|
||||
{
|
||||
return $this->cellHeaderFormat;
|
||||
}
|
||||
@@ -159,11 +249,9 @@ class TableStyle
|
||||
/**
|
||||
* Sets row cell format.
|
||||
*
|
||||
* @param string $cellRowFormat
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellRowFormat($cellRowFormat)
|
||||
public function setCellRowFormat(string $cellRowFormat): static
|
||||
{
|
||||
$this->cellRowFormat = $cellRowFormat;
|
||||
|
||||
@@ -172,10 +260,8 @@ class TableStyle
|
||||
|
||||
/**
|
||||
* Gets row cell format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCellRowFormat()
|
||||
public function getCellRowFormat(): string
|
||||
{
|
||||
return $this->cellRowFormat;
|
||||
}
|
||||
@@ -183,11 +269,9 @@ class TableStyle
|
||||
/**
|
||||
* Sets row cell content format.
|
||||
*
|
||||
* @param string $cellRowContentFormat
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellRowContentFormat($cellRowContentFormat)
|
||||
public function setCellRowContentFormat(string $cellRowContentFormat): static
|
||||
{
|
||||
$this->cellRowContentFormat = $cellRowContentFormat;
|
||||
|
||||
@@ -196,10 +280,8 @@ class TableStyle
|
||||
|
||||
/**
|
||||
* Gets row cell content format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCellRowContentFormat()
|
||||
public function getCellRowContentFormat(): string
|
||||
{
|
||||
return $this->cellRowContentFormat;
|
||||
}
|
||||
@@ -207,11 +289,9 @@ class TableStyle
|
||||
/**
|
||||
* Sets table border format.
|
||||
*
|
||||
* @param string $borderFormat
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBorderFormat($borderFormat)
|
||||
public function setBorderFormat(string $borderFormat): static
|
||||
{
|
||||
$this->borderFormat = $borderFormat;
|
||||
|
||||
@@ -220,10 +300,8 @@ class TableStyle
|
||||
|
||||
/**
|
||||
* Gets table border format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBorderFormat()
|
||||
public function getBorderFormat(): string
|
||||
{
|
||||
return $this->borderFormat;
|
||||
}
|
||||
@@ -231,13 +309,11 @@ class TableStyle
|
||||
/**
|
||||
* Sets cell padding type.
|
||||
*
|
||||
* @param int $padType STR_PAD_*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPadType($padType)
|
||||
public function setPadType(int $padType): static
|
||||
{
|
||||
if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
|
||||
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).');
|
||||
}
|
||||
|
||||
@@ -248,11 +324,39 @@ class TableStyle
|
||||
|
||||
/**
|
||||
* Gets cell padding type.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPadType()
|
||||
public function getPadType(): int
|
||||
{
|
||||
return $this->padType;
|
||||
}
|
||||
|
||||
public function getHeaderTitleFormat(): string
|
||||
{
|
||||
return $this->headerTitleFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeaderTitleFormat(string $format): static
|
||||
{
|
||||
$this->headerTitleFormat = $format;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFooterTitleFormat(): string
|
||||
{
|
||||
return $this->footerTitleFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setFooterTitleFormat(string $format): static
|
||||
{
|
||||
$this->footerTitleFormat = $format;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
185
vendor/symfony/console/Input/ArgvInput.php
vendored
185
vendor/symfony/console/Input/ArgvInput.php
vendored
@@ -40,20 +40,12 @@ use Symfony\Component\Console\Exception\RuntimeException;
|
||||
*/
|
||||
class ArgvInput extends Input
|
||||
{
|
||||
private $tokens;
|
||||
private $parsed;
|
||||
private array $tokens;
|
||||
private array $parsed;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array|null $argv An array of parameters from the CLI (in the argv format)
|
||||
* @param InputDefinition|null $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(array $argv = null, InputDefinition $definition = null)
|
||||
{
|
||||
if (null === $argv) {
|
||||
$argv = $_SERVER['argv'];
|
||||
}
|
||||
$argv = $argv ?? $_SERVER['argv'] ?? [];
|
||||
|
||||
// strip the application name
|
||||
array_shift($argv);
|
||||
@@ -76,30 +68,35 @@ class ArgvInput extends Input
|
||||
$parseOptions = true;
|
||||
$this->parsed = $this->tokens;
|
||||
while (null !== $token = array_shift($this->parsed)) {
|
||||
if ($parseOptions && '' == $token) {
|
||||
$this->parseArgument($token);
|
||||
} elseif ($parseOptions && '--' == $token) {
|
||||
$parseOptions = false;
|
||||
} elseif ($parseOptions && 0 === strpos($token, '--')) {
|
||||
$this->parseLongOption($token);
|
||||
} elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
|
||||
$this->parseShortOption($token);
|
||||
} else {
|
||||
$this->parseArgument($token);
|
||||
}
|
||||
$parseOptions = $this->parseToken($token, $parseOptions);
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseToken(string $token, bool $parseOptions): bool
|
||||
{
|
||||
if ($parseOptions && '' == $token) {
|
||||
$this->parseArgument($token);
|
||||
} elseif ($parseOptions && '--' == $token) {
|
||||
return false;
|
||||
} elseif ($parseOptions && str_starts_with($token, '--')) {
|
||||
$this->parseLongOption($token);
|
||||
} elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
|
||||
$this->parseShortOption($token);
|
||||
} else {
|
||||
$this->parseArgument($token);
|
||||
}
|
||||
|
||||
return $parseOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a short option.
|
||||
*
|
||||
* @param string $token The current token
|
||||
*/
|
||||
private function parseShortOption($token)
|
||||
private function parseShortOption(string $token)
|
||||
{
|
||||
$name = substr($token, 1);
|
||||
|
||||
if (strlen($name) > 1) {
|
||||
if (\strlen($name) > 1) {
|
||||
if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
|
||||
// an option with a value (with no space)
|
||||
$this->addShortOption($name[0], substr($name, 1));
|
||||
@@ -114,16 +111,15 @@ class ArgvInput extends Input
|
||||
/**
|
||||
* Parses a short option set.
|
||||
*
|
||||
* @param string $name The current token
|
||||
*
|
||||
* @throws RuntimeException When option given doesn't exist
|
||||
*/
|
||||
private function parseShortOptionSet($name)
|
||||
private function parseShortOptionSet(string $name)
|
||||
{
|
||||
$len = strlen($name);
|
||||
$len = \strlen($name);
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
if (!$this->definition->hasShortcut($name[$i])) {
|
||||
throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
|
||||
$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]);
|
||||
@@ -139,20 +135,13 @@ class ArgvInput extends Input
|
||||
|
||||
/**
|
||||
* Parses a long option.
|
||||
*
|
||||
* @param string $token The current token
|
||||
*/
|
||||
private function parseLongOption($token)
|
||||
private function parseLongOption(string $token)
|
||||
{
|
||||
$name = substr($token, 2);
|
||||
|
||||
if (false !== $pos = strpos($name, '=')) {
|
||||
if (0 === strlen($value = substr($name, $pos + 1))) {
|
||||
// if no value after "=" then substr() returns "" since php7 only, false before
|
||||
// see http://php.net/manual/fr/migration70.incompatible.php#119151
|
||||
if (\PHP_VERSION_ID < 70000 && false === $value) {
|
||||
$value = '';
|
||||
}
|
||||
if ('' === $value = substr($name, $pos + 1)) {
|
||||
array_unshift($this->parsed, $value);
|
||||
}
|
||||
$this->addLongOption(substr($name, 0, $pos), $value);
|
||||
@@ -164,18 +153,16 @@ class ArgvInput extends Input
|
||||
/**
|
||||
* Parses an argument.
|
||||
*
|
||||
* @param string $token The current token
|
||||
*
|
||||
* @throws RuntimeException When too many arguments are given
|
||||
*/
|
||||
private function parseArgument($token)
|
||||
private function parseArgument(string $token)
|
||||
{
|
||||
$c = count($this->arguments);
|
||||
$c = \count($this->arguments);
|
||||
|
||||
// if input is expecting another argument, add it
|
||||
if ($this->definition->hasArgument($c)) {
|
||||
$arg = $this->definition->getArgument($c);
|
||||
$this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
|
||||
$this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token;
|
||||
|
||||
// if last argument isArray(), append token to last argument
|
||||
} elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
|
||||
@@ -185,23 +172,34 @@ class ArgvInput extends Input
|
||||
// unexpected argument
|
||||
} else {
|
||||
$all = $this->definition->getArguments();
|
||||
if (count($all)) {
|
||||
throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
|
||||
$symfonyCommandName = null;
|
||||
if (($inputArgument = $all[$key = array_key_first($all)] ?? null) && 'command' === $inputArgument->getName()) {
|
||||
$symfonyCommandName = $this->arguments['command'] ?? null;
|
||||
unset($all[$key]);
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
|
||||
if (\count($all)) {
|
||||
if ($symfonyCommandName) {
|
||||
$message = sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all)));
|
||||
} else {
|
||||
$message = sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)));
|
||||
}
|
||||
} elseif ($symfonyCommandName) {
|
||||
$message = sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token);
|
||||
} else {
|
||||
$message = sprintf('No arguments expected, got "%s".', $token);
|
||||
}
|
||||
|
||||
throw new RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a short option value.
|
||||
*
|
||||
* @param string $shortcut The short option key
|
||||
* @param mixed $value The value for the option
|
||||
*
|
||||
* @throws RuntimeException When option given doesn't exist
|
||||
*/
|
||||
private function addShortOption($shortcut, $value)
|
||||
private function addShortOption(string $shortcut, mixed $value)
|
||||
{
|
||||
if (!$this->definition->hasShortcut($shortcut)) {
|
||||
throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
|
||||
@@ -213,15 +211,22 @@ class ArgvInput extends Input
|
||||
/**
|
||||
* Adds a long option value.
|
||||
*
|
||||
* @param string $name The long option key
|
||||
* @param mixed $value The value for the option
|
||||
*
|
||||
* @throws RuntimeException When option given doesn't exist
|
||||
*/
|
||||
private function addLongOption($name, $value)
|
||||
private function addLongOption(string $name, mixed $value)
|
||||
{
|
||||
if (!$this->definition->hasOption($name)) {
|
||||
throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
|
||||
if (!$this->definition->hasNegation($name)) {
|
||||
throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
$optionName = $this->definition->negationToName($name);
|
||||
if (null !== $value) {
|
||||
throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
|
||||
}
|
||||
$this->options[$optionName] = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$option = $this->definition->getOption($name);
|
||||
@@ -230,11 +235,11 @@ class ArgvInput extends Input
|
||||
throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
|
||||
}
|
||||
|
||||
if (in_array($value, array('', null), true) && $option->acceptValue() && count($this->parsed)) {
|
||||
if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) {
|
||||
// if option accepts an optional or mandatory argument
|
||||
// let's see if there is one provided
|
||||
$next = array_shift($this->parsed);
|
||||
if ((isset($next[0]) && '-' !== $next[0]) || in_array($next, array('', null), true)) {
|
||||
if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, ['', null], true)) {
|
||||
$value = $next;
|
||||
} else {
|
||||
array_unshift($this->parsed, $next);
|
||||
@@ -261,30 +266,55 @@ class ArgvInput extends Input
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFirstArgument()
|
||||
public function getFirstArgument(): ?string
|
||||
{
|
||||
foreach ($this->tokens as $token) {
|
||||
$isOption = false;
|
||||
foreach ($this->tokens as $i => $token) {
|
||||
if ($token && '-' === $token[0]) {
|
||||
if (str_contains($token, '=') || !isset($this->tokens[$i + 1])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it's a long option, consider that everything after "--" is the option name.
|
||||
// Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator)
|
||||
$name = '-' === $token[1] ? substr($token, 2) : substr($token, -1);
|
||||
if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) {
|
||||
// noop
|
||||
} elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) {
|
||||
$isOption = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($isOption) {
|
||||
$isOption = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasParameterOption($values, $onlyParams = false)
|
||||
public function hasParameterOption(string|array $values, bool $onlyParams = false): bool
|
||||
{
|
||||
$values = (array) $values;
|
||||
|
||||
foreach ($this->tokens as $token) {
|
||||
if ($onlyParams && $token === '--') {
|
||||
if ($onlyParams && '--' === $token) {
|
||||
return false;
|
||||
}
|
||||
foreach ($values as $value) {
|
||||
if ($token === $value || 0 === strpos($token, $value.'=')) {
|
||||
// Options with values:
|
||||
// For long options, test for '--option=' at beginning
|
||||
// For short options, test for '-o' at beginning
|
||||
$leading = str_starts_with($value, '--') ? $value.'=' : $value;
|
||||
if ($token === $value || '' !== $leading && str_starts_with($token, $leading)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -296,25 +326,28 @@ class ArgvInput extends Input
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParameterOption($values, $default = false, $onlyParams = false)
|
||||
public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false): mixed
|
||||
{
|
||||
$values = (array) $values;
|
||||
$tokens = $this->tokens;
|
||||
|
||||
while (0 < count($tokens)) {
|
||||
while (0 < \count($tokens)) {
|
||||
$token = array_shift($tokens);
|
||||
if ($onlyParams && $token === '--') {
|
||||
return false;
|
||||
if ($onlyParams && '--' === $token) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
foreach ($values as $value) {
|
||||
if ($token === $value || 0 === strpos($token, $value.'=')) {
|
||||
if (false !== $pos = strpos($token, '=')) {
|
||||
return substr($token, $pos + 1);
|
||||
}
|
||||
|
||||
if ($token === $value) {
|
||||
return array_shift($tokens);
|
||||
}
|
||||
// Options with values:
|
||||
// For long options, test for '--option=' at beginning
|
||||
// For short options, test for '-o' at beginning
|
||||
$leading = str_starts_with($value, '--') ? $value.'=' : $value;
|
||||
if ('' !== $leading && str_starts_with($token, $leading)) {
|
||||
return substr($token, \strlen($leading));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,17 +356,15 @@ class ArgvInput extends Input
|
||||
|
||||
/**
|
||||
* Returns a stringified representation of the args passed to the command.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
$tokens = array_map(function ($token) {
|
||||
if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
|
||||
return $match[1].$this->escapeToken($match[2]);
|
||||
}
|
||||
|
||||
if ($token && $token[0] !== '-') {
|
||||
if ($token && '-' !== $token[0]) {
|
||||
return $this->escapeToken($token);
|
||||
}
|
||||
|
||||
|
||||
87
vendor/symfony/console/Input/ArrayInput.php
vendored
87
vendor/symfony/console/Input/ArrayInput.php
vendored
@@ -19,20 +19,14 @@ use Symfony\Component\Console\Exception\InvalidOptionException;
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
|
||||
* $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']);
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class ArrayInput extends Input
|
||||
{
|
||||
private $parameters;
|
||||
private array $parameters;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $parameters An array of parameters
|
||||
* @param InputDefinition|null $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(array $parameters, InputDefinition $definition = null)
|
||||
{
|
||||
$this->parameters = $parameters;
|
||||
@@ -43,34 +37,36 @@ class ArrayInput extends Input
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFirstArgument()
|
||||
public function getFirstArgument(): ?string
|
||||
{
|
||||
foreach ($this->parameters as $key => $value) {
|
||||
if ($key && '-' === $key[0]) {
|
||||
foreach ($this->parameters as $param => $value) {
|
||||
if ($param && \is_string($param) && '-' === $param[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasParameterOption($values, $onlyParams = false)
|
||||
public function hasParameterOption(string|array $values, bool $onlyParams = false): bool
|
||||
{
|
||||
$values = (array) $values;
|
||||
|
||||
foreach ($this->parameters as $k => $v) {
|
||||
if (!is_int($k)) {
|
||||
if (!\is_int($k)) {
|
||||
$v = $k;
|
||||
}
|
||||
|
||||
if ($onlyParams && $v === '--') {
|
||||
if ($onlyParams && '--' === $v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in_array($v, $values)) {
|
||||
if (\in_array($v, $values)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -81,20 +77,20 @@ class ArrayInput extends Input
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParameterOption($values, $default = false, $onlyParams = false)
|
||||
public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false): mixed
|
||||
{
|
||||
$values = (array) $values;
|
||||
|
||||
foreach ($this->parameters as $k => $v) {
|
||||
if ($onlyParams && ($k === '--' || (is_int($k) && $v === '--'))) {
|
||||
return false;
|
||||
if ($onlyParams && ('--' === $k || (\is_int($k) && '--' === $v))) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (is_int($k)) {
|
||||
if (in_array($v, $values)) {
|
||||
if (\is_int($k)) {
|
||||
if (\in_array($v, $values)) {
|
||||
return true;
|
||||
}
|
||||
} elseif (in_array($k, $values)) {
|
||||
} elseif (\in_array($k, $values)) {
|
||||
return $v;
|
||||
}
|
||||
}
|
||||
@@ -104,17 +100,22 @@ class ArrayInput extends Input
|
||||
|
||||
/**
|
||||
* Returns a stringified representation of the args passed to the command.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
$params = array();
|
||||
$params = [];
|
||||
foreach ($this->parameters as $param => $val) {
|
||||
if ($param && '-' === $param[0]) {
|
||||
$params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
|
||||
if ($param && \is_string($param) && '-' === $param[0]) {
|
||||
$glue = ('-' === $param[1]) ? '=' : ' ';
|
||||
if (\is_array($val)) {
|
||||
foreach ($val as $v) {
|
||||
$params[] = $param.('' != $v ? $glue.$this->escapeToken($v) : '');
|
||||
}
|
||||
} else {
|
||||
$params[] = $param.('' != $val ? $glue.$this->escapeToken($val) : '');
|
||||
}
|
||||
} else {
|
||||
$params[] = $this->escapeToken($val);
|
||||
$params[] = \is_array($val) ? implode(' ', array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,12 +128,12 @@ class ArrayInput extends Input
|
||||
protected function parse()
|
||||
{
|
||||
foreach ($this->parameters as $key => $value) {
|
||||
if ($key === '--') {
|
||||
if ('--' === $key) {
|
||||
return;
|
||||
}
|
||||
if (0 === strpos($key, '--')) {
|
||||
if (str_starts_with($key, '--')) {
|
||||
$this->addLongOption(substr($key, 2), $value);
|
||||
} elseif ('-' === $key[0]) {
|
||||
} elseif (str_starts_with($key, '-')) {
|
||||
$this->addShortOption(substr($key, 1), $value);
|
||||
} else {
|
||||
$this->addArgument($key, $value);
|
||||
@@ -143,12 +144,9 @@ class ArrayInput extends Input
|
||||
/**
|
||||
* Adds a short option value.
|
||||
*
|
||||
* @param string $shortcut The short option key
|
||||
* @param mixed $value The value for the option
|
||||
*
|
||||
* @throws InvalidOptionException When option given doesn't exist
|
||||
*/
|
||||
private function addShortOption($shortcut, $value)
|
||||
private function addShortOption(string $shortcut, mixed $value)
|
||||
{
|
||||
if (!$this->definition->hasShortcut($shortcut)) {
|
||||
throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
|
||||
@@ -160,16 +158,20 @@ class ArrayInput extends Input
|
||||
/**
|
||||
* Adds a long option value.
|
||||
*
|
||||
* @param string $name The long option key
|
||||
* @param mixed $value The value for the option
|
||||
*
|
||||
* @throws InvalidOptionException When option given doesn't exist
|
||||
* @throws InvalidOptionException When a required value is missing
|
||||
*/
|
||||
private function addLongOption($name, $value)
|
||||
private function addLongOption(string $name, mixed $value)
|
||||
{
|
||||
if (!$this->definition->hasOption($name)) {
|
||||
throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
|
||||
if (!$this->definition->hasNegation($name)) {
|
||||
throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
$optionName = $this->definition->negationToName($name);
|
||||
$this->options[$optionName] = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$option = $this->definition->getOption($name);
|
||||
@@ -190,12 +192,9 @@ class ArrayInput extends Input
|
||||
/**
|
||||
* Adds an argument value.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
* @param mixed $value The value for the argument
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
*/
|
||||
private function addArgument($name, $value)
|
||||
private function addArgument(string|int $name, mixed $value)
|
||||
{
|
||||
if (!$this->definition->hasArgument($name)) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
|
||||
|
||||
68
vendor/symfony/console/Input/Input.php
vendored
68
vendor/symfony/console/Input/Input.php
vendored
@@ -27,20 +27,12 @@ use Symfony\Component\Console\Exception\RuntimeException;
|
||||
*/
|
||||
abstract class Input implements InputInterface, StreamableInputInterface
|
||||
{
|
||||
/**
|
||||
* @var InputDefinition
|
||||
*/
|
||||
protected $definition;
|
||||
protected $stream;
|
||||
protected $options = array();
|
||||
protected $arguments = array();
|
||||
protected $options = [];
|
||||
protected $arguments = [];
|
||||
protected $interactive = true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param InputDefinition|null $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(InputDefinition $definition = null)
|
||||
{
|
||||
if (null === $definition) {
|
||||
@@ -56,8 +48,8 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
*/
|
||||
public function bind(InputDefinition $definition)
|
||||
{
|
||||
$this->arguments = array();
|
||||
$this->options = array();
|
||||
$this->arguments = [];
|
||||
$this->options = [];
|
||||
$this->definition = $definition;
|
||||
|
||||
$this->parse();
|
||||
@@ -77,10 +69,10 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
$givenArguments = $this->arguments;
|
||||
|
||||
$missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
|
||||
return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
|
||||
return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
|
||||
});
|
||||
|
||||
if (count($missingArguments) > 0) {
|
||||
if (\count($missingArguments) > 0) {
|
||||
throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
|
||||
}
|
||||
}
|
||||
@@ -88,7 +80,7 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isInteractive()
|
||||
public function isInteractive(): bool
|
||||
{
|
||||
return $this->interactive;
|
||||
}
|
||||
@@ -96,15 +88,15 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setInteractive($interactive)
|
||||
public function setInteractive(bool $interactive)
|
||||
{
|
||||
$this->interactive = (bool) $interactive;
|
||||
$this->interactive = $interactive;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments()
|
||||
public function getArguments(): array
|
||||
{
|
||||
return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
|
||||
}
|
||||
@@ -112,19 +104,19 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArgument($name)
|
||||
public function getArgument(string $name): mixed
|
||||
{
|
||||
if (!$this->definition->hasArgument($name)) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
|
||||
}
|
||||
|
||||
return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
|
||||
return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArgument($name, $value)
|
||||
public function setArgument(string $name, mixed $value)
|
||||
{
|
||||
if (!$this->definition->hasArgument($name)) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
|
||||
@@ -136,7 +128,7 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasArgument($name)
|
||||
public function hasArgument(string $name): bool
|
||||
{
|
||||
return $this->definition->hasArgument($name);
|
||||
}
|
||||
@@ -144,7 +136,7 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOptions()
|
||||
public function getOptions(): array
|
||||
{
|
||||
return array_merge($this->definition->getOptionDefaults(), $this->options);
|
||||
}
|
||||
@@ -152,21 +144,33 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOption($name)
|
||||
public function getOption(string $name): mixed
|
||||
{
|
||||
if ($this->definition->hasNegation($name)) {
|
||||
if (null === $value = $this->getOption($this->definition->negationToName($name))) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return !$value;
|
||||
}
|
||||
|
||||
if (!$this->definition->hasOption($name)) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
return array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
|
||||
return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOption($name, $value)
|
||||
public function setOption(string $name, mixed $value)
|
||||
{
|
||||
if (!$this->definition->hasOption($name)) {
|
||||
if ($this->definition->hasNegation($name)) {
|
||||
$this->options[$this->definition->negationToName($name)] = !$value;
|
||||
|
||||
return;
|
||||
} elseif (!$this->definition->hasOption($name)) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
@@ -176,19 +180,15 @@ abstract class Input implements InputInterface, StreamableInputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasOption($name)
|
||||
public function hasOption(string $name): bool
|
||||
{
|
||||
return $this->definition->hasOption($name);
|
||||
return $this->definition->hasOption($name) || $this->definition->hasNegation($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a token through escapeshellarg if it contains unsafe chars.
|
||||
*
|
||||
* @param string $token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function escapeToken($token)
|
||||
public function escapeToken(string $token): string
|
||||
{
|
||||
return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
|
||||
}
|
||||
|
||||
54
vendor/symfony/console/Input/InputArgument.php
vendored
54
vendor/symfony/console/Input/InputArgument.php
vendored
@@ -21,30 +21,28 @@ use Symfony\Component\Console\Exception\LogicException;
|
||||
*/
|
||||
class InputArgument
|
||||
{
|
||||
const REQUIRED = 1;
|
||||
const OPTIONAL = 2;
|
||||
const IS_ARRAY = 4;
|
||||
public const REQUIRED = 1;
|
||||
public const OPTIONAL = 2;
|
||||
public const IS_ARRAY = 4;
|
||||
|
||||
private $name;
|
||||
private $mode;
|
||||
private $default;
|
||||
private $description;
|
||||
private string $name;
|
||||
private int $mode;
|
||||
private string|int|bool|array|null|float $default;
|
||||
private string $description;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @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|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only)
|
||||
*
|
||||
* @throws InvalidArgumentException When argument mode is not valid
|
||||
*/
|
||||
public function __construct($name, $mode = null, $description = '', $default = null)
|
||||
public function __construct(string $name, int $mode = null, string $description = '', string|bool|int|float|array $default = null)
|
||||
{
|
||||
if (null === $mode) {
|
||||
$mode = self::OPTIONAL;
|
||||
} elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
|
||||
} elseif ($mode > 7 || $mode < 1) {
|
||||
throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
|
||||
}
|
||||
|
||||
@@ -57,10 +55,8 @@ class InputArgument
|
||||
|
||||
/**
|
||||
* Returns the argument name.
|
||||
*
|
||||
* @return string The argument name
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
@@ -70,7 +66,7 @@ class InputArgument
|
||||
*
|
||||
* @return bool true if parameter mode is self::REQUIRED, false otherwise
|
||||
*/
|
||||
public function isRequired()
|
||||
public function isRequired(): bool
|
||||
{
|
||||
return self::REQUIRED === (self::REQUIRED & $this->mode);
|
||||
}
|
||||
@@ -80,7 +76,7 @@ class InputArgument
|
||||
*
|
||||
* @return bool true if mode is self::IS_ARRAY, false otherwise
|
||||
*/
|
||||
public function isArray()
|
||||
public function isArray(): bool
|
||||
{
|
||||
return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
|
||||
}
|
||||
@@ -88,20 +84,18 @@ class InputArgument
|
||||
/**
|
||||
* Sets the default value.
|
||||
*
|
||||
* @param mixed $default The default value
|
||||
*
|
||||
* @throws LogicException When incorrect default value is given
|
||||
*/
|
||||
public function setDefault($default = null)
|
||||
public function setDefault(string|bool|int|float|array $default = null)
|
||||
{
|
||||
if (self::REQUIRED === $this->mode && null !== $default) {
|
||||
if ($this->isRequired() && null !== $default) {
|
||||
throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
|
||||
}
|
||||
|
||||
if ($this->isArray()) {
|
||||
if (null === $default) {
|
||||
$default = array();
|
||||
} elseif (!is_array($default)) {
|
||||
$default = [];
|
||||
} elseif (!\is_array($default)) {
|
||||
throw new LogicException('A default value for an array argument must be an array.');
|
||||
}
|
||||
}
|
||||
@@ -111,20 +105,16 @@ class InputArgument
|
||||
|
||||
/**
|
||||
* Returns the default value.
|
||||
*
|
||||
* @return mixed The default value
|
||||
*/
|
||||
public function getDefault()
|
||||
public function getDefault(): string|bool|int|float|array|null
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description text.
|
||||
*
|
||||
* @return string The description text
|
||||
*/
|
||||
public function getDescription()
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ interface InputAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the Console Input.
|
||||
*
|
||||
* @param InputInterface
|
||||
*/
|
||||
public function setInput(InputInterface $input);
|
||||
}
|
||||
|
||||
214
vendor/symfony/console/Input/InputDefinition.php
vendored
214
vendor/symfony/console/Input/InputDefinition.php
vendored
@@ -19,41 +19,38 @@ use Symfony\Component\Console\Exception\LogicException;
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $definition = new InputDefinition(array(
|
||||
* new InputArgument('name', InputArgument::REQUIRED),
|
||||
* new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
|
||||
* ));
|
||||
* $definition = new InputDefinition([
|
||||
* new InputArgument('name', InputArgument::REQUIRED),
|
||||
* new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
|
||||
* ]);
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class InputDefinition
|
||||
{
|
||||
private $arguments;
|
||||
private $requiredCount;
|
||||
private $hasAnArrayArgument = false;
|
||||
private $hasOptional;
|
||||
private $options;
|
||||
private $shortcuts;
|
||||
private array $arguments = [];
|
||||
private int $requiredCount = 0;
|
||||
private $lastArrayArgument = null;
|
||||
private $lastOptionalArgument = null;
|
||||
private array $options = [];
|
||||
private array $negations = [];
|
||||
private array $shortcuts = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $definition An array of InputArgument and InputOption instance
|
||||
*/
|
||||
public function __construct(array $definition = array())
|
||||
public function __construct(array $definition = [])
|
||||
{
|
||||
$this->setDefinition($definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the definition of the input.
|
||||
*
|
||||
* @param array $definition The definition array
|
||||
*/
|
||||
public function setDefinition(array $definition)
|
||||
{
|
||||
$arguments = array();
|
||||
$options = array();
|
||||
$arguments = [];
|
||||
$options = [];
|
||||
foreach ($definition as $item) {
|
||||
if ($item instanceof InputOption) {
|
||||
$options[] = $item;
|
||||
@@ -71,12 +68,12 @@ class InputDefinition
|
||||
*
|
||||
* @param InputArgument[] $arguments An array of InputArgument objects
|
||||
*/
|
||||
public function setArguments($arguments = array())
|
||||
public function setArguments(array $arguments = [])
|
||||
{
|
||||
$this->arguments = array();
|
||||
$this->arguments = [];
|
||||
$this->requiredCount = 0;
|
||||
$this->hasOptional = false;
|
||||
$this->hasAnArrayArgument = false;
|
||||
$this->lastOptionalArgument = null;
|
||||
$this->lastArrayArgument = null;
|
||||
$this->addArguments($arguments);
|
||||
}
|
||||
|
||||
@@ -85,7 +82,7 @@ class InputDefinition
|
||||
*
|
||||
* @param InputArgument[] $arguments An array of InputArgument objects
|
||||
*/
|
||||
public function addArguments($arguments = array())
|
||||
public function addArguments(?array $arguments = [])
|
||||
{
|
||||
if (null !== $arguments) {
|
||||
foreach ($arguments as $argument) {
|
||||
@@ -95,10 +92,6 @@ class InputDefinition
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an InputArgument object.
|
||||
*
|
||||
* @param InputArgument $argument An InputArgument object
|
||||
*
|
||||
* @throws LogicException When incorrect argument is given
|
||||
*/
|
||||
public function addArgument(InputArgument $argument)
|
||||
@@ -107,22 +100,22 @@ class InputDefinition
|
||||
throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
|
||||
}
|
||||
|
||||
if ($this->hasAnArrayArgument) {
|
||||
throw new LogicException('Cannot add an argument after an array argument.');
|
||||
if (null !== $this->lastArrayArgument) {
|
||||
throw new LogicException(sprintf('Cannot add a required argument "%s" after an array argument "%s".', $argument->getName(), $this->lastArrayArgument->getName()));
|
||||
}
|
||||
|
||||
if ($argument->isRequired() && $this->hasOptional) {
|
||||
throw new LogicException('Cannot add a required argument after an optional one.');
|
||||
if ($argument->isRequired() && null !== $this->lastOptionalArgument) {
|
||||
throw new LogicException(sprintf('Cannot add a required argument "%s" after an optional one "%s".', $argument->getName(), $this->lastOptionalArgument->getName()));
|
||||
}
|
||||
|
||||
if ($argument->isArray()) {
|
||||
$this->hasAnArrayArgument = true;
|
||||
$this->lastArrayArgument = $argument;
|
||||
}
|
||||
|
||||
if ($argument->isRequired()) {
|
||||
++$this->requiredCount;
|
||||
} else {
|
||||
$this->hasOptional = true;
|
||||
$this->lastOptionalArgument = $argument;
|
||||
}
|
||||
|
||||
$this->arguments[$argument->getName()] = $argument;
|
||||
@@ -131,33 +124,25 @@ class InputDefinition
|
||||
/**
|
||||
* Returns an InputArgument by name or by position.
|
||||
*
|
||||
* @param string|int $name The InputArgument name or position
|
||||
*
|
||||
* @return InputArgument An InputArgument object
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
*/
|
||||
public function getArgument($name)
|
||||
public function getArgument(string|int $name): InputArgument
|
||||
{
|
||||
if (!$this->hasArgument($name)) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
|
||||
}
|
||||
|
||||
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
|
||||
$arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
|
||||
|
||||
return $arguments[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputArgument object exists by name or position.
|
||||
*
|
||||
* @param string|int $name The InputArgument name or position
|
||||
*
|
||||
* @return bool true if the InputArgument object exists, false otherwise
|
||||
*/
|
||||
public function hasArgument($name)
|
||||
public function hasArgument(string|int $name): bool
|
||||
{
|
||||
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
|
||||
$arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
|
||||
|
||||
return isset($arguments[$name]);
|
||||
}
|
||||
@@ -165,41 +150,35 @@ class InputDefinition
|
||||
/**
|
||||
* Gets the array of InputArgument objects.
|
||||
*
|
||||
* @return InputArgument[] An array of InputArgument objects
|
||||
* @return InputArgument[]
|
||||
*/
|
||||
public function getArguments()
|
||||
public function getArguments(): array
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of InputArguments.
|
||||
*
|
||||
* @return int The number of InputArguments
|
||||
*/
|
||||
public function getArgumentCount()
|
||||
public function getArgumentCount(): int
|
||||
{
|
||||
return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
|
||||
return null !== $this->lastArrayArgument ? \PHP_INT_MAX : \count($this->arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of required InputArguments.
|
||||
*
|
||||
* @return int The number of required InputArguments
|
||||
*/
|
||||
public function getArgumentRequiredCount()
|
||||
public function getArgumentRequiredCount(): int
|
||||
{
|
||||
return $this->requiredCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default values.
|
||||
*
|
||||
* @return array An array of default values
|
||||
* @return array<string|bool|int|float|array|null>
|
||||
*/
|
||||
public function getArgumentDefaults()
|
||||
public function getArgumentDefaults(): array
|
||||
{
|
||||
$values = array();
|
||||
$values = [];
|
||||
foreach ($this->arguments as $argument) {
|
||||
$values[$argument->getName()] = $argument->getDefault();
|
||||
}
|
||||
@@ -212,10 +191,11 @@ class InputDefinition
|
||||
*
|
||||
* @param InputOption[] $options An array of InputOption objects
|
||||
*/
|
||||
public function setOptions($options = array())
|
||||
public function setOptions(array $options = [])
|
||||
{
|
||||
$this->options = array();
|
||||
$this->shortcuts = array();
|
||||
$this->options = [];
|
||||
$this->shortcuts = [];
|
||||
$this->negations = [];
|
||||
$this->addOptions($options);
|
||||
}
|
||||
|
||||
@@ -224,7 +204,7 @@ class InputDefinition
|
||||
*
|
||||
* @param InputOption[] $options An array of InputOption objects
|
||||
*/
|
||||
public function addOptions($options = array())
|
||||
public function addOptions(array $options = [])
|
||||
{
|
||||
foreach ($options as $option) {
|
||||
$this->addOption($option);
|
||||
@@ -232,10 +212,6 @@ class InputDefinition
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an InputOption object.
|
||||
*
|
||||
* @param InputOption $option An InputOption object
|
||||
*
|
||||
* @throws LogicException When option given already exist
|
||||
*/
|
||||
public function addOption(InputOption $option)
|
||||
@@ -243,6 +219,9 @@ class InputDefinition
|
||||
if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
|
||||
throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
|
||||
}
|
||||
if (isset($this->negations[$option->getName()])) {
|
||||
throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
|
||||
}
|
||||
|
||||
if ($option->getShortcut()) {
|
||||
foreach (explode('|', $option->getShortcut()) as $shortcut) {
|
||||
@@ -258,18 +237,22 @@ class InputDefinition
|
||||
$this->shortcuts[$shortcut] = $option->getName();
|
||||
}
|
||||
}
|
||||
|
||||
if ($option->isNegatable()) {
|
||||
$negatedName = 'no-'.$option->getName();
|
||||
if (isset($this->options[$negatedName])) {
|
||||
throw new LogicException(sprintf('An option named "%s" already exists.', $negatedName));
|
||||
}
|
||||
$this->negations[$negatedName] = $option->getName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputOption by name.
|
||||
*
|
||||
* @param string $name The InputOption name
|
||||
*
|
||||
* @return InputOption A InputOption object
|
||||
*
|
||||
* @throws InvalidArgumentException When option given doesn't exist
|
||||
*/
|
||||
public function getOption($name)
|
||||
public function getOption(string $name): InputOption
|
||||
{
|
||||
if (!$this->hasOption($name)) {
|
||||
throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
|
||||
@@ -283,12 +266,8 @@ class InputDefinition
|
||||
*
|
||||
* This method can't be used to check if the user included the option when
|
||||
* executing the command (use getOption() instead).
|
||||
*
|
||||
* @param string $name The InputOption name
|
||||
*
|
||||
* @return bool true if the InputOption object exists, false otherwise
|
||||
*/
|
||||
public function hasOption($name)
|
||||
public function hasOption(string $name): bool
|
||||
{
|
||||
return isset($this->options[$name]);
|
||||
}
|
||||
@@ -296,45 +275,43 @@ class InputDefinition
|
||||
/**
|
||||
* Gets the array of InputOption objects.
|
||||
*
|
||||
* @return InputOption[] An array of InputOption objects
|
||||
* @return InputOption[]
|
||||
*/
|
||||
public function getOptions()
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputOption object exists by shortcut.
|
||||
*
|
||||
* @param string $name The InputOption shortcut
|
||||
*
|
||||
* @return bool true if the InputOption object exists, false otherwise
|
||||
*/
|
||||
public function hasShortcut($name)
|
||||
public function hasShortcut(string $name): bool
|
||||
{
|
||||
return isset($this->shortcuts[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an InputOption by shortcut.
|
||||
*
|
||||
* @param string $shortcut the Shortcut name
|
||||
*
|
||||
* @return InputOption An InputOption object
|
||||
* Returns true if an InputOption object exists by negated name.
|
||||
*/
|
||||
public function getOptionForShortcut($shortcut)
|
||||
public function hasNegation(string $name): bool
|
||||
{
|
||||
return isset($this->negations[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an InputOption by shortcut.
|
||||
*/
|
||||
public function getOptionForShortcut(string $shortcut): InputOption
|
||||
{
|
||||
return $this->getOption($this->shortcutToName($shortcut));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of default values.
|
||||
*
|
||||
* @return array An array of all default values
|
||||
* @return array<string|bool|int|float|array|null>
|
||||
*/
|
||||
public function getOptionDefaults()
|
||||
public function getOptionDefaults(): array
|
||||
{
|
||||
$values = array();
|
||||
$values = [];
|
||||
foreach ($this->options as $option) {
|
||||
$values[$option->getName()] = $option->getDefault();
|
||||
}
|
||||
@@ -345,13 +322,11 @@ class InputDefinition
|
||||
/**
|
||||
* Returns the InputOption name given a shortcut.
|
||||
*
|
||||
* @param string $shortcut The shortcut
|
||||
*
|
||||
* @return string The InputOption name
|
||||
*
|
||||
* @throws InvalidArgumentException When option given does not exist
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private function shortcutToName($shortcut)
|
||||
public function shortcutToName(string $shortcut): string
|
||||
{
|
||||
if (!isset($this->shortcuts[$shortcut])) {
|
||||
throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
|
||||
@@ -361,15 +336,27 @@ class InputDefinition
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the synopsis.
|
||||
* Returns the InputOption name given a negation.
|
||||
*
|
||||
* @param bool $short Whether to return the short version (with options folded) or not
|
||||
* @throws InvalidArgumentException When option given does not exist
|
||||
*
|
||||
* @return string The synopsis
|
||||
* @internal
|
||||
*/
|
||||
public function getSynopsis($short = false)
|
||||
public function negationToName(string $negation): string
|
||||
{
|
||||
$elements = array();
|
||||
if (!isset($this->negations[$negation])) {
|
||||
throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $negation));
|
||||
}
|
||||
|
||||
return $this->negations[$negation];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the synopsis.
|
||||
*/
|
||||
public function getSynopsis(bool $short = false): string
|
||||
{
|
||||
$elements = [];
|
||||
|
||||
if ($short && $this->getOptions()) {
|
||||
$elements[] = '[options]';
|
||||
@@ -386,29 +373,30 @@ class InputDefinition
|
||||
}
|
||||
|
||||
$shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
|
||||
$elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
|
||||
$negation = $option->isNegatable() ? sprintf('|--no-%s', $option->getName()) : '';
|
||||
$elements[] = sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($elements) && $this->getArguments()) {
|
||||
if (\count($elements) && $this->getArguments()) {
|
||||
$elements[] = '[--]';
|
||||
}
|
||||
|
||||
$tail = '';
|
||||
foreach ($this->getArguments() as $argument) {
|
||||
$element = '<'.$argument->getName().'>';
|
||||
if (!$argument->isRequired()) {
|
||||
$element = '['.$element.']';
|
||||
} elseif ($argument->isArray()) {
|
||||
$element = $element.' ('.$element.')';
|
||||
}
|
||||
|
||||
if ($argument->isArray()) {
|
||||
$element .= '...';
|
||||
}
|
||||
|
||||
if (!$argument->isRequired()) {
|
||||
$element = '['.$element;
|
||||
$tail .= ']';
|
||||
}
|
||||
|
||||
$elements[] = $element;
|
||||
}
|
||||
|
||||
return implode(' ', $elements);
|
||||
return implode(' ', $elements).$tail;
|
||||
}
|
||||
}
|
||||
|
||||
74
vendor/symfony/console/Input/InputInterface.php
vendored
74
vendor/symfony/console/Input/InputInterface.php
vendored
@@ -23,42 +23,42 @@ interface InputInterface
|
||||
{
|
||||
/**
|
||||
* Returns the first argument from the raw parameters (not parsed).
|
||||
*
|
||||
* @return string The value of the first argument or null otherwise
|
||||
*/
|
||||
public function getFirstArgument();
|
||||
public function getFirstArgument(): ?string;
|
||||
|
||||
/**
|
||||
* Returns true if the raw parameters (not parsed) contain a value.
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before they have been validated. It must be used carefully.
|
||||
* Does not necessarily return the correct result for short options
|
||||
* when multiple flags are combined in the same option.
|
||||
*
|
||||
* @param string|array $values The values to look for in the raw parameters (can be an array)
|
||||
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
|
||||
*
|
||||
* @return bool true if the value is contained in the raw parameters
|
||||
*/
|
||||
public function hasParameterOption($values, $onlyParams = false);
|
||||
public function hasParameterOption(string|array $values, bool $onlyParams = false): bool;
|
||||
|
||||
/**
|
||||
* Returns the value of a raw option (not parsed).
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before they have been validated. It must be used carefully.
|
||||
* Does not necessarily return the correct result for short options
|
||||
* when multiple flags are combined in the same option.
|
||||
*
|
||||
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
|
||||
* @param mixed $default The default value to return if no result is found
|
||||
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
|
||||
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
|
||||
* @param string|bool|int|float|array|null $default The default value to return if no result is found
|
||||
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
|
||||
*
|
||||
* @return mixed The option value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParameterOption($values, $default = false, $onlyParams = false);
|
||||
public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false);
|
||||
|
||||
/**
|
||||
* Binds the current Input instance with the given arguments and options.
|
||||
*
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function bind(InputDefinition $definition);
|
||||
|
||||
@@ -72,88 +72,66 @@ interface InputInterface
|
||||
/**
|
||||
* Returns all the given arguments merged with the default values.
|
||||
*
|
||||
* @return array
|
||||
* @return array<string|bool|int|float|array|null>
|
||||
*/
|
||||
public function getArguments();
|
||||
public function getArguments(): array;
|
||||
|
||||
/**
|
||||
* Returns the argument value for a given argument name.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
*
|
||||
* @return mixed The argument value
|
||||
* @return mixed
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
*/
|
||||
public function getArgument($name);
|
||||
public function getArgument(string $name);
|
||||
|
||||
/**
|
||||
* Sets an argument value by name.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
* @param string $value The argument value
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
*/
|
||||
public function setArgument($name, $value);
|
||||
public function setArgument(string $name, mixed $value);
|
||||
|
||||
/**
|
||||
* Returns true if an InputArgument object exists by name or position.
|
||||
*
|
||||
* @param string|int $name The InputArgument name or position
|
||||
*
|
||||
* @return bool true if the InputArgument object exists, false otherwise
|
||||
*/
|
||||
public function hasArgument($name);
|
||||
public function hasArgument(string $name): bool;
|
||||
|
||||
/**
|
||||
* Returns all the given options merged with the default values.
|
||||
*
|
||||
* @return array
|
||||
* @return array<string|bool|int|float|array|null>
|
||||
*/
|
||||
public function getOptions();
|
||||
public function getOptions(): array;
|
||||
|
||||
/**
|
||||
* Returns the option value for a given option name.
|
||||
*
|
||||
* @param string $name The option name
|
||||
*
|
||||
* @return mixed The option value
|
||||
* @return mixed
|
||||
*
|
||||
* @throws InvalidArgumentException When option given doesn't exist
|
||||
*/
|
||||
public function getOption($name);
|
||||
public function getOption(string $name);
|
||||
|
||||
/**
|
||||
* Sets an option value by name.
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @param string|bool $value The option value
|
||||
*
|
||||
* @throws InvalidArgumentException When option given doesn't exist
|
||||
*/
|
||||
public function setOption($name, $value);
|
||||
public function setOption(string $name, mixed $value);
|
||||
|
||||
/**
|
||||
* Returns true if an InputOption object exists by name.
|
||||
*
|
||||
* @param string $name The InputOption name
|
||||
*
|
||||
* @return bool true if the InputOption object exists, false otherwise
|
||||
*/
|
||||
public function hasOption($name);
|
||||
public function hasOption(string $name): bool;
|
||||
|
||||
/**
|
||||
* Is this input means interactive?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInteractive();
|
||||
public function isInteractive(): bool;
|
||||
|
||||
/**
|
||||
* Sets the input interactivity.
|
||||
*
|
||||
* @param bool $interactive If the input should be interactive
|
||||
*/
|
||||
public function setInteractive($interactive);
|
||||
public function setInteractive(bool $interactive);
|
||||
}
|
||||
|
||||
112
vendor/symfony/console/Input/InputOption.php
vendored
112
vendor/symfony/console/Input/InputOption.php
vendored
@@ -21,31 +21,47 @@ use Symfony\Component\Console\Exception\LogicException;
|
||||
*/
|
||||
class InputOption
|
||||
{
|
||||
const VALUE_NONE = 1;
|
||||
const VALUE_REQUIRED = 2;
|
||||
const VALUE_OPTIONAL = 4;
|
||||
const VALUE_IS_ARRAY = 8;
|
||||
|
||||
private $name;
|
||||
private $shortcut;
|
||||
private $mode;
|
||||
private $default;
|
||||
private $description;
|
||||
/**
|
||||
* Do not accept input for the option (e.g. --yell). This is the default behavior of options.
|
||||
*/
|
||||
public const VALUE_NONE = 1;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @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)
|
||||
* A value must be passed when the option is used (e.g. --iterations=5 or -i5).
|
||||
*/
|
||||
public const VALUE_REQUIRED = 2;
|
||||
|
||||
/**
|
||||
* The option may or may not have a value (e.g. --yell or --yell=loud).
|
||||
*/
|
||||
public const VALUE_OPTIONAL = 4;
|
||||
|
||||
/**
|
||||
* The option accepts multiple values (e.g. --dir=/foo --dir=/bar).
|
||||
*/
|
||||
public const VALUE_IS_ARRAY = 8;
|
||||
|
||||
/**
|
||||
* The option may have either positive or negative value (e.g. --ansi or --no-ansi).
|
||||
*/
|
||||
public const VALUE_NEGATABLE = 16;
|
||||
|
||||
private string $name;
|
||||
private string|array|null $shortcut;
|
||||
private int $mode;
|
||||
private string|int|bool|array|null|float $default;
|
||||
private string $description;
|
||||
|
||||
/**
|
||||
* @param string|array|null $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|bool|int|float|array|null $default The default value (must be null for self::VALUE_NONE)
|
||||
*
|
||||
* @throws InvalidArgumentException If option mode is invalid or incompatible
|
||||
*/
|
||||
public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
|
||||
public function __construct(string $name, string|array $shortcut = null, int $mode = null, string $description = '', string|bool|int|float|array $default = null)
|
||||
{
|
||||
if (0 === strpos($name, '--')) {
|
||||
if (str_starts_with($name, '--')) {
|
||||
$name = substr($name, 2);
|
||||
}
|
||||
|
||||
@@ -58,7 +74,7 @@ class InputOption
|
||||
}
|
||||
|
||||
if (null !== $shortcut) {
|
||||
if (is_array($shortcut)) {
|
||||
if (\is_array($shortcut)) {
|
||||
$shortcut = implode('|', $shortcut);
|
||||
}
|
||||
$shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
|
||||
@@ -72,7 +88,7 @@ class InputOption
|
||||
|
||||
if (null === $mode) {
|
||||
$mode = self::VALUE_NONE;
|
||||
} elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
|
||||
} elseif ($mode >= (self::VALUE_NEGATABLE << 1) || $mode < 1) {
|
||||
throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
|
||||
}
|
||||
|
||||
@@ -84,26 +100,25 @@ class InputOption
|
||||
if ($this->isArray() && !$this->acceptValue()) {
|
||||
throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
|
||||
}
|
||||
if ($this->isNegatable() && $this->acceptValue()) {
|
||||
throw new InvalidArgumentException('Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.');
|
||||
}
|
||||
|
||||
$this->setDefault($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the option shortcut.
|
||||
*
|
||||
* @return string The shortcut
|
||||
*/
|
||||
public function getShortcut()
|
||||
public function getShortcut(): ?string
|
||||
{
|
||||
return $this->shortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the option name.
|
||||
*
|
||||
* @return string The name
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
@@ -113,7 +128,7 @@ class InputOption
|
||||
*
|
||||
* @return bool true if value mode is not self::VALUE_NONE, false otherwise
|
||||
*/
|
||||
public function acceptValue()
|
||||
public function acceptValue(): bool
|
||||
{
|
||||
return $this->isValueRequired() || $this->isValueOptional();
|
||||
}
|
||||
@@ -123,7 +138,7 @@ class InputOption
|
||||
*
|
||||
* @return bool true if value mode is self::VALUE_REQUIRED, false otherwise
|
||||
*/
|
||||
public function isValueRequired()
|
||||
public function isValueRequired(): bool
|
||||
{
|
||||
return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
|
||||
}
|
||||
@@ -133,7 +148,7 @@ class InputOption
|
||||
*
|
||||
* @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise
|
||||
*/
|
||||
public function isValueOptional()
|
||||
public function isValueOptional(): bool
|
||||
{
|
||||
return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
|
||||
}
|
||||
@@ -143,19 +158,17 @@ class InputOption
|
||||
*
|
||||
* @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise
|
||||
*/
|
||||
public function isArray()
|
||||
public function isArray(): bool
|
||||
{
|
||||
return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default value.
|
||||
*
|
||||
* @param mixed $default The default value
|
||||
*
|
||||
* @throws LogicException When incorrect default value is given
|
||||
*/
|
||||
public function setDefault($default = null)
|
||||
public function isNegatable(): bool
|
||||
{
|
||||
return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode);
|
||||
}
|
||||
|
||||
public function setDefault(string|bool|int|float|array $default = null)
|
||||
{
|
||||
if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
|
||||
throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
|
||||
@@ -163,47 +176,40 @@ class InputOption
|
||||
|
||||
if ($this->isArray()) {
|
||||
if (null === $default) {
|
||||
$default = array();
|
||||
} elseif (!is_array($default)) {
|
||||
$default = [];
|
||||
} elseif (!\is_array($default)) {
|
||||
throw new LogicException('A default value for an array option must be an array.');
|
||||
}
|
||||
}
|
||||
|
||||
$this->default = $this->acceptValue() ? $default : false;
|
||||
$this->default = $this->acceptValue() || $this->isNegatable() ? $default : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value.
|
||||
*
|
||||
* @return mixed The default value
|
||||
*/
|
||||
public function getDefault()
|
||||
public function getDefault(): string|bool|int|float|array|null
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description text.
|
||||
*
|
||||
* @return string The description text
|
||||
*/
|
||||
public function getDescription()
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given option equals this one.
|
||||
*
|
||||
* @param InputOption $option option to compare
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(InputOption $option)
|
||||
public function equals(self $option): bool
|
||||
{
|
||||
return $option->getName() === $this->getName()
|
||||
&& $option->getShortcut() === $this->getShortcut()
|
||||
&& $option->getDefault() === $this->getDefault()
|
||||
&& $option->isNegatable() === $this->isNegatable()
|
||||
&& $option->isArray() === $this->isArray()
|
||||
&& $option->isValueRequired() === $this->isValueRequired()
|
||||
&& $option->isValueOptional() === $this->isValueOptional()
|
||||
|
||||
60
vendor/symfony/console/Input/StringInput.php
vendored
60
vendor/symfony/console/Input/StringInput.php
vendored
@@ -24,17 +24,16 @@ use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
*/
|
||||
class StringInput extends ArgvInput
|
||||
{
|
||||
const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
|
||||
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
|
||||
public const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
|
||||
public const REGEX_UNQUOTED_STRING = '([^\s\\\\]+?)';
|
||||
public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $input An array of parameters from the CLI (in the argv format)
|
||||
* @param string $input A string representing the parameters from the CLI
|
||||
*/
|
||||
public function __construct($input)
|
||||
public function __construct(string $input)
|
||||
{
|
||||
parent::__construct(array());
|
||||
parent::__construct([]);
|
||||
|
||||
$this->setTokens($this->tokenize($input));
|
||||
}
|
||||
@@ -42,31 +41,42 @@ class StringInput extends ArgvInput
|
||||
/**
|
||||
* Tokenizes a string.
|
||||
*
|
||||
* @param string $input The input to tokenize
|
||||
*
|
||||
* @return array An array of tokens
|
||||
*
|
||||
* @throws InvalidArgumentException When unable to parse input (should never happen)
|
||||
*/
|
||||
private function tokenize($input)
|
||||
private function tokenize(string $input): array
|
||||
{
|
||||
$tokens = array();
|
||||
$length = strlen($input);
|
||||
$tokens = [];
|
||||
$length = \strlen($input);
|
||||
$cursor = 0;
|
||||
$token = null;
|
||||
while ($cursor < $length) {
|
||||
if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
|
||||
} elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
|
||||
$tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
|
||||
} elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
|
||||
$tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
|
||||
} elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
|
||||
$tokens[] = stripcslashes($match[1]);
|
||||
} else {
|
||||
// should never happen
|
||||
throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
|
||||
if ('\\' === $input[$cursor]) {
|
||||
$token .= $input[++$cursor] ?? '';
|
||||
++$cursor;
|
||||
continue;
|
||||
}
|
||||
|
||||
$cursor += strlen($match[0]);
|
||||
if (preg_match('/\s+/A', $input, $match, 0, $cursor)) {
|
||||
if (null !== $token) {
|
||||
$tokens[] = $token;
|
||||
$token = null;
|
||||
}
|
||||
} elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, 0, $cursor)) {
|
||||
$token .= $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, -1)));
|
||||
} elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, 0, $cursor)) {
|
||||
$token .= stripcslashes(substr($match[0], 1, -1));
|
||||
} elseif (preg_match('/'.self::REGEX_UNQUOTED_STRING.'/A', $input, $match, 0, $cursor)) {
|
||||
$token .= $match[1];
|
||||
} else {
|
||||
// should never happen
|
||||
throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10)));
|
||||
}
|
||||
|
||||
$cursor += \strlen($match[0]);
|
||||
}
|
||||
|
||||
if (null !== $token) {
|
||||
$tokens[] = $token;
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
|
||||
2
vendor/symfony/console/LICENSE
vendored
2
vendor/symfony/console/LICENSE
vendored
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2017 Fabien Potencier
|
||||
Copyright (c) 2004-2022 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
67
vendor/symfony/console/Logger/ConsoleLogger.php
vendored
67
vendor/symfony/console/Logger/ConsoleLogger.php
vendored
@@ -14,29 +14,23 @@ namespace Symfony\Component\Console\Logger;
|
||||
use Psr\Log\AbstractLogger;
|
||||
use Psr\Log\InvalidArgumentException;
|
||||
use Psr\Log\LogLevel;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* PSR-3 compliant console logger.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*
|
||||
* @see http://www.php-fig.org/psr/psr-3/
|
||||
* @see https://www.php-fig.org/psr/psr-3/
|
||||
*/
|
||||
class ConsoleLogger extends AbstractLogger
|
||||
{
|
||||
const INFO = 'info';
|
||||
const ERROR = 'error';
|
||||
public const INFO = 'info';
|
||||
public const ERROR = 'error';
|
||||
|
||||
/**
|
||||
* @var OutputInterface
|
||||
*/
|
||||
private $output;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $verbosityLevelMap = array(
|
||||
private array $verbosityLevelMap = [
|
||||
LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
|
||||
LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
|
||||
LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
|
||||
@@ -45,11 +39,8 @@ class ConsoleLogger extends AbstractLogger
|
||||
LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
|
||||
LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
|
||||
LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
|
||||
);
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $formatLevelMap = array(
|
||||
];
|
||||
private array $formatLevelMap = [
|
||||
LogLevel::EMERGENCY => self::ERROR,
|
||||
LogLevel::ALERT => self::ERROR,
|
||||
LogLevel::CRITICAL => self::ERROR,
|
||||
@@ -58,15 +49,10 @@ class ConsoleLogger extends AbstractLogger
|
||||
LogLevel::NOTICE => self::INFO,
|
||||
LogLevel::INFO => self::INFO,
|
||||
LogLevel::DEBUG => self::INFO,
|
||||
);
|
||||
private $errored = false;
|
||||
];
|
||||
private bool $errored = false;
|
||||
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
* @param array $verbosityLevelMap
|
||||
* @param array $formatLevelMap
|
||||
*/
|
||||
public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
|
||||
public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = [])
|
||||
{
|
||||
$this->output = $output;
|
||||
$this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
|
||||
@@ -76,7 +62,7 @@ class ConsoleLogger extends AbstractLogger
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function log($level, $message, array $context = array())
|
||||
public function log($level, $message, array $context = []): void
|
||||
{
|
||||
if (!isset($this->verbosityLevelMap[$level])) {
|
||||
throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
|
||||
@@ -85,7 +71,7 @@ class ConsoleLogger extends AbstractLogger
|
||||
$output = $this->output;
|
||||
|
||||
// Write to the error output if necessary and available
|
||||
if ($this->formatLevelMap[$level] === self::ERROR) {
|
||||
if (self::ERROR === $this->formatLevelMap[$level]) {
|
||||
if ($this->output instanceof ConsoleOutputInterface) {
|
||||
$output = $output->getErrorOutput();
|
||||
}
|
||||
@@ -102,7 +88,7 @@ class ConsoleLogger extends AbstractLogger
|
||||
/**
|
||||
* Returns true when any messages have been logged at error levels.
|
||||
*/
|
||||
public function hasErrored()
|
||||
public function hasErrored(): bool
|
||||
{
|
||||
return $this->errored;
|
||||
}
|
||||
@@ -111,23 +97,26 @@ class ConsoleLogger extends AbstractLogger
|
||||
* Interpolates context values into the message placeholders.
|
||||
*
|
||||
* @author PHP Framework Interoperability Group
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function interpolate($message, array $context)
|
||||
private function interpolate(string $message, array $context): string
|
||||
{
|
||||
// build a replacement array with braces around the context keys
|
||||
$replace = array();
|
||||
if (!str_contains($message, '{')) {
|
||||
return $message;
|
||||
}
|
||||
|
||||
$replacements = [];
|
||||
foreach ($context as $key => $val) {
|
||||
if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
|
||||
$replace[sprintf('{%s}', $key)] = $val;
|
||||
if (null === $val || \is_scalar($val) || $val instanceof \Stringable) {
|
||||
$replacements["{{$key}}"] = $val;
|
||||
} elseif ($val instanceof \DateTimeInterface) {
|
||||
$replacements["{{$key}}"] = $val->format(\DateTime::RFC3339);
|
||||
} elseif (\is_object($val)) {
|
||||
$replacements["{{$key}}"] = '[object '.\get_class($val).']';
|
||||
} else {
|
||||
$replacements["{{$key}}"] = '['.\gettype($val).']';
|
||||
}
|
||||
}
|
||||
|
||||
// interpolate replacement values into the message and return
|
||||
return strtr($message, $replace);
|
||||
return strtr($message, $replacements);
|
||||
}
|
||||
}
|
||||
|
||||
13
vendor/symfony/console/Output/BufferedOutput.php
vendored
13
vendor/symfony/console/Output/BufferedOutput.php
vendored
@@ -16,17 +16,12 @@ namespace Symfony\Component\Console\Output;
|
||||
*/
|
||||
class BufferedOutput extends Output
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $buffer = '';
|
||||
private string $buffer = '';
|
||||
|
||||
/**
|
||||
* Empties buffer and returns its content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch(): string
|
||||
{
|
||||
$content = $this->buffer;
|
||||
$this->buffer = '';
|
||||
@@ -37,12 +32,12 @@ class BufferedOutput extends Output
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doWrite($message, $newline)
|
||||
protected function doWrite(string $message, bool $newline)
|
||||
{
|
||||
$this->buffer .= $message;
|
||||
|
||||
if ($newline) {
|
||||
$this->buffer .= PHP_EOL;
|
||||
$this->buffer .= \PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
59
vendor/symfony/console/Output/ConsoleOutput.php
vendored
59
vendor/symfony/console/Output/ConsoleOutput.php
vendored
@@ -29,22 +29,25 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
*/
|
||||
class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
{
|
||||
/**
|
||||
* @var StreamOutput
|
||||
*/
|
||||
private $stderr;
|
||||
private array $consoleSectionOutputs = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
|
||||
* @param bool|null $decorated Whether to decorate messages (null for auto-guessing)
|
||||
* @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
|
||||
*/
|
||||
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
|
||||
public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null)
|
||||
{
|
||||
parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
|
||||
|
||||
if (null === $formatter) {
|
||||
// for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter.
|
||||
$this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$actualDecorated = $this->isDecorated();
|
||||
$this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
|
||||
|
||||
@@ -53,10 +56,18 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new output section.
|
||||
*/
|
||||
public function section(): ConsoleSectionOutput
|
||||
{
|
||||
return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDecorated($decorated)
|
||||
public function setDecorated(bool $decorated)
|
||||
{
|
||||
parent::setDecorated($decorated);
|
||||
$this->stderr->setDecorated($decorated);
|
||||
@@ -74,7 +85,7 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setVerbosity($level)
|
||||
public function setVerbosity(int $level)
|
||||
{
|
||||
parent::setVerbosity($level);
|
||||
$this->stderr->setVerbosity($level);
|
||||
@@ -83,7 +94,7 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getErrorOutput()
|
||||
public function getErrorOutput(): OutputInterface
|
||||
{
|
||||
return $this->stderr;
|
||||
}
|
||||
@@ -99,10 +110,8 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
/**
|
||||
* Returns true if current environment supports writing console output to
|
||||
* STDOUT.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasStdoutSupport()
|
||||
protected function hasStdoutSupport(): bool
|
||||
{
|
||||
return false === $this->isRunningOS400();
|
||||
}
|
||||
@@ -110,10 +119,8 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
/**
|
||||
* Returns true if current environment supports writing console output to
|
||||
* STDERR.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasStderrSupport()
|
||||
protected function hasStderrSupport(): bool
|
||||
{
|
||||
return false === $this->isRunningOS400();
|
||||
}
|
||||
@@ -121,16 +128,14 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
/**
|
||||
* Checks if current executing environment is IBM iSeries (OS400), which
|
||||
* doesn't properly convert character-encodings between ASCII to EBCDIC.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isRunningOS400()
|
||||
private function isRunningOS400(): bool
|
||||
{
|
||||
$checks = array(
|
||||
function_exists('php_uname') ? php_uname('s') : '',
|
||||
$checks = [
|
||||
\function_exists('php_uname') ? php_uname('s') : '',
|
||||
getenv('OSTYPE'),
|
||||
PHP_OS,
|
||||
);
|
||||
\PHP_OS,
|
||||
];
|
||||
|
||||
return false !== stripos(implode(';', $checks), 'OS400');
|
||||
}
|
||||
@@ -144,7 +149,8 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
return fopen('php://output', 'w');
|
||||
}
|
||||
|
||||
return @fopen('php://stdout', 'w') ?: fopen('php://output', 'w');
|
||||
// Use STDOUT when possible to prevent from opening too many file descriptors
|
||||
return \defined('STDOUT') ? \STDOUT : (@fopen('php://stdout', 'w') ?: fopen('php://output', 'w'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,6 +158,11 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
|
||||
*/
|
||||
private function openErrorStream()
|
||||
{
|
||||
return fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w');
|
||||
if (!$this->hasStderrSupport()) {
|
||||
return fopen('php://output', 'w');
|
||||
}
|
||||
|
||||
// Use STDERR when possible to prevent from opening too many file descriptors
|
||||
return \defined('STDERR') ? \STDERR : (@fopen('php://stderr', 'w') ?: fopen('php://output', 'w'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Symfony\Component\Console\Output;
|
||||
|
||||
/**
|
||||
* ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
|
||||
* This adds information about stderr output stream.
|
||||
* This adds information about stderr and section output stream.
|
||||
*
|
||||
* @author Dariusz Górecki <darek.krk@gmail.com>
|
||||
*/
|
||||
@@ -21,15 +21,10 @@ interface ConsoleOutputInterface extends OutputInterface
|
||||
{
|
||||
/**
|
||||
* Gets the OutputInterface for errors.
|
||||
*
|
||||
* @return OutputInterface
|
||||
*/
|
||||
public function getErrorOutput();
|
||||
public function getErrorOutput(): OutputInterface;
|
||||
|
||||
/**
|
||||
* Sets the OutputInterface used for errors.
|
||||
*
|
||||
* @param OutputInterface $error
|
||||
*/
|
||||
public function setErrorOutput(OutputInterface $error);
|
||||
|
||||
public function section(): ConsoleSectionOutput;
|
||||
}
|
||||
|
||||
141
vendor/symfony/console/Output/ConsoleSectionOutput.php
vendored
Normal file
141
vendor/symfony/console/Output/ConsoleSectionOutput.php
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
<?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\Output;
|
||||
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
use Symfony\Component\Console\Helper\Helper;
|
||||
use Symfony\Component\Console\Terminal;
|
||||
|
||||
/**
|
||||
* @author Pierre du Plessis <pdples@gmail.com>
|
||||
* @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com>
|
||||
*/
|
||||
class ConsoleSectionOutput extends StreamOutput
|
||||
{
|
||||
private array $content = [];
|
||||
private int $lines = 0;
|
||||
private array $sections;
|
||||
private $terminal;
|
||||
|
||||
/**
|
||||
* @param resource $stream
|
||||
* @param ConsoleSectionOutput[] $sections
|
||||
*/
|
||||
public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter)
|
||||
{
|
||||
parent::__construct($stream, $verbosity, $decorated, $formatter);
|
||||
array_unshift($sections, $this);
|
||||
$this->sections = &$sections;
|
||||
$this->terminal = new Terminal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears previous output for this section.
|
||||
*
|
||||
* @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared
|
||||
*/
|
||||
public function clear(int $lines = null)
|
||||
{
|
||||
if (empty($this->content) || !$this->isDecorated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($lines) {
|
||||
array_splice($this->content, -($lines * 2)); // Multiply lines by 2 to cater for each new line added between content
|
||||
} else {
|
||||
$lines = $this->lines;
|
||||
$this->content = [];
|
||||
}
|
||||
|
||||
$this->lines -= $lines;
|
||||
|
||||
parent::doWrite($this->popStreamContentUntilCurrentSection($lines), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the previous output with a new message.
|
||||
*/
|
||||
public function overwrite(string|iterable $message)
|
||||
{
|
||||
$this->clear();
|
||||
$this->writeln($message);
|
||||
}
|
||||
|
||||
public function getContent(): string
|
||||
{
|
||||
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}
|
||||
*/
|
||||
protected function doWrite(string $message, bool $newline)
|
||||
{
|
||||
if (!$this->isDecorated()) {
|
||||
parent::doWrite($message, $newline);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$erasedContent = $this->popStreamContentUntilCurrentSection();
|
||||
|
||||
$this->addContent($message);
|
||||
|
||||
parent::doWrite($message, true);
|
||||
parent::doWrite($erasedContent, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits
|
||||
* current section. Then it erases content it crawled through. Optionally, it erases part of current section too.
|
||||
*/
|
||||
private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0): string
|
||||
{
|
||||
$numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection;
|
||||
$erasedContent = [];
|
||||
|
||||
foreach ($this->sections as $section) {
|
||||
if ($section === $this) {
|
||||
break;
|
||||
}
|
||||
|
||||
$numberOfLinesToClear += $section->lines;
|
||||
$erasedContent[] = $section->getContent();
|
||||
}
|
||||
|
||||
if ($numberOfLinesToClear > 0) {
|
||||
// move cursor up n lines
|
||||
parent::doWrite(sprintf("\x1b[%dA", $numberOfLinesToClear), false);
|
||||
// erase to end of screen
|
||||
parent::doWrite("\x1b[0J", false);
|
||||
}
|
||||
|
||||
return implode('', array_reverse($erasedContent));
|
||||
}
|
||||
|
||||
private function getDisplayLength(string $text): int
|
||||
{
|
||||
return Helper::width(Helper::removeDecoration($this->getFormatter(), str_replace("\t", ' ', $text)));
|
||||
}
|
||||
}
|
||||
28
vendor/symfony/console/Output/NullOutput.php
vendored
28
vendor/symfony/console/Output/NullOutput.php
vendored
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Console\Output;
|
||||
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Formatter\NullOutputFormatter;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
|
||||
/**
|
||||
@@ -24,6 +24,8 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
*/
|
||||
class NullOutput implements OutputInterface
|
||||
{
|
||||
private $formatter;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -35,16 +37,16 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormatter()
|
||||
public function getFormatter(): OutputFormatterInterface
|
||||
{
|
||||
// to comply with the interface we must return a OutputFormatterInterface
|
||||
return new OutputFormatter();
|
||||
return $this->formatter ??= new NullOutputFormatter();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDecorated($decorated)
|
||||
public function setDecorated(bool $decorated)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -52,7 +54,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDecorated()
|
||||
public function isDecorated(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -60,7 +62,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setVerbosity($level)
|
||||
public function setVerbosity(int $level)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -68,7 +70,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVerbosity()
|
||||
public function getVerbosity(): int
|
||||
{
|
||||
return self::VERBOSITY_QUIET;
|
||||
}
|
||||
@@ -76,7 +78,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isQuiet()
|
||||
public function isQuiet(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -84,7 +86,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVerbose()
|
||||
public function isVerbose(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -92,7 +94,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVeryVerbose()
|
||||
public function isVeryVerbose(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -100,7 +102,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDebug()
|
||||
public function isDebug(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -108,7 +110,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function writeln($messages, $options = self::OUTPUT_NORMAL)
|
||||
public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -116,7 +118,7 @@ class NullOutput implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
|
||||
public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
49
vendor/symfony/console/Output/Output.php
vendored
49
vendor/symfony/console/Output/Output.php
vendored
@@ -11,8 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Console\Output;
|
||||
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
|
||||
/**
|
||||
* Base class for output classes.
|
||||
@@ -29,20 +29,18 @@ use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
*/
|
||||
abstract class Output implements OutputInterface
|
||||
{
|
||||
private $verbosity;
|
||||
private int $verbosity;
|
||||
private $formatter;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
|
||||
* @param int|null $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
|
||||
* @param bool $decorated Whether to decorate messages
|
||||
* @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
|
||||
*/
|
||||
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
|
||||
public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null)
|
||||
{
|
||||
$this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
|
||||
$this->formatter = $formatter ?: new OutputFormatter();
|
||||
$this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL;
|
||||
$this->formatter = $formatter ?? new OutputFormatter();
|
||||
$this->formatter->setDecorated($decorated);
|
||||
}
|
||||
|
||||
@@ -57,7 +55,7 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormatter()
|
||||
public function getFormatter(): OutputFormatterInterface
|
||||
{
|
||||
return $this->formatter;
|
||||
}
|
||||
@@ -65,7 +63,7 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDecorated($decorated)
|
||||
public function setDecorated(bool $decorated)
|
||||
{
|
||||
$this->formatter->setDecorated($decorated);
|
||||
}
|
||||
@@ -73,7 +71,7 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDecorated()
|
||||
public function isDecorated(): bool
|
||||
{
|
||||
return $this->formatter->isDecorated();
|
||||
}
|
||||
@@ -81,15 +79,15 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setVerbosity($level)
|
||||
public function setVerbosity(int $level)
|
||||
{
|
||||
$this->verbosity = (int) $level;
|
||||
$this->verbosity = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVerbosity()
|
||||
public function getVerbosity(): int
|
||||
{
|
||||
return $this->verbosity;
|
||||
}
|
||||
@@ -97,7 +95,7 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isQuiet()
|
||||
public function isQuiet(): bool
|
||||
{
|
||||
return self::VERBOSITY_QUIET === $this->verbosity;
|
||||
}
|
||||
@@ -105,7 +103,7 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVerbose()
|
||||
public function isVerbose(): bool
|
||||
{
|
||||
return self::VERBOSITY_VERBOSE <= $this->verbosity;
|
||||
}
|
||||
@@ -113,7 +111,7 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVeryVerbose()
|
||||
public function isVeryVerbose(): bool
|
||||
{
|
||||
return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
|
||||
}
|
||||
@@ -121,7 +119,7 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDebug()
|
||||
public function isDebug(): bool
|
||||
{
|
||||
return self::VERBOSITY_DEBUG <= $this->verbosity;
|
||||
}
|
||||
@@ -129,7 +127,7 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function writeln($messages, $options = self::OUTPUT_NORMAL)
|
||||
public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL)
|
||||
{
|
||||
$this->write($messages, true, $options);
|
||||
}
|
||||
@@ -137,9 +135,11 @@ abstract class Output implements OutputInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
|
||||
public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL)
|
||||
{
|
||||
$messages = (array) $messages;
|
||||
if (!is_iterable($messages)) {
|
||||
$messages = [$messages];
|
||||
}
|
||||
|
||||
$types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
|
||||
$type = $types & $options ?: self::OUTPUT_NORMAL;
|
||||
@@ -163,15 +163,12 @@ abstract class Output implements OutputInterface
|
||||
break;
|
||||
}
|
||||
|
||||
$this->doWrite($message, $newline);
|
||||
$this->doWrite($message ?? '', $newline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a message to the output.
|
||||
*
|
||||
* @param string $message A message to write to the output
|
||||
* @param bool $newline Whether to add a newline or not
|
||||
*/
|
||||
abstract protected function doWrite($message, $newline);
|
||||
abstract protected function doWrite(string $message, bool $newline);
|
||||
}
|
||||
|
||||
@@ -20,100 +20,75 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
*/
|
||||
interface OutputInterface
|
||||
{
|
||||
const VERBOSITY_QUIET = 16;
|
||||
const VERBOSITY_NORMAL = 32;
|
||||
const VERBOSITY_VERBOSE = 64;
|
||||
const VERBOSITY_VERY_VERBOSE = 128;
|
||||
const VERBOSITY_DEBUG = 256;
|
||||
public const VERBOSITY_QUIET = 16;
|
||||
public const VERBOSITY_NORMAL = 32;
|
||||
public const VERBOSITY_VERBOSE = 64;
|
||||
public const VERBOSITY_VERY_VERBOSE = 128;
|
||||
public const VERBOSITY_DEBUG = 256;
|
||||
|
||||
const OUTPUT_NORMAL = 1;
|
||||
const OUTPUT_RAW = 2;
|
||||
const OUTPUT_PLAIN = 4;
|
||||
public const OUTPUT_NORMAL = 1;
|
||||
public const OUTPUT_RAW = 2;
|
||||
public const OUTPUT_PLAIN = 4;
|
||||
|
||||
/**
|
||||
* Writes a message to the output.
|
||||
*
|
||||
* @param string|array $messages The message as an array of lines or a single string
|
||||
* @param bool $newline Whether to add a newline
|
||||
* @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
|
||||
* @param $newline Whether to add a newline
|
||||
* @param $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
|
||||
*/
|
||||
public function write($messages, $newline = false, $options = 0);
|
||||
public function write(string|iterable $messages, bool $newline = false, int $options = 0);
|
||||
|
||||
/**
|
||||
* Writes a message to the output and adds a newline at the end.
|
||||
*
|
||||
* @param string|array $messages The message as an array of lines of a single string
|
||||
* @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
|
||||
* @param $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
|
||||
*/
|
||||
public function writeln($messages, $options = 0);
|
||||
public function writeln(string|iterable $messages, int $options = 0);
|
||||
|
||||
/**
|
||||
* Sets the verbosity of the output.
|
||||
*
|
||||
* @param int $level The level of verbosity (one of the VERBOSITY constants)
|
||||
*/
|
||||
public function setVerbosity($level);
|
||||
public function setVerbosity(int $level);
|
||||
|
||||
/**
|
||||
* Gets the current verbosity of the output.
|
||||
*
|
||||
* @return int The current level of verbosity (one of the VERBOSITY constants)
|
||||
*/
|
||||
public function getVerbosity();
|
||||
public function getVerbosity(): int;
|
||||
|
||||
/**
|
||||
* Returns whether verbosity is quiet (-q).
|
||||
*
|
||||
* @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise
|
||||
*/
|
||||
public function isQuiet();
|
||||
public function isQuiet(): bool;
|
||||
|
||||
/**
|
||||
* Returns whether verbosity is verbose (-v).
|
||||
*
|
||||
* @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise
|
||||
*/
|
||||
public function isVerbose();
|
||||
public function isVerbose(): bool;
|
||||
|
||||
/**
|
||||
* Returns whether verbosity is very verbose (-vv).
|
||||
*
|
||||
* @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise
|
||||
*/
|
||||
public function isVeryVerbose();
|
||||
public function isVeryVerbose(): bool;
|
||||
|
||||
/**
|
||||
* Returns whether verbosity is debug (-vvv).
|
||||
*
|
||||
* @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise
|
||||
*/
|
||||
public function isDebug();
|
||||
public function isDebug(): bool;
|
||||
|
||||
/**
|
||||
* Sets the decorated flag.
|
||||
*
|
||||
* @param bool $decorated Whether to decorate the messages
|
||||
*/
|
||||
public function setDecorated($decorated);
|
||||
public function setDecorated(bool $decorated);
|
||||
|
||||
/**
|
||||
* Gets the decorated flag.
|
||||
*
|
||||
* @return bool true if the output will decorate messages, false otherwise
|
||||
*/
|
||||
public function isDecorated();
|
||||
public function isDecorated(): bool;
|
||||
|
||||
/**
|
||||
* Sets output formatter.
|
||||
*
|
||||
* @param OutputFormatterInterface $formatter
|
||||
*/
|
||||
public function setFormatter(OutputFormatterInterface $formatter);
|
||||
|
||||
/**
|
||||
* Returns current output formatter instance.
|
||||
*
|
||||
* @return OutputFormatterInterface
|
||||
*/
|
||||
public function getFormatter();
|
||||
public function getFormatter(): OutputFormatterInterface;
|
||||
}
|
||||
|
||||
48
vendor/symfony/console/Output/StreamOutput.php
vendored
48
vendor/symfony/console/Output/StreamOutput.php
vendored
@@ -12,7 +12,6 @@
|
||||
namespace Symfony\Component\Console\Output;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
|
||||
/**
|
||||
@@ -20,11 +19,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>
|
||||
*/
|
||||
@@ -33,8 +32,6 @@ class StreamOutput extends Output
|
||||
private $stream;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param resource $stream A stream resource
|
||||
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
|
||||
* @param bool|null $decorated Whether to decorate messages (null for auto-guessing)
|
||||
@@ -42,9 +39,9 @@ class StreamOutput extends Output
|
||||
*
|
||||
* @throws InvalidArgumentException When first argument is not a real stream
|
||||
*/
|
||||
public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
|
||||
public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null)
|
||||
{
|
||||
if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
|
||||
if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
|
||||
throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
|
||||
}
|
||||
|
||||
@@ -60,7 +57,7 @@ class StreamOutput extends Output
|
||||
/**
|
||||
* Gets the stream attached to this StreamOutput instance.
|
||||
*
|
||||
* @return resource A stream resource
|
||||
* @return resource
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
@@ -70,13 +67,14 @@ class StreamOutput extends Output
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doWrite($message, $newline)
|
||||
protected function doWrite(string $message, bool $newline)
|
||||
{
|
||||
if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
|
||||
// should never happen
|
||||
throw new RuntimeException('Unable to write output.');
|
||||
if ($newline) {
|
||||
$message .= \PHP_EOL;
|
||||
}
|
||||
|
||||
@fwrite($this->stream, $message);
|
||||
|
||||
fflush($this->stream);
|
||||
}
|
||||
|
||||
@@ -85,21 +83,33 @@ class StreamOutput extends Output
|
||||
*
|
||||
* Colorization is disabled if not supported by the stream:
|
||||
*
|
||||
* - Windows != 10.0.10586 without Ansicon, ConEmu or Mintty
|
||||
* - non tty consoles
|
||||
* This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo
|
||||
* terminals via named pipes, so we can only check the environment.
|
||||
*
|
||||
* Reference: Composer\XdebugHandler\Process::supportsColor
|
||||
* https://github.com/composer/xdebug-handler
|
||||
*
|
||||
* @return bool true if the stream supports colorization, false otherwise
|
||||
*/
|
||||
protected function hasColorSupport()
|
||||
protected function hasColorSupport(): bool
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
return
|
||||
'10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
|
||||
// Follow https://no-color.org/
|
||||
if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('Hyper' === getenv('TERM_PROGRAM')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\DIRECTORY_SEPARATOR === '\\') {
|
||||
return (\function_exists('sapi_windows_vt100_support')
|
||||
&& @sapi_windows_vt100_support($this->stream))
|
||||
|| false !== getenv('ANSICON')
|
||||
|| 'ON' === getenv('ConEmuANSI')
|
||||
|| 'xterm' === getenv('TERM');
|
||||
}
|
||||
|
||||
return function_exists('posix_isatty') && @posix_isatty($this->stream);
|
||||
return stream_isatty($this->stream);
|
||||
}
|
||||
}
|
||||
|
||||
61
vendor/symfony/console/Output/TrimmedBufferOutput.php
vendored
Normal file
61
vendor/symfony/console/Output/TrimmedBufferOutput.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?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\Output;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
|
||||
/**
|
||||
* A BufferedOutput that keeps only the last N chars.
|
||||
*
|
||||
* @author Jérémy Derussé <jeremy@derusse.com>
|
||||
*/
|
||||
class TrimmedBufferOutput extends Output
|
||||
{
|
||||
private int $maxLength;
|
||||
private string $buffer = '';
|
||||
|
||||
public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null)
|
||||
{
|
||||
if ($maxLength <= 0) {
|
||||
throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength));
|
||||
}
|
||||
|
||||
parent::__construct($verbosity, $decorated, $formatter);
|
||||
$this->maxLength = $maxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties buffer and returns its content.
|
||||
*/
|
||||
public function fetch(): string
|
||||
{
|
||||
$content = $this->buffer;
|
||||
$this->buffer = '';
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doWrite(string $message, bool $newline)
|
||||
{
|
||||
$this->buffer .= $message;
|
||||
|
||||
if ($newline) {
|
||||
$this->buffer .= \PHP_EOL;
|
||||
}
|
||||
|
||||
$this->buffer = substr($this->buffer, 0 - $this->maxLength);
|
||||
}
|
||||
}
|
||||
@@ -20,19 +20,17 @@ use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
*/
|
||||
class ChoiceQuestion extends Question
|
||||
{
|
||||
private $choices;
|
||||
private $multiselect = false;
|
||||
private $prompt = ' > ';
|
||||
private $errorMessage = 'Value "%s" is invalid';
|
||||
private array $choices;
|
||||
private bool $multiselect = false;
|
||||
private string $prompt = ' > ';
|
||||
private string $errorMessage = 'Value "%s" is invalid';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $question The question to ask to the user
|
||||
* @param array $choices The list of available choices
|
||||
* @param mixed $default The default answer to return
|
||||
*/
|
||||
public function __construct($question, array $choices, $default = null)
|
||||
public function __construct(string $question, array $choices, mixed $default = null)
|
||||
{
|
||||
if (!$choices) {
|
||||
throw new \LogicException('Choice question must have at least 1 choice available.');
|
||||
@@ -47,10 +45,8 @@ class ChoiceQuestion extends Question
|
||||
|
||||
/**
|
||||
* Returns available choices.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getChoices()
|
||||
public function getChoices(): array
|
||||
{
|
||||
return $this->choices;
|
||||
}
|
||||
@@ -60,11 +56,9 @@ class ChoiceQuestion extends Question
|
||||
*
|
||||
* When multiselect is set to true, multiple choices can be answered.
|
||||
*
|
||||
* @param bool $multiselect
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMultiselect($multiselect)
|
||||
public function setMultiselect(bool $multiselect): static
|
||||
{
|
||||
$this->multiselect = $multiselect;
|
||||
$this->setValidator($this->getDefaultValidator());
|
||||
@@ -74,20 +68,16 @@ class ChoiceQuestion extends Question
|
||||
|
||||
/**
|
||||
* Returns whether the choices are multiselect.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMultiselect()
|
||||
public function isMultiselect(): bool
|
||||
{
|
||||
return $this->multiselect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prompt for choices.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPrompt()
|
||||
public function getPrompt(): string
|
||||
{
|
||||
return $this->prompt;
|
||||
}
|
||||
@@ -95,11 +85,9 @@ class ChoiceQuestion extends Question
|
||||
/**
|
||||
* Sets the prompt for choices.
|
||||
*
|
||||
* @param string $prompt
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPrompt($prompt)
|
||||
public function setPrompt(string $prompt): static
|
||||
{
|
||||
$this->prompt = $prompt;
|
||||
|
||||
@@ -111,11 +99,9 @@ class ChoiceQuestion extends Question
|
||||
*
|
||||
* The error message has a string placeholder (%s) for the invalid value.
|
||||
*
|
||||
* @param string $errorMessage
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setErrorMessage($errorMessage)
|
||||
public function setErrorMessage(string $errorMessage): static
|
||||
{
|
||||
$this->errorMessage = $errorMessage;
|
||||
$this->setValidator($this->getDefaultValidator());
|
||||
@@ -123,12 +109,7 @@ class ChoiceQuestion extends Question
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default answer validator.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
private function getDefaultValidator()
|
||||
private function getDefaultValidator(): callable
|
||||
{
|
||||
$choices = $this->choices;
|
||||
$errorMessage = $this->errorMessage;
|
||||
@@ -136,30 +117,34 @@ class ChoiceQuestion extends Question
|
||||
$isAssoc = $this->isAssoc($choices);
|
||||
|
||||
return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
|
||||
// Collapse all spaces.
|
||||
$selectedChoices = str_replace(' ', '', $selected);
|
||||
|
||||
if ($multiselect) {
|
||||
// Check for a separated comma values
|
||||
if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
|
||||
if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) {
|
||||
throw new InvalidArgumentException(sprintf($errorMessage, $selected));
|
||||
}
|
||||
$selectedChoices = explode(',', $selectedChoices);
|
||||
|
||||
$selectedChoices = explode(',', (string) $selected);
|
||||
} else {
|
||||
$selectedChoices = array($selected);
|
||||
$selectedChoices = [$selected];
|
||||
}
|
||||
|
||||
$multiselectChoices = array();
|
||||
if ($this->isTrimmable()) {
|
||||
foreach ($selectedChoices as $k => $v) {
|
||||
$selectedChoices[$k] = trim((string) $v);
|
||||
}
|
||||
}
|
||||
|
||||
$multiselectChoices = [];
|
||||
foreach ($selectedChoices as $value) {
|
||||
$results = array();
|
||||
$results = [];
|
||||
foreach ($choices as $key => $choice) {
|
||||
if ($choice === $value) {
|
||||
$results[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($results) > 1) {
|
||||
throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
|
||||
if (\count($results) > 1) {
|
||||
throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results)));
|
||||
}
|
||||
|
||||
$result = array_search($value, $choices);
|
||||
@@ -178,7 +163,8 @@ class ChoiceQuestion extends Question
|
||||
throw new InvalidArgumentException(sprintf($errorMessage, $value));
|
||||
}
|
||||
|
||||
$multiselectChoices[] = (string) $result;
|
||||
// For associative choices, consistently return the key as string:
|
||||
$multiselectChoices[] = $isAssoc ? (string) $result : $result;
|
||||
}
|
||||
|
||||
if ($multiselect) {
|
||||
|
||||
@@ -18,18 +18,16 @@ namespace Symfony\Component\Console\Question;
|
||||
*/
|
||||
class ConfirmationQuestion extends Question
|
||||
{
|
||||
private $trueAnswerRegex;
|
||||
private string $trueAnswerRegex;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $question The question to ask to the user
|
||||
* @param bool $default The default answer to return, true or false
|
||||
* @param string $trueAnswerRegex A regex to match the "yes" answer
|
||||
*/
|
||||
public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
|
||||
public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y/i')
|
||||
{
|
||||
parent::__construct($question, (bool) $default);
|
||||
parent::__construct($question, $default);
|
||||
|
||||
$this->trueAnswerRegex = $trueAnswerRegex;
|
||||
$this->setNormalizer($this->getDefaultNormalizer());
|
||||
@@ -37,16 +35,14 @@ class ConfirmationQuestion extends Question
|
||||
|
||||
/**
|
||||
* Returns the default answer normalizer.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
private function getDefaultNormalizer()
|
||||
private function getDefaultNormalizer(): callable
|
||||
{
|
||||
$default = $this->getDefault();
|
||||
$regex = $this->trueAnswerRegex;
|
||||
|
||||
return function ($answer) use ($default, $regex) {
|
||||
if (is_bool($answer)) {
|
||||
if (\is_bool($answer)) {
|
||||
return $answer;
|
||||
}
|
||||
|
||||
@@ -55,7 +51,7 @@ class ConfirmationQuestion extends Question
|
||||
return $answer && $answerIsTrue;
|
||||
}
|
||||
|
||||
return !$answer || $answerIsTrue;
|
||||
return '' === $answer || $answerIsTrue;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
185
vendor/symfony/console/Question/Question.php
vendored
185
vendor/symfony/console/Question/Question.php
vendored
@@ -21,22 +21,22 @@ use Symfony\Component\Console\Exception\LogicException;
|
||||
*/
|
||||
class Question
|
||||
{
|
||||
private $question;
|
||||
private $attempts;
|
||||
private $hidden = false;
|
||||
private $hiddenFallback = true;
|
||||
private $autocompleterValues;
|
||||
private $validator;
|
||||
private $default;
|
||||
private $normalizer;
|
||||
private string $question;
|
||||
private ?int $attempts = null;
|
||||
private bool $hidden = false;
|
||||
private bool $hiddenFallback = true;
|
||||
private ?\Closure $autocompleterCallback = null;
|
||||
private ?\Closure $validator = null;
|
||||
private string|int|bool|null|float $default;
|
||||
private ?\Closure $normalizer = null;
|
||||
private bool $trimmable = true;
|
||||
private bool $multiline = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $question The question to ask to the user
|
||||
* @param mixed $default The default answer to return if the user enters nothing
|
||||
* @param string $question The question to ask to the user
|
||||
* @param string|bool|int|float|null $default The default answer to return if the user enters nothing
|
||||
*/
|
||||
public function __construct($question, $default = null)
|
||||
public function __construct(string $question, string|bool|int|float $default = null)
|
||||
{
|
||||
$this->question = $question;
|
||||
$this->default = $default;
|
||||
@@ -44,30 +44,44 @@ class Question
|
||||
|
||||
/**
|
||||
* Returns the question.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQuestion()
|
||||
public function getQuestion(): string
|
||||
{
|
||||
return $this->question;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default answer.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDefault()
|
||||
public function getDefault(): string|bool|int|float|null
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user response must be hidden.
|
||||
*
|
||||
* @return bool
|
||||
* Returns whether the user response accepts newline characters.
|
||||
*/
|
||||
public function isHidden()
|
||||
public function isMultiline(): bool
|
||||
{
|
||||
return $this->multiline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the user response should accept newline characters.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMultiline(bool $multiline): static
|
||||
{
|
||||
$this->multiline = $multiline;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user response must be hidden.
|
||||
*/
|
||||
public function isHidden(): bool
|
||||
{
|
||||
return $this->hidden;
|
||||
}
|
||||
@@ -75,84 +89,100 @@ class Question
|
||||
/**
|
||||
* Sets whether the user response must be hidden or not.
|
||||
*
|
||||
* @param bool $hidden
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws LogicException In case the autocompleter is also used
|
||||
*/
|
||||
public function setHidden($hidden)
|
||||
public function setHidden(bool $hidden): static
|
||||
{
|
||||
if ($this->autocompleterValues) {
|
||||
if ($this->autocompleterCallback) {
|
||||
throw new LogicException('A hidden question cannot use the autocompleter.');
|
||||
}
|
||||
|
||||
$this->hidden = (bool) $hidden;
|
||||
$this->hidden = $hidden;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case the response can not be hidden, whether to fallback on non-hidden question or not.
|
||||
*
|
||||
* @return bool
|
||||
* In case the response cannot be hidden, whether to fallback on non-hidden question or not.
|
||||
*/
|
||||
public function isHiddenFallback()
|
||||
public function isHiddenFallback(): bool
|
||||
{
|
||||
return $this->hiddenFallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to fallback on non-hidden question if the response can not be hidden.
|
||||
*
|
||||
* @param bool $fallback
|
||||
* Sets whether to fallback on non-hidden question if the response cannot be hidden.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHiddenFallback($fallback)
|
||||
public function setHiddenFallback(bool $fallback): static
|
||||
{
|
||||
$this->hiddenFallback = (bool) $fallback;
|
||||
$this->hiddenFallback = $fallback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets values for the autocompleter.
|
||||
*
|
||||
* @return null|array|\Traversable
|
||||
*/
|
||||
public function getAutocompleterValues()
|
||||
public function getAutocompleterValues(): ?iterable
|
||||
{
|
||||
return $this->autocompleterValues;
|
||||
$callback = $this->getAutocompleterCallback();
|
||||
|
||||
return $callback ? $callback('') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets values for the autocompleter.
|
||||
*
|
||||
* @param null|array|\Traversable $values
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function setAutocompleterValues($values)
|
||||
public function setAutocompleterValues(?iterable $values): static
|
||||
{
|
||||
if (is_array($values)) {
|
||||
if (\is_array($values)) {
|
||||
$values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
|
||||
|
||||
$callback = static function () use ($values) {
|
||||
return $values;
|
||||
};
|
||||
} elseif ($values instanceof \Traversable) {
|
||||
$valueCache = null;
|
||||
$callback = static function () use ($values, &$valueCache) {
|
||||
return $valueCache ?? $valueCache = iterator_to_array($values, false);
|
||||
};
|
||||
} else {
|
||||
$callback = null;
|
||||
}
|
||||
|
||||
if (null !== $values && !is_array($values)) {
|
||||
if (!$values instanceof \Traversable || !$values instanceof \Countable) {
|
||||
throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
|
||||
}
|
||||
}
|
||||
return $this->setAutocompleterCallback($callback);
|
||||
}
|
||||
|
||||
if ($this->hidden) {
|
||||
/**
|
||||
* Gets the callback function used for the autocompleter.
|
||||
*/
|
||||
public function getAutocompleterCallback(): ?callable
|
||||
{
|
||||
return $this->autocompleterCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the callback function used for the autocompleter.
|
||||
*
|
||||
* The callback is passed the user input as argument and should return an iterable of corresponding suggestions.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutocompleterCallback(callable $callback = null): static
|
||||
{
|
||||
if ($this->hidden && null !== $callback) {
|
||||
throw new LogicException('A hidden question cannot use the autocompleter.');
|
||||
}
|
||||
|
||||
$this->autocompleterValues = $values;
|
||||
$this->autocompleterCallback = null === $callback || $callback instanceof \Closure ? $callback : \Closure::fromCallable($callback);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -160,23 +190,19 @@ class Question
|
||||
/**
|
||||
* Sets a validator for the question.
|
||||
*
|
||||
* @param null|callable $validator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setValidator(callable $validator = null)
|
||||
public function setValidator(callable $validator = null): static
|
||||
{
|
||||
$this->validator = $validator;
|
||||
$this->validator = null === $validator || $validator instanceof \Closure ? $validator : \Closure::fromCallable($validator);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the validator for the question.
|
||||
*
|
||||
* @return null|callable
|
||||
*/
|
||||
public function getValidator()
|
||||
public function getValidator(): ?callable
|
||||
{
|
||||
return $this->validator;
|
||||
}
|
||||
@@ -186,13 +212,11 @@ class Question
|
||||
*
|
||||
* Null means an unlimited number of attempts.
|
||||
*
|
||||
* @param null|int $attempts
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException In case the number of attempts is invalid.
|
||||
* @throws InvalidArgumentException in case the number of attempts is invalid
|
||||
*/
|
||||
public function setMaxAttempts($attempts)
|
||||
public function setMaxAttempts(?int $attempts): static
|
||||
{
|
||||
if (null !== $attempts && $attempts < 1) {
|
||||
throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
|
||||
@@ -207,10 +231,8 @@ class Question
|
||||
* Gets the maximum number of attempts.
|
||||
*
|
||||
* Null means an unlimited number of attempts.
|
||||
*
|
||||
* @return null|int
|
||||
*/
|
||||
public function getMaxAttempts()
|
||||
public function getMaxAttempts(): ?int
|
||||
{
|
||||
return $this->attempts;
|
||||
}
|
||||
@@ -220,13 +242,11 @@ class Question
|
||||
*
|
||||
* The normalizer can be a callable (a string), a closure or a class implementing __invoke.
|
||||
*
|
||||
* @param callable $normalizer
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setNormalizer(callable $normalizer)
|
||||
public function setNormalizer(callable $normalizer): static
|
||||
{
|
||||
$this->normalizer = $normalizer;
|
||||
$this->normalizer = $normalizer instanceof \Closure ? $normalizer : \Closure::fromCallable($normalizer);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -235,16 +255,29 @@ class Question
|
||||
* Gets the normalizer for the response.
|
||||
*
|
||||
* The normalizer can ba a callable (a string), a closure or a class implementing __invoke.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function getNormalizer()
|
||||
public function getNormalizer(): ?callable
|
||||
{
|
||||
return $this->normalizer;
|
||||
}
|
||||
|
||||
protected function isAssoc($array)
|
||||
protected function isAssoc(array $array)
|
||||
{
|
||||
return (bool) count(array_filter(array_keys($array), 'is_string'));
|
||||
return (bool) \count(array_filter(array_keys($array), 'is_string'));
|
||||
}
|
||||
|
||||
public function isTrimmable(): bool
|
||||
{
|
||||
return $this->trimmable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setTrimmable(bool $trimmable): static
|
||||
{
|
||||
$this->trimmable = $trimmable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
26
vendor/symfony/console/README.md
vendored
26
vendor/symfony/console/README.md
vendored
@@ -4,17 +4,33 @@ Console Component
|
||||
The Console component eases the creation of beautiful and testable command line
|
||||
interfaces.
|
||||
|
||||
Sponsor
|
||||
-------
|
||||
|
||||
The Console component for Symfony 5.4/6.0 is [backed][1] by [Les-Tilleuls.coop][2].
|
||||
|
||||
Les-Tilleuls.coop is a team of 50+ Symfony experts who can help you design, develop and
|
||||
fix your projects. We provide a wide range of professional services including development,
|
||||
consulting, coaching, training and audits. We also are highly skilled in JS, Go and DevOps.
|
||||
We are a worker cooperative!
|
||||
|
||||
Help Symfony by [sponsoring][3] its development!
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/console/index.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
||||
* [Documentation](https://symfony.com/doc/current/components/console.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
`Resources/bin/hiddeninput.exe` is a third party binary provided within this
|
||||
component. Find sources and license at https://github.com/Seldaek/hidden-input.
|
||||
|
||||
[1]: https://symfony.com/backers
|
||||
[2]: https://les-tilleuls.coop
|
||||
[3]: https://symfony.com/sponsor
|
||||
|
||||
84
vendor/symfony/console/Resources/completion.bash
vendored
Normal file
84
vendor/symfony/console/Resources/completion.bash
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
# This file is part of the Symfony package.
|
||||
#
|
||||
# (c) Fabien Potencier <fabien@symfony.com>
|
||||
#
|
||||
# For the full copyright and license information, please view
|
||||
# https://symfony.com/doc/current/contributing/code/license.html
|
||||
|
||||
_sf_{{ COMMAND_NAME }}() {
|
||||
# Use newline as only separator to allow space in completion values
|
||||
IFS=$'\n'
|
||||
local sf_cmd="${COMP_WORDS[0]}"
|
||||
|
||||
# for an alias, get the real script behind it
|
||||
sf_cmd_type=$(type -t $sf_cmd)
|
||||
if [[ $sf_cmd_type == "alias" ]]; then
|
||||
sf_cmd=$(alias $sf_cmd | sed -E "s/alias $sf_cmd='(.*)'/\1/")
|
||||
elif [[ $sf_cmd_type == "file" ]]; then
|
||||
sf_cmd=$(type -p $sf_cmd)
|
||||
fi
|
||||
|
||||
if [[ $sf_cmd_type != "function" && ! -x $sf_cmd ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local cur prev words cword
|
||||
_get_comp_words_by_ref -n := cur prev words cword
|
||||
|
||||
local completecmd=("$sf_cmd" "_complete" "--no-interaction" "-sbash" "-c$cword" "-S{{ VERSION }}")
|
||||
for w in ${words[@]}; do
|
||||
w=$(printf -- '%b' "$w")
|
||||
# remove quotes from typed values
|
||||
quote="${w:0:1}"
|
||||
if [ "$quote" == \' ]; then
|
||||
w="${w%\'}"
|
||||
w="${w#\'}"
|
||||
elif [ "$quote" == \" ]; then
|
||||
w="${w%\"}"
|
||||
w="${w#\"}"
|
||||
fi
|
||||
# empty values are ignored
|
||||
if [ ! -z "$w" ]; then
|
||||
completecmd+=("-i$w")
|
||||
fi
|
||||
done
|
||||
|
||||
local sfcomplete
|
||||
if sfcomplete=$(${completecmd[@]} 2>&1); then
|
||||
local quote suggestions
|
||||
quote=${cur:0:1}
|
||||
|
||||
# Use single quotes by default if suggestions contains backslash (FQCN)
|
||||
if [ "$quote" == '' ] && [[ "$sfcomplete" =~ \\ ]]; then
|
||||
quote=\'
|
||||
fi
|
||||
|
||||
if [ "$quote" == \' ]; then
|
||||
# single quotes: no additional escaping (does not accept ' in values)
|
||||
suggestions=$(for s in $sfcomplete; do printf $'%q%q%q\n' "$quote" "$s" "$quote"; done)
|
||||
elif [ "$quote" == \" ]; then
|
||||
# double quotes: double escaping for \ $ ` "
|
||||
suggestions=$(for s in $sfcomplete; do
|
||||
s=${s//\\/\\\\}
|
||||
s=${s//\$/\\\$}
|
||||
s=${s//\`/\\\`}
|
||||
s=${s//\"/\\\"}
|
||||
printf $'%q%q%q\n' "$quote" "$s" "$quote";
|
||||
done)
|
||||
else
|
||||
# no quotes: double escaping
|
||||
suggestions=$(for s in $sfcomplete; do printf $'%q\n' $(printf '%q' "$s"); done)
|
||||
fi
|
||||
COMPREPLY=($(IFS=$'\n' compgen -W "$suggestions" -- $(printf -- "%q" "$cur")))
|
||||
__ltrim_colon_completions "$cur"
|
||||
else
|
||||
if [[ "$sfcomplete" != *"Command \"_complete\" is not defined."* ]]; then
|
||||
>&2 echo
|
||||
>&2 echo $sfcomplete
|
||||
fi
|
||||
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
complete -F _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }}
|
||||
65
vendor/symfony/console/SignalRegistry/SignalRegistry.php
vendored
Normal file
65
vendor/symfony/console/SignalRegistry/SignalRegistry.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?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\SignalRegistry;
|
||||
|
||||
final class SignalRegistry
|
||||
{
|
||||
private array $signalHandlers = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (\function_exists('pcntl_async_signals')) {
|
||||
pcntl_async_signals(true);
|
||||
}
|
||||
}
|
||||
|
||||
public function register(int $signal, callable $signalHandler): void
|
||||
{
|
||||
if (!isset($this->signalHandlers[$signal])) {
|
||||
$previousCallback = pcntl_signal_get_handler($signal);
|
||||
|
||||
if (\is_callable($previousCallback)) {
|
||||
$this->signalHandlers[$signal][] = $previousCallback;
|
||||
}
|
||||
}
|
||||
|
||||
$this->signalHandlers[$signal][] = $signalHandler;
|
||||
|
||||
pcntl_signal($signal, [$this, 'handle']);
|
||||
}
|
||||
|
||||
public static function isSupported(): bool
|
||||
{
|
||||
if (!\function_exists('pcntl_signal')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (\in_array('pcntl_signal', explode(',', \ini_get('disable_functions')))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function handle(int $signal): void
|
||||
{
|
||||
$count = \count($this->signalHandlers[$signal]);
|
||||
|
||||
foreach ($this->signalHandlers[$signal] as $i => $signalHandler) {
|
||||
$hasNext = $i !== $count - 1;
|
||||
$signalHandler($signal, $hasNext);
|
||||
}
|
||||
}
|
||||
}
|
||||
72
vendor/symfony/console/SingleCommandApplication.php
vendored
Normal file
72
vendor/symfony/console/SingleCommandApplication.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class SingleCommandApplication extends Command
|
||||
{
|
||||
private string $version = 'UNKNOWN';
|
||||
private bool $autoExit = true;
|
||||
private bool $running = false;
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setVersion(string $version): static
|
||||
{
|
||||
$this->version = $version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @final
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutoExit(bool $autoExit): static
|
||||
{
|
||||
$this->autoExit = $autoExit;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function run(InputInterface $input = null, OutputInterface $output = null): int
|
||||
{
|
||||
if ($this->running) {
|
||||
return parent::run($input, $output);
|
||||
}
|
||||
|
||||
// We use the command name as the application name
|
||||
$application = new Application($this->getName() ?: 'UNKNOWN', $this->version);
|
||||
$application->setAutoExit($this->autoExit);
|
||||
// Fix the usage of the command displayed with "--help"
|
||||
$this->setName($_SERVER['argv'][0]);
|
||||
$application->add($this);
|
||||
$application->setDefaultCommand($this->getName(), true);
|
||||
|
||||
$this->running = true;
|
||||
try {
|
||||
$ret = $application->run($input, $output);
|
||||
} finally {
|
||||
$this->running = false;
|
||||
}
|
||||
|
||||
return $ret ?? 1;
|
||||
}
|
||||
}
|
||||
38
vendor/symfony/console/Style/OutputStyle.php
vendored
38
vendor/symfony/console/Style/OutputStyle.php
vendored
@@ -13,8 +13,8 @@ namespace Symfony\Component\Console\Style;
|
||||
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Decorates output to add console style guide helpers.
|
||||
@@ -25,9 +25,6 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
{
|
||||
private $output;
|
||||
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
*/
|
||||
public function __construct(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
@@ -36,17 +33,12 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function newLine($count = 1)
|
||||
public function newLine(int $count = 1)
|
||||
{
|
||||
$this->output->write(str_repeat(PHP_EOL, $count));
|
||||
$this->output->write(str_repeat(\PHP_EOL, $count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $max
|
||||
*
|
||||
* @return ProgressBar
|
||||
*/
|
||||
public function createProgressBar($max = 0)
|
||||
public function createProgressBar(int $max = 0): ProgressBar
|
||||
{
|
||||
return new ProgressBar($this->output, $max);
|
||||
}
|
||||
@@ -54,7 +46,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
|
||||
public function write(string|iterable $messages, bool $newline = false, int $type = self::OUTPUT_NORMAL)
|
||||
{
|
||||
$this->output->write($messages, $newline, $type);
|
||||
}
|
||||
@@ -62,7 +54,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function writeln($messages, $type = self::OUTPUT_NORMAL)
|
||||
public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL)
|
||||
{
|
||||
$this->output->writeln($messages, $type);
|
||||
}
|
||||
@@ -70,7 +62,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setVerbosity($level)
|
||||
public function setVerbosity(int $level)
|
||||
{
|
||||
$this->output->setVerbosity($level);
|
||||
}
|
||||
@@ -78,7 +70,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVerbosity()
|
||||
public function getVerbosity(): int
|
||||
{
|
||||
return $this->output->getVerbosity();
|
||||
}
|
||||
@@ -86,7 +78,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDecorated($decorated)
|
||||
public function setDecorated(bool $decorated)
|
||||
{
|
||||
$this->output->setDecorated($decorated);
|
||||
}
|
||||
@@ -94,7 +86,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDecorated()
|
||||
public function isDecorated(): bool
|
||||
{
|
||||
return $this->output->isDecorated();
|
||||
}
|
||||
@@ -110,7 +102,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormatter()
|
||||
public function getFormatter(): OutputFormatterInterface
|
||||
{
|
||||
return $this->output->getFormatter();
|
||||
}
|
||||
@@ -118,7 +110,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isQuiet()
|
||||
public function isQuiet(): bool
|
||||
{
|
||||
return $this->output->isQuiet();
|
||||
}
|
||||
@@ -126,7 +118,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVerbose()
|
||||
public function isVerbose(): bool
|
||||
{
|
||||
return $this->output->isVerbose();
|
||||
}
|
||||
@@ -134,7 +126,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVeryVerbose()
|
||||
public function isVeryVerbose(): bool
|
||||
{
|
||||
return $this->output->isVeryVerbose();
|
||||
}
|
||||
@@ -142,7 +134,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDebug()
|
||||
public function isDebug(): bool
|
||||
{
|
||||
return $this->output->isDebug();
|
||||
}
|
||||
|
||||
79
vendor/symfony/console/Style/StyleInterface.php
vendored
79
vendor/symfony/console/Style/StyleInterface.php
vendored
@@ -20,137 +20,88 @@ interface StyleInterface
|
||||
{
|
||||
/**
|
||||
* Formats a command title.
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function title($message);
|
||||
public function title(string $message);
|
||||
|
||||
/**
|
||||
* Formats a section title.
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function section($message);
|
||||
public function section(string $message);
|
||||
|
||||
/**
|
||||
* Formats a list.
|
||||
*
|
||||
* @param array $elements
|
||||
*/
|
||||
public function listing(array $elements);
|
||||
|
||||
/**
|
||||
* Formats informational text.
|
||||
*
|
||||
* @param string|array $message
|
||||
*/
|
||||
public function text($message);
|
||||
public function text(string|array $message);
|
||||
|
||||
/**
|
||||
* Formats a success result bar.
|
||||
*
|
||||
* @param string|array $message
|
||||
*/
|
||||
public function success($message);
|
||||
public function success(string|array $message);
|
||||
|
||||
/**
|
||||
* Formats an error result bar.
|
||||
*
|
||||
* @param string|array $message
|
||||
*/
|
||||
public function error($message);
|
||||
public function error(string|array $message);
|
||||
|
||||
/**
|
||||
* Formats an warning result bar.
|
||||
*
|
||||
* @param string|array $message
|
||||
*/
|
||||
public function warning($message);
|
||||
public function warning(string|array $message);
|
||||
|
||||
/**
|
||||
* Formats a note admonition.
|
||||
*
|
||||
* @param string|array $message
|
||||
*/
|
||||
public function note($message);
|
||||
public function note(string|array $message);
|
||||
|
||||
/**
|
||||
* Formats a caution admonition.
|
||||
*
|
||||
* @param string|array $message
|
||||
*/
|
||||
public function caution($message);
|
||||
public function caution(string|array $message);
|
||||
|
||||
/**
|
||||
* Formats a table.
|
||||
*
|
||||
* @param array $headers
|
||||
* @param array $rows
|
||||
*/
|
||||
public function table(array $headers, array $rows);
|
||||
|
||||
/**
|
||||
* Asks a question.
|
||||
*
|
||||
* @param string $question
|
||||
* @param string|null $default
|
||||
* @param callable|null $validator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ask($question, $default = null, $validator = null);
|
||||
public function ask(string $question, string $default = null, callable $validator = null): mixed;
|
||||
|
||||
/**
|
||||
* Asks a question with the user input hidden.
|
||||
*
|
||||
* @param string $question
|
||||
* @param callable|null $validator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function askHidden($question, $validator = null);
|
||||
public function askHidden(string $question, callable $validator = null): mixed;
|
||||
|
||||
/**
|
||||
* Asks for confirmation.
|
||||
*
|
||||
* @param string $question
|
||||
* @param bool $default
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function confirm($question, $default = true);
|
||||
public function confirm(string $question, bool $default = true): bool;
|
||||
|
||||
/**
|
||||
* Asks a choice question.
|
||||
*
|
||||
* @param string $question
|
||||
* @param array $choices
|
||||
* @param string|int|null $default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function choice($question, array $choices, $default = null);
|
||||
public function choice(string $question, array $choices, mixed $default = null): mixed;
|
||||
|
||||
/**
|
||||
* Add newline(s).
|
||||
*
|
||||
* @param int $count The number of newlines
|
||||
*/
|
||||
public function newLine($count = 1);
|
||||
public function newLine(int $count = 1);
|
||||
|
||||
/**
|
||||
* Starts the progress output.
|
||||
*
|
||||
* @param int $max Maximum steps (0 if unknown)
|
||||
*/
|
||||
public function progressStart($max = 0);
|
||||
public function progressStart(int $max = 0);
|
||||
|
||||
/**
|
||||
* Advances the progress output X steps.
|
||||
*
|
||||
* @param int $step Number of steps to advance
|
||||
*/
|
||||
public function progressAdvance($step = 1);
|
||||
public function progressAdvance(int $step = 1);
|
||||
|
||||
/**
|
||||
* Finishes the progress output.
|
||||
|
||||
267
vendor/symfony/console/Style/SymfonyStyle.php
vendored
267
vendor/symfony/console/Style/SymfonyStyle.php
vendored
@@ -11,15 +11,19 @@
|
||||
|
||||
namespace Symfony\Component\Console\Style;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Helper\Helper;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Helper\TableCell;
|
||||
use Symfony\Component\Console\Helper\TableSeparator;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\TrimmedBufferOutput;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
@@ -32,42 +36,32 @@ use Symfony\Component\Console\Terminal;
|
||||
*/
|
||||
class SymfonyStyle extends OutputStyle
|
||||
{
|
||||
const MAX_LINE_LENGTH = 120;
|
||||
public const MAX_LINE_LENGTH = 120;
|
||||
|
||||
private $input;
|
||||
private $output;
|
||||
private $questionHelper;
|
||||
private $progressBar;
|
||||
private $lineLength;
|
||||
private int $lineLength;
|
||||
private $bufferedOutput;
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*/
|
||||
public function __construct(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->input = $input;
|
||||
$this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
|
||||
$this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), false, clone $output->getFormatter());
|
||||
// Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
|
||||
$width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
|
||||
$this->lineLength = min($width - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
|
||||
$this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
|
||||
|
||||
parent::__construct($output);
|
||||
parent::__construct($this->output = $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a message as a block of text.
|
||||
*
|
||||
* @param string|array $messages The message to write in the block
|
||||
* @param string|null $type The block type (added in [] on first line)
|
||||
* @param string|null $style The style to apply to the whole block
|
||||
* @param string $prefix The prefix for the block
|
||||
* @param bool $padding Whether to add vertical padding
|
||||
* @param bool $escape Whether to escape the message
|
||||
*/
|
||||
public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = true)
|
||||
public function block(string|array $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true)
|
||||
{
|
||||
$messages = is_array($messages) ? array_values($messages) : array($messages);
|
||||
$messages = \is_array($messages) ? array_values($messages) : [$messages];
|
||||
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape));
|
||||
@@ -77,26 +71,26 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function title($message)
|
||||
public function title(string $message)
|
||||
{
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln(array(
|
||||
$this->writeln([
|
||||
sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
|
||||
sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
|
||||
));
|
||||
sprintf('<comment>%s</>', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))),
|
||||
]);
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function section($message)
|
||||
public function section(string $message)
|
||||
{
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln(array(
|
||||
$this->writeln([
|
||||
sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
|
||||
sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
|
||||
));
|
||||
sprintf('<comment>%s</>', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))),
|
||||
]);
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
@@ -117,11 +111,11 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function text($message)
|
||||
public function text(string|array $message)
|
||||
{
|
||||
$this->autoPrependText();
|
||||
|
||||
$messages = is_array($message) ? array_values($message) : array($message);
|
||||
$messages = \is_array($message) ? array_values($message) : [$message];
|
||||
foreach ($messages as $message) {
|
||||
$this->writeln(sprintf(' %s', $message));
|
||||
}
|
||||
@@ -129,10 +123,8 @@ class SymfonyStyle extends OutputStyle
|
||||
|
||||
/**
|
||||
* Formats a command comment.
|
||||
*
|
||||
* @param string|array $message
|
||||
*/
|
||||
public function comment($message)
|
||||
public function comment(string|array $message)
|
||||
{
|
||||
$this->block($message, null, null, '<fg=default;bg=default> // </>', false, false);
|
||||
}
|
||||
@@ -140,7 +132,7 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function success($message)
|
||||
public function success(string|array $message)
|
||||
{
|
||||
$this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
|
||||
}
|
||||
@@ -148,7 +140,7 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function error($message)
|
||||
public function error(string|array $message)
|
||||
{
|
||||
$this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
|
||||
}
|
||||
@@ -156,23 +148,31 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function warning($message)
|
||||
public function warning(string|array $message)
|
||||
{
|
||||
$this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
|
||||
$this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function note($message)
|
||||
public function note(string|array $message)
|
||||
{
|
||||
$this->block($message, 'NOTE', 'fg=yellow', ' ! ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an info message.
|
||||
*/
|
||||
public function info(string|array $message)
|
||||
{
|
||||
$this->block($message, 'INFO', 'fg=green', ' ', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function caution($message)
|
||||
public function caution(string|array $message)
|
||||
{
|
||||
$this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
|
||||
}
|
||||
@@ -182,22 +182,67 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function table(array $headers, array $rows)
|
||||
{
|
||||
$style = clone Table::getStyleDefinition('symfony-style-guide');
|
||||
$style->setCellHeaderFormat('<info>%s</info>');
|
||||
$this->createTable()
|
||||
->setHeaders($headers)
|
||||
->setRows($rows)
|
||||
->render()
|
||||
;
|
||||
|
||||
$table = new Table($this);
|
||||
$table->setHeaders($headers);
|
||||
$table->setRows($rows);
|
||||
$table->setStyle($style);
|
||||
|
||||
$table->render();
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a horizontal table.
|
||||
*/
|
||||
public function horizontalTable(array $headers, array $rows)
|
||||
{
|
||||
$this->createTable()
|
||||
->setHorizontal(true)
|
||||
->setHeaders($headers)
|
||||
->setRows($rows)
|
||||
->render()
|
||||
;
|
||||
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a list of key/value horizontally.
|
||||
*
|
||||
* Each row can be one of:
|
||||
* * 'A title'
|
||||
* * ['key' => 'value']
|
||||
* * new TableSeparator()
|
||||
*/
|
||||
public function definitionList(string|array|TableSeparator ...$list)
|
||||
{
|
||||
$headers = [];
|
||||
$row = [];
|
||||
foreach ($list as $value) {
|
||||
if ($value instanceof TableSeparator) {
|
||||
$headers[] = $value;
|
||||
$row[] = $value;
|
||||
continue;
|
||||
}
|
||||
if (\is_string($value)) {
|
||||
$headers[] = new TableCell($value, ['colspan' => 2]);
|
||||
$row[] = null;
|
||||
continue;
|
||||
}
|
||||
if (!\is_array($value)) {
|
||||
throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.');
|
||||
}
|
||||
$headers[] = key($value);
|
||||
$row[] = current($value);
|
||||
}
|
||||
|
||||
$this->horizontalTable($headers, [$row]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function ask($question, $default = null, $validator = null)
|
||||
public function ask(string $question, string $default = null, callable $validator = null): mixed
|
||||
{
|
||||
$question = new Question($question, $default);
|
||||
$question->setValidator($validator);
|
||||
@@ -208,7 +253,7 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function askHidden($question, $validator = null)
|
||||
public function askHidden(string $question, callable $validator = null): mixed
|
||||
{
|
||||
$question = new Question($question);
|
||||
|
||||
@@ -221,7 +266,7 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function confirm($question, $default = true)
|
||||
public function confirm(string $question, bool $default = true): bool
|
||||
{
|
||||
return $this->askQuestion(new ConfirmationQuestion($question, $default));
|
||||
}
|
||||
@@ -229,11 +274,11 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function choice($question, array $choices, $default = null)
|
||||
public function choice(string $question, array $choices, mixed $default = null): mixed
|
||||
{
|
||||
if (null !== $default) {
|
||||
$values = array_flip($choices);
|
||||
$default = $values[$default];
|
||||
$default = $values[$default] ?? $default;
|
||||
}
|
||||
|
||||
return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
|
||||
@@ -242,7 +287,7 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function progressStart($max = 0)
|
||||
public function progressStart(int $max = 0)
|
||||
{
|
||||
$this->progressBar = $this->createProgressBar($max);
|
||||
$this->progressBar->start();
|
||||
@@ -251,7 +296,7 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function progressAdvance($step = 1)
|
||||
public function progressAdvance(int $step = 1)
|
||||
{
|
||||
$this->getProgressBar()->advance($step);
|
||||
}
|
||||
@@ -263,17 +308,17 @@ class SymfonyStyle extends OutputStyle
|
||||
{
|
||||
$this->getProgressBar()->finish();
|
||||
$this->newLine(2);
|
||||
$this->progressBar = null;
|
||||
unset($this->progressBar);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createProgressBar($max = 0)
|
||||
public function createProgressBar(int $max = 0): ProgressBar
|
||||
{
|
||||
$progressBar = parent::createProgressBar($max);
|
||||
|
||||
if ('\\' !== DIRECTORY_SEPARATOR) {
|
||||
if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
|
||||
$progressBar->setEmptyBarCharacter('░'); // light shade character \u2591
|
||||
$progressBar->setProgressCharacter('');
|
||||
$progressBar->setBarCharacter('▓'); // dark shade character \u2593
|
||||
@@ -283,19 +328,22 @@ class SymfonyStyle extends OutputStyle
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Question $question
|
||||
*
|
||||
* @return string
|
||||
* @see ProgressBar::iterate()
|
||||
*/
|
||||
public function askQuestion(Question $question)
|
||||
public function progressIterate(iterable $iterable, int $max = null): iterable
|
||||
{
|
||||
yield from $this->createProgressBar()->iterate($iterable, $max);
|
||||
|
||||
$this->newLine(2);
|
||||
}
|
||||
|
||||
public function askQuestion(Question $question): mixed
|
||||
{
|
||||
if ($this->input->isInteractive()) {
|
||||
$this->autoPrependBlock();
|
||||
}
|
||||
|
||||
if (!$this->questionHelper) {
|
||||
$this->questionHelper = new SymfonyQuestionHelper();
|
||||
}
|
||||
$this->questionHelper ??= new SymfonyQuestionHelper();
|
||||
|
||||
$answer = $this->questionHelper->ask($this->input, $this, $question);
|
||||
|
||||
@@ -310,25 +358,37 @@ class SymfonyStyle extends OutputStyle
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function writeln($messages, $type = self::OUTPUT_NORMAL)
|
||||
public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL)
|
||||
{
|
||||
parent::writeln($messages, $type);
|
||||
$this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
|
||||
if (!is_iterable($messages)) {
|
||||
$messages = [$messages];
|
||||
}
|
||||
|
||||
foreach ($messages as $message) {
|
||||
parent::writeln($message, $type);
|
||||
$this->writeBuffer($message, true, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
|
||||
public function write(string|iterable $messages, bool $newline = false, int $type = self::OUTPUT_NORMAL)
|
||||
{
|
||||
parent::write($messages, $newline, $type);
|
||||
$this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
|
||||
if (!is_iterable($messages)) {
|
||||
$messages = [$messages];
|
||||
}
|
||||
|
||||
foreach ($messages as $message) {
|
||||
parent::write($message, $newline, $type);
|
||||
$this->writeBuffer($message, $newline, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function newLine($count = 1)
|
||||
public function newLine(int $count = 1)
|
||||
{
|
||||
parent::newLine($count);
|
||||
$this->bufferedOutput->write(str_repeat("\n", $count));
|
||||
@@ -336,64 +396,64 @@ class SymfonyStyle extends OutputStyle
|
||||
|
||||
/**
|
||||
* Returns a new instance which makes use of stderr if available.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function getErrorStyle()
|
||||
public function getErrorStyle(): self
|
||||
{
|
||||
return new self($this->input, $this->getErrorOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ProgressBar
|
||||
*/
|
||||
private function getProgressBar()
|
||||
public function createTable(): Table
|
||||
{
|
||||
if (!$this->progressBar) {
|
||||
throw new RuntimeException('The ProgressBar is not started.');
|
||||
}
|
||||
$output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output;
|
||||
$style = clone Table::getStyleDefinition('symfony-style-guide');
|
||||
$style->setCellHeaderFormat('<info>%s</info>');
|
||||
|
||||
return $this->progressBar;
|
||||
return (new Table($output))->setStyle($style);
|
||||
}
|
||||
|
||||
private function autoPrependBlock()
|
||||
private function getProgressBar(): ProgressBar
|
||||
{
|
||||
$chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
|
||||
return $this->progressBar
|
||||
?? throw new RuntimeException('The ProgressBar is not started.');
|
||||
}
|
||||
|
||||
private function autoPrependBlock(): void
|
||||
{
|
||||
$chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
|
||||
|
||||
if (!isset($chars[0])) {
|
||||
return $this->newLine(); //empty history, so we should start with a new line.
|
||||
$this->newLine(); // empty history, so we should start with a new line.
|
||||
|
||||
return;
|
||||
}
|
||||
//Prepend new line for each non LF chars (This means no blank line was output before)
|
||||
// Prepend new line for each non LF chars (This means no blank line was output before)
|
||||
$this->newLine(2 - substr_count($chars, "\n"));
|
||||
}
|
||||
|
||||
private function autoPrependText()
|
||||
private function autoPrependText(): void
|
||||
{
|
||||
$fetched = $this->bufferedOutput->fetch();
|
||||
//Prepend new line if last char isn't EOL:
|
||||
if ("\n" !== substr($fetched, -1)) {
|
||||
// Prepend new line if last char isn't EOL:
|
||||
if (!str_ends_with($fetched, "\n")) {
|
||||
$this->newLine();
|
||||
}
|
||||
}
|
||||
|
||||
private function reduceBuffer($messages)
|
||||
private function writeBuffer(string $message, bool $newLine, int $type): void
|
||||
{
|
||||
// We need to know if the two last chars are PHP_EOL
|
||||
// Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer
|
||||
return array_map(function ($value) {
|
||||
return substr($value, -4);
|
||||
}, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
|
||||
// We need to know if the last chars are PHP_EOL
|
||||
$this->bufferedOutput->write($message, $newLine, $type);
|
||||
}
|
||||
|
||||
private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
|
||||
private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array
|
||||
{
|
||||
$indentLength = 0;
|
||||
$prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
|
||||
$lines = array();
|
||||
$prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix));
|
||||
$lines = [];
|
||||
|
||||
if (null !== $type) {
|
||||
$type = sprintf('[%s] ', $type);
|
||||
$indentLength = strlen($type);
|
||||
$indentLength = \strlen($type);
|
||||
$lineIndentation = str_repeat(' ', $indentLength);
|
||||
}
|
||||
|
||||
@@ -403,9 +463,14 @@ class SymfonyStyle extends OutputStyle
|
||||
$message = OutputFormatter::escape($message);
|
||||
}
|
||||
|
||||
$lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
|
||||
$decorationLength = Helper::width($message) - Helper::width(Helper::removeDecoration($this->getFormatter(), $message));
|
||||
$messageLineLength = min($this->lineLength - $prefixLength - $indentLength + $decorationLength, $this->lineLength);
|
||||
$messageLines = explode(\PHP_EOL, wordwrap($message, $messageLineLength, \PHP_EOL, true));
|
||||
foreach ($messageLines as $messageLine) {
|
||||
$lines[] = $messageLine;
|
||||
}
|
||||
|
||||
if (count($messages) > 1 && $key < count($messages) - 1) {
|
||||
if (\count($messages) > 1 && $key < \count($messages) - 1) {
|
||||
$lines[] = '';
|
||||
}
|
||||
}
|
||||
@@ -423,7 +488,7 @@ class SymfonyStyle extends OutputStyle
|
||||
}
|
||||
|
||||
$line = $prefix.$line;
|
||||
$line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
|
||||
$line .= str_repeat(' ', max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0));
|
||||
|
||||
if ($style) {
|
||||
$line = sprintf('<%s>%s</>', $style, $line);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user